#! /bin/sh
# next line not seen by tcl upon reentry by exec \
DYLD_LIBRARY_PATH="$CSURF_LIBRARY_PATH" exec wish8.5 "$0" ${1+"$@"}
# previous inline env is required b/c Mac10.11+ won't pass DYLD_LIBRARY_PATH
# since exec replaces curr shell (vs. /usr/bin/env subshell) Mac PATH *is* seen
# csurf -h => err, but continues (not a valid wish flag), csurf --h => no err
# wish8.5 -- "$0" ${1+"$@"} fixes -h err but blocks opt wish args (e.g., -sync)

### HOWTO run csurf with a tcl interpreter for debug/inspect/hack
# source FreeSurfer.{c}sh
# wish8.5
# % source $env(CSURF_DIR)/bin/noarch/csurf

### HOWTO use wrappers.tcl functions (e.g., confirmalert <msg>)
# source FreeSurfer.{c}sh
# wish8.5
# % source $env(CSURF_DIR)/lib/tcl/wrappers.tcl

### HOWTO use tix functions
# wish8.5
# load libTix8.4.3.{so,dylib}
# tixComboBox .a
# pack .a

### previous first line: Linux still OK, worked until Mac10.10, fail Mac10.11
# #! /usr/bin/env wish8.5
# Mac10.11+: wish subshell doesn't get DYLD_LIBRARY_PATH *or* PATH

############################################################################
# UCSD/UCL/SDSU csurf -- by Martin Sereno
############################################################################
### user-settable interface defaults
set doublebufferflag    1     ;# set 0 if xserver reqs singlebuff, redraw probs
set smallscreenflag     0     ;# menuflag->tksurf/med, nofollow, 2helps, smlist
set fnewtopflag         1     ;# session combo: 0=newest-bot, 1=newest-top
set editorlist { /System/Applications/TextEdit.app/Contents/MacOS/TextEdit \
                 /Applications/TextEdit.app/Contents/MacOS/TextEdit \
                 gedit nedit xedit vigterm vixterm "" }  ;# use 1stfound
set helpwinlines       45     ;# num lines in csurf Help menu popups
set selbitpixhigh     500     ;# select panels (pix, reduce for shorter screen)
set loglines            7     ;# lines shown in command/tkmedit/tksurfer logs
set logflag             0     ;# init status of logs
set minglxdepthflag     0     ;# 1 means 12bit (vs. 24bit) depth buff request

### flags to omit/swap interface parts, don't change
set simplediffsflag     0     ;# RandBlockPanel: 0=fullglts, 1=orig diffs/adds
set newsubjtoolsflag    1     ;# incl new hi-res tkstrip/wmfilter/fill/surf
set mghsubjtoolsflag    1     ;# incl tools to run separate default MGH install
set xsesstoolsflag      1     ;# incl cross session tools (AFNI, mri_surf2surf)
set talairachflag       1     ;# FreeSurfer0.8 only: incl old MNI talairach
set oldsubjtoolsflag    1     ;# FreeSurfer0.8 only: incl old Linux static bins

### for information, don't change
set program            csurf  ;# used to find helpfiles
set ${program}_oldvers  0.8   ;# back here 2013: match csurf0.8/FreeSurfer0.8
set ${program}_vers     0.9   ;# still recognize: in some stale csurf.dat
set ${program}_newvers  1.0   ;# TODO: when released
set functdirstyle imagesubdir ;# "imagesubdir"->image/$dir, "flat"->$dir
set csurfconvalignflag  1     ;# old: convalign {brik,orig}2cor vs mri_convert
set csurfstripskullflag 1     ;# old: mri_strip_skull vs. mri_watershed
set logwidth           80     ;# same width as widgets
set biglogflag          0     ;# 0 is $loglines, 1 is 18 lines
set bigloglines        18     ;# lines shown in command/tkmedit/tksurfer logs

### for debug
set debugarrayparms     0     ;# csurf.dat parms to stdout each write
set debugcommands       0     ;# runacmd cmds to stdout
set debugafnilabels     0     ;# dump AFNI labels during demangle, default mask

############################################################################
# Binaries included and/or needed
############################################################################
### csurf newly compiled binaries (Linux/Mac/IRIX)
#  tksurfer           -- interactive surface render, data overlay
#  tkmedit            -- interactive 3D MRI view, edit, data overlay
#  tkregister         -- interactive 3D MRI blink align
#  tkstrip            -- interactive skull strip
#  wheel              -- interactive disk/rectangle color scales
#  regcor             -- avg multiple COR imagesets w/xform matrices (rare)
#  orig2cor           -- convert/upsamp raw scans to COR (rare)
#  brik2cor           -- convert/upsamp BRIK to CORdir/mgz, reads ORI_SPECIFIC
#  cor2brik           -- convert CORdir/mgz to BRIK, write ORIENT_SPECIFIC
#  brik2bfloat        -- AFNI -> bfloat (slice bfloats no longer used by def)
#  bfloat2brik        -- undo above: bfloat -> AFNI (not used here)
#  bresize            -- fold/unfold vertex list data into pseudo 3D brik
#  calcimg            -- BRIK/COR/mgz simple pixmath, manipulate mgz header
#  wmfilter           -- refurbished hi-res-capable wmfilter, Gauss planefilter
#  fill               -- refurbished hi-res-capable fill white matter
#  surf               -- refurbished hi-res-capable tessellate
#  paint              -- sample volume stats onto surface (3D -> vertexlist)
#  calcvert           -- wfile/curvfile convert, header, simple vtx math/stat
#  rawaverage         -- average 3D scans
#  fourier            -- calculate fourier stats, permutation options
#  phasecombine       -- combine fourier-analyzed data, circ subtract
#  rcxcombine         -- combine real or fourier-analyzed data, vect avg
#  surfcombine        -- stack-based combine stats on surface
#  surfclust          -- calc/apply surface-based cluster filter
#  multiclust         -- calc hierarchical surface clusters
#  randsurfclust      -- Monte Carlo smoothing -> surfclust parameters
#  mytoppm            -- toppm version that writes to stdout (rgb *or* tiff)
#  mpeg_encode        -- make MPEG-1 video
#  mpeg_play          -- play MPEG-1 video
#  nmovie             -- view SGI rgb or tiff bitmaps as movie

### current MGH dist binaries included
#  mri_convert        -- convert image formats
#  mri_surf2surf      -- resample data between different surface meshes

### AFNI binaries included
#  afni               -- display, convert, overlay
#  3dvolreg           -- motion correction
#  3dcalc             -- voxel-wise math
#  3dTcat             -- subsample timeseries
#  3dmerge            -- cluster filter
#  3dDeconvolve       -- general linear stats
#  2swap              -- swap MSB/LSB short
#  4swap              -- swap MSB/LSB float/int
#  3drefit            -- fix HEAD
#  3dttest            -- average, t-test
#  3dbucket           -- assemble indiv BRIKs
#  3drename           -- head-aware rename
#  3dinfo             -- dump HEAD

### current MGH dist binaries used by MGHTools (assumes separate installation)
#  mris_smooth        -- generate smooth white matter, calculate curv, origarea
#  mris_inflate       -- inflate surface, calculate sulc
#  mris_make_surfaces -- make final surfaces
#  mris_flatten       -- flatten cortex
#  mris_sphere        -- transform to sphere
#  mris_register      -- curvature-based morph on sphere

### old MNI mritotal talairach perl script (included w/FreeSurfer0.8 only)
#  uses binaries: autocrop minc_modify_header mincresample mincreshape
#                 mincblur volume_cog minctracc check_scale

### old static 2001 Linux-only binaries (included w/FreeSurfer0.8 only)
#  mri_convert        -- convert image format
#  mri_average        -- motion correct and average
#  mri_normalize      -- normalize brightness
#  mri_strip_skull    -- remove skull
#  mri_watershed      -- new version  of skull stripping (default: not used)
#  mri_wmfilter       -- old white matter filter (default: not used)
#  mri_segment        -- white matter filter
#  mri_fill           -- fill white matter
#  mri_auto_fill      -- template based auto fill (not used)
#  mri_tessellate     -- generate surface
#  mris_smooth        -- generate smooth white matter
#  mris_inflate       -- inflate surface
#  mris_fix_topology  -- auto correct topological defects
#  mris_make_surfaces -- make final surfaces
#  mris_flatten       -- flatten cortex
#  mris_sphere        -- transform to sphere
#  mris_register      -- curvature-based morph on sphere
#  stat_w_average     -- combine stats on surface (not used)

############################################################################
# update NOTES -- summary
############################################################################
### overall changes history
#1989-1994: Anders Dale C/IRIXGL: {trishrink/wmfilter/fill/surf/medit/surfer}.c
#1994: combine image/scripts csh's into: mksurface.csh, mkfunct.csh
#1995: sereno surfer.c w/homemade ASCII script interperter (C/IRIXGL) for movies
#1996: tksurfer01 (discovered tcl, merge surfer/nsurfer/msurfer,C/OpenGL/tcltk)
#1997: bsurf01 (tcltk) mksurface/tksurfer runner (1.3K lines)
#1998: csurf01 (tcltktix) tksurfer/tkmedit runner + recon/overlays (730 lines)
#1999: csurf31 (June 1999 CorTechs CD) HBM release (3.7K lines)
#2000: csurf32a (4K lines -- UCSD updates)
#2001: csurf33a (5K lines -- UCSD updates)
#2002: csurf34a (10K lines -- UCSD updates)
#2003: csurf34g (11K lines -- UCSD updates)
#2004: csurf34p (12K lines -- UCSD updates)
#2005: csurf34r (13K lines) -- UCSD updates: last UCSD)
#2007: csurf35a (13K lines) first London
#set subversion 35c ;# 2008: fix MakeScanDirs, forceMSB does float, sort
#set subversion 35d ;# forceMSB briks after stripTRs
#set subversion 35e ;# new paint opts (mx|av|min,normop) in addfunctscan
#set subversion 35f ;# resurrect Import Ext Stats AFNI-SINGLE pane
#set subversion 35g ;# fix back compat, add undo curv compat, surfcolor
#set subversion 35h ;# CLONE FUNCT added to Setup Funct Scan (version lost)
#set subversion 35i ;# qsphere/full-noinfl/full-infl fail at 0.75mm, revert!
#set subversion 35j ;# vi/gterm, load rand OK after extstat, cat/chk motion.1Ds
#set subversion 35k ;# 2009: mkorig1/2, sort AFNI cond, fwd/bak FS Compat+Undo
#set subversion 35l ;# 2010: (14K lines) sliceord timing correct, fourier uses
### Sep 2010: begin Mac/Linux recompile tk{surfer,medit,register}/fourier/etc
#set subversion 35m ;# (17K lines) new cmplx-valued xsess/subj SphereAvg panel
#set subversion 35n ;# cosmetic, finally remember structparms, subj patt match
#set subversion 35o ;# rm disablers, add sphavg dispersion index, log chdir's
#set subversion 35p ;# allow non-complex-valued SphereAvg
#set subversion 35q ;# port->wish8.5 Tix as tk pkg w/bakcmpat, mkorigdirs/cpraw
#set subversion 35r ;# 2011: DirList,DCONVsmo,setcolor,rendtrunc,ipsiyel,fouramp
#set subversion 35s ;# SphereAvg F-from-cmplx, VOLUME-STATS, read newcurv as .w
#set subversion 35t ;# thk-based dfrac paint, sphavg batch (begin MGH tools)
#set subversion 35u ;# light controls, F from sig, font update, stat mask, LUT
#set subversion 35v ;# MGHtools, fixREADHEAD, Rayleigh, flatpatch, tiff, VOLAVG
#set subversion 35w ;# 2012: (21K lines) hires tkstrip/wmfilt/fill/surf/MGHparms
#set subversion 35x ;# mask, t-pow, full FTs, bfloat->BRIK, new 3dDeconv labels
#set subversion 35y ;# 2013: (23K lines) GLTs, !tcl7.4, tnormsamp, clust, bord
#set subversion 35z ;# 2014: (24K lines) AVGSURF, buckner40, Csurf.app
#set subversion 36a ;# 2017: (27K lines) Yosemite/Sierra, CARET/Jet, chk env
#set subversion 36aa ;# 2019: (28K lines) incl subversion matches tksurfer
#set subversion 36ah ;# 2022: (29K lines) bug fixes
#set subversion 36ai ;# 2023: (29K lines) use TAXIS_OFFSETS
#set subversion 36ak ;# 2024
set csurfsubversion 36am
set tclsubversion 8.5.18
set tixsubversion 8.4.3

############################################################################
# update NOTES -- details
############################################################################
# ... none before this
### detailed changes subversion 35j
# change align/funct scan links so non-link sorts first
# vregregressflag to optionally turn it off
# autogenerate 1 smooth step surface: orig1 (for normals noise test vs. orig)
# change default editor to vi inside gnome-terminal
# fix no autoload rand block after functscan=>extstatscan
# Combine 3D Raw Images -> concat: motion.1Ds
### detailed change subversion 35k
# Combine 3D Raw Images -> concat: stim1Ds (list from first, names: <cond>?.1D)
# better paradigm file checking (only 1 and 0 allowed)
# fix no autoload rawaverage after functscan=>extstatscan
# sort Paintfile's (for AFNI-MULTI), put contrasts (*-VS-*) after single-vs.-off
# forward compatibility 3d/curv (and undo) button
# put fthresh below fslope and fmid on Render panel
# also autogenerate 2 smooth step surface: orig2
### detailed change subversion 35l
# Setup Funct sliceorder switch, fourier can use it
# better warning for BackCompat3d when COR dir exists but missing COR-.info
### detailed change subversion 35m
# new fourier xsession avg panel with configurable 5-wide entry lines (1based)
# Make SphereAvg Dir -> only 1 scandir allowed
# display-subject for average data resettable (via rewrite name file)
# cp live panel vars -> sphavglists -> parmfile at Save (read/write/clear)
# restore saved sphavg panel state from sphavglists
# File -> New Spherical Avg to make sphavg session
# differentiate aspects: render, rendersphavg for next
# prevent config sphavg w/SessionTools, and config indiv sess w/CrossSessTools
# add purpleintr to quitacmd command in runacmd so proc can test, debugcommands
# SPHEREAVG => sample to ico, conv->AFNI, avg, conv->wfile
# SAMP2SUBJ => just sample to subject (on same panel)
# put config'able sphavg widgets in tixScrolledWindow for lg avgs (15 visible)
# resettable default heights for Help, selectbitmaps popups
# spherical avg Help panels 
# hemi pattern match more permissive for ViewSubjectRgb's (was blank w/o BOTH)
# cd to svit dir so output goes there instead of in subject scriptdir
# $CSURF_DIR/local/lib/tix4.1/ComboBox.tcl->tixComboBox:EscKey add return ->0<-
# above fixes long standing crash from Esc in main window w/disabled comboboxes
# catch attempt to run SPHEREAVG/SAMP2SUBJ on blank session, inform
# fix sphereavg entry/button/combobox halos (-highlightbackground $bgcol)
# RenderPanel: repack Paintfile/surfpick line to not overlap OpenGL window
# fix halos for setupscans action entry/button, bottom Saves
### detailed change subversion 35n
# fix halos 11 other setupscans panels, expertprefs, popups, wrappers.tcl
# expose mri_surf2surf --mapmethod (nnfr vs nnf) in interface, document
# tix meter for ico resample gets reset at end and stays up during final avg
# fix halos in scrollbars (many panels)
# selecthemi one-hemi warning now defaults to currently selected single hemi
# fix saved Setup Struct Scan parms erase -> SubjectTools cmds now readparms
# add tixMeter to SAMP2SUBJ, don't leave it stranded if purple interrupt
# allow expand (but not shrink) Fourier SphAvg window (to banish scrollbars)
# interface def flag: brighten R/G curv like grays+data w/brightphase.tcl
# made stub afni_vcheck that does nothing in case AFNI website down!
# distinguish runacmd-always-resets purplekill (log) from purplekillseq
# do pattern match on subject if not found (like sessions)
# check if libXm.so.3 is there, give err/instructions for installing it
### detailed change subversion 35o
# strip out flags disabling interface parts (except talairach/icos flags)
# add dispersion index to SPHEREAVG and SAMP2SUBJ
# record all cd's in cmdlog (echo if debugcommands)
# RH9-compatible afni lib check
### detailed change subversion 35p
# Cross Sess Spherical Avg panel allows non-complex-valued average
# fix editor search (csurf/tksurfer.tcl) on Mac (/usr/bin/which resp differs)
# add optional parm to selectdialog (if optional selmode not single|multiple)
# use new optional parm to adjust mpeg framerate (like nmovie)
### detailed change subversion 35q (update to Tix8.4.3 -- tedious!)
# Tix8.4.3 now pkg in wish8.5 (no tixwish), in wish8.5: require package Tix
# move Tix .so/.dylib out of noarch lib into arch-specific with libtk8.5.so
# $newpkgtix: keep back compat w/older tixwish (tixwish4.1.7.4,tixwish8.1.8.4)
# main csurf tixLabelFrame grooves missing -> do "tix resetoptions" at end 
# tixListNoteBook pane is vertical ->... -options "pane.orientation horizontal"
# unneeded tixListNoteBook scrollbars ->... -options "shlist.scrollbar auto"
# unneeded sphavg/extstats tixScrolledWindow scrollbars -> -scrollbar auto
# def Yspace toplevel top/bot buttbox gone -> config -pady 20
# def Xspace toplevel top/bot buttbox gone -> -padx 13 => -ipadx 13
# restore batchstat tixCheckList defaults: $hlist config -pady 0 -padx 25
# different height convention tixCheckList hlist: -height 125 -> ~170
# non-extended and extended file select dialogs crash parsing "-image" arg
# http://bazaar.launchpad.net/%7Evcs-imports/tix/main/revision/596/ChangeLog
# apply Dir{List,Tree}.tcl patch above: ... add $dir -itemtype imagetext ...
# MRI_DIR -> CSURF_DIR in wrappers.tcl (helpwin)
# undo smaller tixNoteBook def tabs: $nb subwidget nbframe config -tabpady 5
# tixLabelFrame grooves invisible except white line after tix resetoptions
# tixLabelFrame $f; pack $f; $f.border config -relief groove -bd 2
# do above for every toplevel panel created by each add<type>scan proc
# update idletasks to get rawavg panel to redraw after save
# bigger default hlist size for new bigger-icon directory hlist
# viewallscandirs: selbgcol (lightgreen) instead of selcol (newpkgtix->white)
# black menu checks (was green check boxes with dark border line)
# extended fileselect dialog works w/patch, but a mess (11 hand fixes)
# $extdialog subwidget fsbox subwidget {dir,file}list config -scrollbar auto
# put back 3 labels (leave packleft vs top), re-enable combos, pady, widen left
# wrappers.tcl: menubutton ... -padx 4 -pady 3
# menu -activeborderwidth default changed: new=0 looks like old default=2
# main.{right,left} config -bd 0 (old -bd 2 looks like new -bd 0)
# new tixButtonBox default -padx 3m -pady 1m bigger => -padx 6 -pady 3
# reset entbgcol #e9e9e9 (darker than tixdef gray95, lighter than old entbgcol)
# default bgcol configs moved (for tix widgets) to configtixbookcbxent
# restore combobox entry+listbox -selectbackground after re-enable combos
# rm fontsize-dep height-setting code in bgsequencewin (just expand width)
# can't compactly avoid tix options, tixDisplayStyle completely
# --------- basically done with horrible wish8.5/Tix8.4.3 update ------------
# log all mkdirs (parallel to logging all cd to dir's)
# extend Make Scandirs + Find/Copy Raw panel work for struct orig dirs
# better documentation runacmd, checkdestroy
# onearch-style bins/libs, fish out afni/tcltktix, mpeg/xv/xdiff/nedit->bin
# update FreeSurfer0.8/<dirs> FreeSurferEnv.csh FreeSurferSwitcher.csh to same
# skip COR-.info warning if not old tksurfer
# darker disabled entry text (also tixCombo): -disabledforeground #555555
# add doublebufferflag, dividequadsflag to expert parms
### detailed change subversion 35r
# tcltktix/lib/noarch/Tix8.4.3/DirList.tcl:tixDirList:Command fails on links
# hack: before tixDirList:LoadDir -- set vpath [file normalize $vpath]
# hack: disable full directory trees
# if Darwin, use correct previously commented out BSD args to ps
# strip old struct-vits/icos commands
# add optional 3D pre-smooth (3dmerge) to DECONVOLVE panel
# if not Linux, omit startup err on not-found SubjectTools binaries
# tksurfer colscale code flossed: set_{const,curv,complex,fs,fstat,real}_color
# 3 colscale vars: first combines parms, second two select Cfuncs,Cfuncparts
#   rendertype:   eccen,polar,2cond,fstat,real,fs => multi-set, 1st panel open
#   colscaletype: cplx,stat,fs,real => pick which set_*_color function
#   colscale:     wheel,heat,etc,... => pick which subtype in set_*_color funct
# tksurfer: redefine statflag blu/redY HEAT_SCALE=1 -> HEAT_SCALE2=11
# stop making (stupid) non-copy-able links to raw scans => save in txtfile
# add renderscanlists/renderpanel vers of $hemi,truncphase{min,max} (defs diff)
# rm mri_average/noalign, def=heptic, rm brightRGcurv,brightphase (now def)
# add renderscanlists/renderpanel offset,cvfact; pass via env; add bi colscale
# change FUNCT=>SUBJ and ALIGN=>SUBJ target to orig (was T1)
# add renderscanlists/renderpanel fadef,ipsiyellowfact; pass via env
# surftestrender now saves panel parms (on kill tksurfer) like other panels
# tksurfer: separate tclenv (bypass to tclscripts) from opts (set tksurfer vars)
# smallscreenflag menu flag passed to tksurfer (GL->upR, tools->lowL, nofollow)
# add Expert Preferences morph target parm sphereparms(morphtarg)
# fix editorlist, if same-plane struct unset and alignslist>0, auto set align
# fourier saves raw amp too (_x,_y), sigavg/paint auto-avg/paint if there
# fourierampflag Render panel checkbutton to toggle sigphase,ampphase
# viewallscandirs: getxydsp->maxy, rm viewscandirlines, tixMeter8.5 -width/-pady
# viewallscandirs: fix dump if double-click unconfig'd, update no panel proc
# phavg/surfavg: warn non-informative phavg/surfavg default names not changed
# bakcompat older csurf.dat files: rendertype->colscaletype no redef config'd
# fix tixMeter8.5 on Sphere Avg panel, update samp2subj mri_surf2surf cmdline
### detailed change subversion 35s
# sphavg panel also calculates raw Fourier coefficient averages (_xavg,_yavg)
# sphavg panel also calculates Don's 2007 complex F-ratio
# polar-{views,flat}.tcl: optional read stat if stat{mult/repl}flag
# add Complex Amp (stat, mul) to View Functional Data panel, add both to parms
# if $newpkgtix: VOLUME: if no $imagedir/COR-001, try $imagedir.mgz
# if mgz, reflect in right-side mritype entry, Return there clicks VOLUME
# if $newpkgtix: ALIGN/FUNCT=>SUBJ same as above (no interface var update)
# 3D phase avg: don't overwrite normsearch parms (all other parms from 1stdir)
# VOLUME-STATS button works for _r_i, _x_y, or _f (newpkgtix->newmeditcmdline)
# warn/help no .BRIK suffix on Image Name Pattern (bug corrupting imagepatt?)
# fix introduced sphavg bug: missing $fnum in $tmppref
# VOLUME-STATS button checks for underlay in: orig/COR-001, orig.mgz, orig.mgh
# [no change: read_binary_values accepts newcurv format stats files, still *.w]
# fix yet another find-editor/editorlist bug
# read AFNI HEAD functs fail parsing new comment lines w/brackets and \n's:
#  err: list element in braces followed by "\n[inverse@buc05:" instead of space
#  fix: if {[lindex $line 2] == "PATT"} => if [string match *PATT* $line]
# stray quote on textvariable (csurf35q+) after "Surface for Sampling 3D Data"
# auto surfaverage raw fourier if there (surfcombine and rcxcombine) TODO:test!
# sphavg panel samples new Don complex-F stats back to an indiv subject
# mark cmds better in log (runacmd), fix Don sphavg/resamp, ignore sphavg dir~
# render panel select r,i or x,y updates fourierampflag
# fix mkorigdirs setupscans misplace invoking sessions combo, changing name
# imagepatt fix attempt: non-tix-option textvariable w/addfourscan imagepatt
# tix8.4.3 progress meter needs -bd 2 -relief sunken
# log all exec rm's w/rmlog, handlog recursive rm's, debug _x,_y surfaverage
# batch skips fourier panel on accidentally fourier-config'd phavg/surfavg
# Don F finally fixed (rm prev run total before rename to it, no sqrt numer!)
# sort vtxlist prefs (real/cmplx) in sphavg panel (in select_sphavgscandir)
### detailed change subversion 35t
# add frac/mm vtxnorm searchtype switch (NormSrch: [mm][frac] mn/mx:[][] ...)
# copy above to Import Stats panel, test/warn select frac if no thickness file
# paintcmd/paintcmdbrikmulti read normtype, make various cmdlines for new paint
# smallscreenflag makes sphavg dropdowns uniform, shorter
# frac/thick filetest catch BOTH, def sigavg normsearch if missing (surfavgOK)
# pop-ups when sphavg,samp2subj finish (like bgsequence) -> later disabled
# add MGHTools menu, FSURF_DIR, $mghbindir
# if change normtype: to frac: 0-0.8 (avgthk=2.5mm), to mm: 0.0-2.0, else saved
# special-case runbatchstat for sphavg/rendersphavg, special runsphavgpanel
# setupsphavgcx returns, add kill proc, runsphavgpanel can now press buttons
# check fieldsign panel fspatchext (was using $fspatchext but chking $patchext)
# add TruncFS (nonbinaryfsflag) control; no csurf fsslope control for now
# Mac: all following assume default X11.app "Use the system keyboard layout"
# Mac: def X11 key bindings: option/alt => Mode_switch, apple/cmd => Meta_L
# Mac: use "bind . <Meta-l> action" to bind action to Mac Cmd-l
# Mac: N.B.!: only Meta/cmd- keys available: b,d,e,f,g,i,j,k,l,o,p,r,s,t,u,y
# Mac: entry-less toplevel OK bind literal Opt/Alt-key output so Alt-key works
# Mac: e.g., <Opt/Alt-a> => <Key-aring>, <Opt/Alt-l> => <Key-notsign>
# Mac: above won't work in any panel w/entry because it also types Opt/Alt char
# Mac: HOWTO find out tcl/tk keysyms/nums: bind . <Key> { puts "%k %K" }
# change 'old' (now envsurfcmdline) cmdline to mostly options, pass overlayflag
# rm statflag mess (was disabled: disp stat field instead of val[val2] field)
# add invphase to renderpanel, pass it (was flag-dep copy revphase to invphase)
# re-bind AFNI to Alt-f (Darwin Meta-f), update setupfunct help
# select_sigtoavgdir: catch oldsess miss paintnormtype, better msg at COMBINE
# fixed backward order, missing +orig 3dmerge args DECONVOLVE pre-smooth panel
# add Fourier panel pre-smooth3D, rm smoothtepsin (crashing fourier in-plane)
# add AFNI button/binding to fourier panel
# change 3dvolreg labels to avoid kill mishap: ALL->ALL=>T, CURR->CURR=>T
# re-arrange FreeSurfer0.8 mni dirs, fix binary check and model/targ paths here
# proper default + backward fix missing brightness parm on phase avg paint redo
# ----- Mac10.6 font mess: defs changed (config butts->bold, label chaos) ----
# wrappers.tcl font cleanup: fork existing to pre-8.4, new standard font style
# combobox subwidget config vs. -options (see: "tix options bug")
# tixlabelframe subwidget font config vs. -options (see: "tix options bug")
# [tix option get bold_font] -> wrappers.tcl: $tfont (leave italic_font now)
# add label/entry defaults to configtixbookcbxent (TODO: add tixSelect fonts)
# config default combox label ffont->tfont, override for main csurf panel
# wrappers.tcl: compact arial12 hfont for hlist/cbx (entries keep loose lucida)
# config bare entries ffont, Make Dir entries tighter hfont
# config(newpkgtix) hlist->hfont: phavg/surfavg/rndblk/viewscans/batch/rgb/mpg
# mk{orig,scan}dirs entries -> smaller hfont(newpkgtix)
# configfunct(newpkgtix) TixButtonBox->hfont (declare), TixLabelFrame->tfont
### detailed change subversion 35u
# add subj-specific ExpertPref lights controls, transfer cvfact/offset to there
# rm renderpanel cvfact/offset, expand chklabels, hide/save renderscanlist copy
# make Hagler-like F-stat from single subj sqrt-F (in addition to raw F amp)
# statsfromsigflag: picks which cplxfname F-stat to use in sphavg stat/mul mod
# set tixSelect button font $hfont, fix dup'd hemi/subj/patch, setuprender help
# startup checks catch final slash on SUBJ..,FUNCT.._DIR -> breaks path parsing!
# changed f.a->f.aa to fix stale imagepatt value in fourier,render (worked?)
# rm all -options, unoverlap: funct:$f.a, four:$f.aa, rand:$f.aaa (worked?)
# add -zpad 4 to motion-correct EPI 3dvolreg 
# [tix option get italic_font] -> wrappers.tcl: $ifont
# add reverse time checkboxes to rawaverage panel (concat err)
# rewrite rawaveragecmd for BRIK out (if BRIK in) for rev'd rawavg timecourse
# widen entries, squish buttons for Make Raw/Phase/Surf/Field Dir
# fix ps -[options] (finally broke for good on Mac OS X 10.6)
# move mri_convert (w/nmovie, mri_surf2surf) to core bins for bak compat
# current fs5.1 10.4 compile doesn't have mri_surf2surf! (there in new linux)
# tkmedit rad:0->1, Update subj/sess restores curr, tkmedit surf respects $hemi
# load scriptsdir tcl scripts (w/divider) into top of 3D,Flat combos
# render: val2rgblut/real colscale, tksurfer changes to amp if complexvalflag
# render: interpolatelutflag parm, to surftestrender, rawdata/regdat in nopanel
# menu: disable oldsubjtools if Darwin, if !oldsubjtools bakcompat to MGHTools
# handle 3 types of complex amp mods: precedence: replace, mask, multiply
# if a cmplx amp mod is set, try substitute -mean- to -stat- for _f,_g lookup
# new mri_surf2surf requires .w suffix even w/recog'd src_type w (OK for older)
# mvlog: fix "set own/grp(was: 501/0):not permitted" work-but-crash-tcl w/catch
# force all calculations in sphavg to output float briks
# re-dir start editor errs->null, catch other which errors (like tksurfer.tcl)
### detailed change subversion 35v
# finish/test interface machinery for RECON-ALL (curr:no csurf.dat parms saved)
# auto-create make{scan/orig}dirs panel and 2 blank entries
# rm flipbrik, convalign/CONV=>COR, classify{struct,funct}+children, mri_head
# replace w/simple suffix-based head reader for BRIK,bshort,bfloat: readheader
# save avg/tstat of amp=hypot(_r,_i) as <zz>-{mean,tstat}-sph-sm1_a-$hemi.w
# resamp avg/tstat of _a to dispsubj, *don't* resample (_x,_y)(_r,_i) *t-tests*
# add single value (def=0.0) to compare 1-sample ttest of _a with
# replace statsfromsigflag with renderscanlists($page,complexstatsource)
# cplxfname->cplxstatname1,cplxfname2->cplxstatname2,new:cplxstatname3=amplname
# change csurf repl/mask/mult to tixSelect, translate to tksurfer binary flags
# second rendersphavg-only tixSelect for repl/mask/mult stats source (12combos)
# write complicated complex+stats mod/source consistency check (3 error panels)
# surftestrender warns Data Type (colscaletype) and Color Scale mismatch
# change colscaletype forces compatible complexvalflag/tclscripts/colscale
# add -stimcycles env/opt (functscanlists) to surftestrender, default missing
# use bfloat stem verbatim for tkmedit overlay if real file (don't add _f)
# block/warn spaces: mkavgdirs, CSURF,SUBJECTS,FUNCTIONALS_DIR, browse to dir
# add AFNI-ALL SetupFunct cmd to make links + view all BRIKs in current session
# add Rayleigh test to SPEREAVG cross sub stats, save pos p exponent => _e
# Rayleigh p pos exponent = -log10(exp(sqrt(1 + 4*n + 4*(n^2 - R^2)) - (1+2n)))
#   where n=samples, R=vectsum (not avg) of unit vectors for each sample angle
# add Rayleigh mask (cxR-ang) to View SphereAvg Data
# tksurfer def patch output now float, expertpref writefloatpatchflag reverts
# re-write/fix MGH recon-all errors/cmdline/re-run
# add/wire-up cross-subj StatBrikStem, add VOLAVG butt (volavgcxcmd empty)
# fix which/editor once again (new /usr/bin/which empty return on missing)
# if in scripts dir in curr tail of FUNCTIONALS_DIR, start csurf in that sess
# finalparms array wasn't being saved in csurf.dat, makingextstatscan->save dmin
# add allverticesflag to addfunctscan, def missing: fourier/sigavg/extstat
# catch no-widgeterr w/BOLDcmd on no scandirs, catch configd missing sigavg dir
# default dstep smaller (0.25->0.10) if choose frac
# prevent Save/Close from delete win before tkwait visibility (lg num panes)
# get/pass -scandir to option tkmedit, unique-ize AFNI-ALL links
# savetiff menu (surf+med), accept both .rgb/.tiff view/mpg bitmaps, tiff 1st
# global black2transparency menu item, wasbrak: # -> @, else nmovie pukes!
# disable also sessionscombo callback (sub already) dur mksphavg w/missing sess
# pass -rawdata <imagpatt> to tkmedit for ROI lookup rawdata
# allow float BRIK for tkregister (also change tkregister)
# fix "=" in passing fslope to tkmedit at option
# allow reset sphavg dir back to functscan (but not other way)
# VOLAVG 3dttest avg of r,i and x,y
# allow 1 input to 3D Raw Average (for reversing time in single scan)
# double-click on  subj/surf labels raises csurf subwindows in correct order
### detailed change subversion 35w
# if cross-subj, omit non-subsamp/nslice/etc to tkmedit, pass complexvalflag
# add alternate set of ExpertPrefs (fill.dat=options) for old fill
# add/use undividequadsflag, newquadoutputflag, *don't* tcl exp dividequadsflag
# add one-time checkbutton to load selected VOLUME images w/-loadmri1 on SURFACE
# new SubjectTools to run reconditioned hi-res tkstrip/wmfilter/fill/surf
# runwmfilter/wmfilterhirescmd -> old+mgz wmfilter
# runfill/[existing wmfillcmd does both fill+mri_fill] -> old+mgz fill
# runsurf/surfhirescmd -> old+mgz surf
# replace orig2cor with brik2cor only for: AFNI align, BRIK with HEAD
# warn attempt to load 3D MRI data set w/inflated surface
# FUNCT=>SUBJ uses TR field to pick timepoint to register
# don't delete clustered F-stats tmpcluster
# add tkregister target-image entry to Setup Functscan
# VOLAVG Don complex-F implemented (N.B.: no reversed phase)
# tkmedit cmdline: use -real/-imag vs. -real/-complex, -substatpatt_{r,i,m}
# VOLUME-STATS autoloads VOLAVG cross subj subsampled if there
# fix: set renderscanlists($page,complexampmodtype) == "off"   ;# tmp bak compat
# fix: tkregtargdir var/entry missing for alignscan, if align -> no invert
# fix: rm accel underlines, key bind mess (rm Mac-reserved), align Linux/Mac
# better keybind: b->bitmaps, e->all, f->viewfunct, l=>log, o=>force, u->update
# ViewFunct/RandBlk AFNI buttons (rm more stray Alt-'s incl View Funct Alt-f!)
# File menu: explicit Funct/SphereAvg in Open/OpenNOTES/Copy, SphAvgPan tixbug
# add focus . to end of succesful select_session (first select: in listbox)
# logs hotkey on setupscans(+bitmaps)/sphavg/reconall toplevels, mv popups back
# Mod-F hotkey for open/view sphavg
# refurbished hi-res tkstrip/wmfilter/fill popup ExpertPrefs tabs to set parms
# new Expert "Surf" tab w/surfparms, newquadoutputflag used by old/hi-res surf
# add $pddir=PD, $pdbraindir=PDbrain to VOLUME line, rm mkdir svit
# SubjTools -> StripSkull (hi-res), ExpertPrefs: addparms, use/view script
# SubjTools -> WMFIlter (hi-res), ExpertPrefs: use parms
# SubjTools -> Fill WM (hi-res), ExpertPrefs: use parms
# SubjTools -> Create Orig Surface (hi-res), ExpertPrefs: use parms
# tkstrip: PD->orig, wmfilter: brain->T1->orig
# Smooth/Curv/Inflate/Sulc menu: mghsmooth/mghinflate
# add view bitmaps to hi-res subjects menu, autoset hemi=both (else def=empty)
# rearranged Help menus (now too long on Linux, submenus?? combine steps?)
# clip plane feedback ExpertPreferences, autosave/reopen Prefs: strip,wm,fill
# RH/LH fill color in ExpertPreferences FillWM, Surf tabs (same var, no edit)
# surfhires 2-part, add hotkey menuflash, rm menubind (was being overridden)
# add nbrs parm for inflate hires (long parm search!), selecthemi (15min/hemi)
# add load image2 (filled.mgz, would need 2nd entry for starttime load)
# load 3rd im: surfload1->surfload, surfload2(filled)->surfload(filled,T2)
# write 7 helpfiles for main csurf ent/butt, squish menu heads for Fedora15
# new Final Expert Preferences tab: mv/update parms, toggle mris vs. tclscript
# Make Final Surface (mris_make_surfaces) vs. hi-res (tksurfer tcl)
# stop DECONVOLVE -> w/TEST from deleting already run stats file
# separate menucmds for mgh{smooth,inflate} and mgh{smooth,inflate}hires
# fixed introduced hemicurr view save bitmaps bug
# smallscreenflag=1 => tk{med/reg/strip}->followglwinflag=0 (tksurfer.tcl does)
# add Expert Prefs: zbuff24->zbuff12, doublebuffer->singlebuffer, menu separ
# pass testrender $rgb to tkmedit/tksurfer via option -rgbname
# if smallscreenflag set=1 in live parms code, split long help menu into two
# fix -rgbame option: *still* have to pass $rgb to tcl for render scripts!!
# fix showstopper missing "flag" typo in tkstriphirescmd
# mk maskname: strip _LC@0@_coef-thresh+orig, add _{t-st,F-stat}-clust+orig
# split colscaletype vstat -> rstat/tstat, -statmask passed to tkmedit
# don't pass vstatflag to tksurfer (statmaskampflag works, also controls live)
# tkmedit: construct *-clust- name from coef for tkmedit mask, pass by options
# check statmasks exist, live statmask render "one" only (no "all", "last")
# tksurfer: tkmedit logic, statmaskampflag->opt, $maskbfloatstem env->tclscript
# N.B.: 3dDeconvolve: t label retains _LC@0@, F omits it
# turn mask OFF, return if (1) can't subst mask, mask not found
### detailed change subversion 35x
# sphavg: save/paint/sampbak variance (_b = _a^2, variance, orig F-ratio sig)
# sphavg: t-test _b against t-val entry squared (out:avg-tstat-sph-sm1_b-lh.w)
# fix Extract/Convert help to reflect actual operations performed
# keep mritype radio buttons lit by re-trimming added .mgz/.mgh
# sphavg render panel: move XSub mask up to below Data Type (renum widgets)
# selecting real+{Fmsk,tmsk} "Data Type" unsets complexvalflag
# add StatMask Paintfile combo under Paintfile combo, init'd by fixswfileprefs
# fixswfileprefs: search matching real/complex statmask file, reload StatMask
# select_{wfilepref,complexstatsource,complexampmodtype}=>fixswfileprefs/update
# selecting complex F vs. sig reset fourierampflag
# select {r,i} vs. {x,y} swaps XSubPhaseMsk type only if mask on
# fixed missing-statfile bug that was preventing fieldsign display
# unoverlap surftestrender, fixswfileprefs (all infix manip in fixswfileprefs)
# fix display of real mask (bak compat: accept #)
# render panel display/save/surftestrender/togglestate sfthresh/sfmid/sfslope
# fix togglestate (page-specific statmaskparmslist for non-sphavg render)
# fix intro'd bug in mk new renderscan (wait fix(s)wfile til vars exist)
# render panel passes sfthresh/sfmid/sfslope to tkmedit
# add bwslope/bwmid to Render panel/parms, pass to tkmedit
# setdefault polar/eccen color scale unsets invphaseflag
# add kfwhm/kcnt to Render panel/parms, pass to tkmedit to autosmooth overlay
# refix funct/four tix lab/ent mangling: only breaks if renderpanel opened prev
# fix introduced bug: fix non-existing coefsuffold w/t-stat
# addfourscan: config'd pre-phasestatformat w/bfloats -> set statfmt bfloat
# addfourscan: bfloat/afnibrik radio button, maybe pass -sigoutbrik to fourier
# sigaveragecmd: config'd pre-phasestatfmt w/bfloats+1stavg is bfloat -> same
#  --above is cmd not mkpanel because sigavg is cross scandir dep on inputs
# sigaveragecmd: pass {bfloat,BRIK},-ext {bfloat,BRIK} to BRIK-OK rcxcombine
# paintcmd: config'd pre-phasestatformat w/bfloats -> set statfmt bfloat
#  --above is cmd not mkpanel since PAINT is an extra button on several panels
# paintcmd: pass bfloat or BRIK to paint (paint checks suffix)
# stripbpatt: generalize to strip +orig.BRIK, better filter (rcxcombine fixed)
# fourier panel has "full FT" checkbox to dump all-freq's real/imag/amp BRIKs
# also pass complex float BRIK stats to tkmedit overlay if phasestatformat
# expose Hi-Freq cutoff (rm hi freq breathing above 100 w/256reps)
# addfour: select "full FT" change statformat->afnibrik (not req'd, consistent)
# sigaveragecmd: add sigoperation fullphavgsig
# sigaveragecmd: fullFT avg requires same stimcycles, timepoints
# sigavg fullFT is two stage: rcxcombine fullFT's, then fourier the average
# checkanalyseinput -> gettimeseriesinputstem
# [Select-to-Add generated "3D Stat Image Prefix" same for sigavg,fullFTavg]
# fix fslope getting mangled by de-option-ize textvariable (TODO: for all tix)
# also pass -fullfouramp flag to rcxcombine
# add -selectForeground black to tix combo-ent, combo-list, lab-ent for linux
# add -selectforeground black to *.e? entries for linux (missed by fixcolors)
# add "rm full FT" button to Fourier panel to cleanup 6x raw FTs after use
# phasestatformat -> def statbrik output (SPH uses .w, VOLAVG req's BRIKs)
# add realstatformat (bfloat,afnibrik) to avoid dumping large num real bfloats
# big: add to addextstatscan, convertfunctcmd, paintcmd, paintcmdbrikmulti
# deconvcmd sets output stats filename ahead for init addextstats input
# BRICK_LABS changes: <zz> LC[0] coef -> <zz>_GLT#0_Coef, val,mask both w/GLT
# extend readmultibriklabels demangling (bak compat), rm new # for nmovie choke
# fix load MaskFile combos to also accept, default/match new label format
# AFNI-SINGLE paintcmd does bskip previously done for bfloat by brik2bfloat
# AFNI-MULTI paintcmdbrikmulti accepts either bfloat or BRIK stats
# auto-default ExtStats: Extract (all), Cluster (maskedcoef), MaskThresh (0.01)
# sort *-stats+orig.BRIK(HEAD)'s to top of External Stats Image Set list
# VOLUME-STATS accepts old or new 3dDeconvolve infixes
# Import External also auto-defaults Tstats (old and new label versions)
# convertfunctcmd now saves/uses clustered statmask for tksurfer
# paintcmdbrikmulti does both simple thresh, clust stats (add/chk ,sbfloatstem)
# surf overlay fixswfileprefs (find statmask) works w/new 3dDeconvolve labels
# use more compact 3dmerge command to generate clusters
# rewrite convertfunctcmd:
#  AFNI files: 3dDeconvolve: (1) coef, (2) fstat/tstat
#  AFNI files: 3dmerge: fstat/tstat -> (3) fstat/tstat-clustermask
#  AFNI files: 3dcalc: mask (1) with (3) -> (4), mask (2) with (3) -> (5)
# coef operations:
#   coef/nocluster/nothresh -> dump coef
#   coef/nocluster/thresh -> thresh coef
#   coef/cluster/thresh -> cluster stat, mask coef
# stat operations:
#   stat/nocluster/nothresh -> dump stat
#   stat/nocluster/thresh -> thresh stat
#   stat/cluster/thresh -> cluster, mask stat + dump unclustered stat
# improve mask enable/disable wiring
# surftestrendernopanel F/tstat mask search
### detailed change subversion 35y
# addrenderscan: new alternate arbitrary GLTs panel (vars don't overlap)
# simplediffsflag toggles orig and new (now Preferences, could store by page)
# mkgenlintestmats: use new vars, return success (if need abort deconvcmd)
# mkgenlintestmats: can now turn off vregregressflag
# deconvcmd: use 3dDeconvolve output from new GLT panel output
# mkgenlintestmats: allow only neg (VS-asdf,sadf), warn all 0's
# finally, read TR's from HEAD (for Fourier and Rand Block Stats)
# discovered 3dDeconvolve truncates BRICK_LABS to 32-chars!! catch/warn attempt
# extract chkcontrastsmknames from mkgenlintestmats, autogen or test names
# add saved GLT name entry, DECONVOLVE tests if empty or >32, uses directly
# add update idletasks to end add*'s to avoid squished Save/Close/Cancel
# change default struct convert to mgz
# add renderpanel complexlut "lutw" (phase) to ColorScale, add clash check
# surftestrender: pass -normdfracsamp/-normdsamp from SetupFunct min/max midpnt
# defmissinglutfile: warn/make missing real/ecc/pol lut if ColorScale lut,lutw
# surftestrender defaults missing search parms (TODO: default in add*scan prcs)
# medtestrender passes -stimcycles for collapse t
# mkscandirs/setupscans: block scandirs w/spaces,semicolons (-raisecmd crash)
# choosedir (session/subject) also blocks semicolons (was blocking space)
# don't allow make subject or session with space(s) or semicolon(s)
# rm newpkgtix, env{surf,med}cmdline from {surf,med}testrender
# all other newpkgtix removed entirely
# mk mpg panel sets mpg name using stem of first rgb/tiff (reqs 2 dialog calls)
# fix addrawavgscan showstopper: rm spurious -font option from tixCheckList call
# make combolistbox adjust and split/unsplit help menu also work live
# CONVERT/AVERAGE warns non-zero spacingX,Y,Z MGH tkmedit incompat
# newcurvareaoutputflag (float curv, area not 2x), Prefs, pass to tksurfer
# add "F:" and "mm^2:" entries to Cross Sess Sepherical Average panel
# add surfclust filter-resampled-F-stat to SAMP2SUBJ button => _h
# warn if re-SAMP2SUBJ on old SPHEREAVG run if missing _b bfloat
# nocallback-wrap varcfg complex{statsource,ampmodtype} else re-def sbfloatstem
# addfunctscan: tNormSrch (normdsampsearchflag), pass to tksurfer
# addfunctscan: tUniqVox (normdsampuniqvoxflag), pass to tksurfer
# if normdsampsearchflag, normd samps are min, maxs are max, else samps are mid
# bakcompat create either missing at older-configd init renderpanel open
# if normdsampallflag, dump (non-uniq) timecourse for every dstep, uniq override
# add INIT/FLIP button to addalignscan panel for standard tkregister flip
# add "tALLdx" to pass -normdsampallflag (BlkCntOff->Cent, PaintAllVtx->PntAll)
# rearrange funct: NormSearch parms before timecourse flags, mv CentOffset up
# debugged options passed for write_label_timecourses
# fourierpanel: Mean Delay => Single Subj Pre SurfClust F-thr (preclustfthr)
# fourierpanel: add Single Subj Min Clust Area (mm^2) (clustarea)
# noticed StimProgNOTES var mangle -> change it to not tix options
# singlesub PAINT does surfclust at end if: (1) cplxdata, (2) _r,_i (3) _f there
# Mac DYLD setuid warn crashes surftestrender! exec ps uxww | grep => .. |& ..
# fix missing not eq: selecting phase data wasn't resetting colscale to "wheel"
# new single-only tixsel: SingleSubPhaseMask: sig(none:amp=sqrtF) sig+clustFmsk
# fixswfileprefs: 4 cases: real/complex by singlesub/xsubj (real xsubj empty)
# fixswfileprefs: complex singlesub now auto-sets _h if sig+clustFmask
# fixswfileprefs: complex xsubj selecting _x,_y now checks for _f if no _h
# sigaveragecmd also copies preclustfthr,clustarea from firstdir
# render surf: don't warn missing "-mean-" in bfloatpatt of single subject
# put better default rgbnames into SURFACE button tcl scripts
# offset startup of successive csurf's, include pid in title
# add INIT/FLIP to setup funct (for no-align hi-res)
# Paintfile: sort real/imag phase before stats (_i at top -> def init load sig)
# expand width of fieldsign listbox entries, dropdowns
# revert 0.9 -> 0.8 in csurf.dat header to match tarfiles (TODO: newvers: 1.0)
# addfieldscan: find_retin_borders parms/GROWBORD (Calc Fieldsign panel)
# findretinborderscmd: run find_retin_borders via borders.tcl script
# select_{eccen,polar}: 1st time, sort complex infix-stripped to top
# fixed 3 border.tcl parms that had "def" not "$page" (fix:2cogsci,3buc05,3zak)
# add fclu=sig+clustFmask to mask check
# mknewfunct allows inserting functional session inside an already-made subject
# change medtestrender regdat,rawdata args to relative (like surftestrender)
# if no select on return from select from list popup and 1 avail, select it
# medtestrender: no longer pass -stat{yres,xres,nslices} to tkmedit
# helpwin setupfour: add right gif (650 pix tall) scan
# initial select of "mm" or "frac" sets normdsampsearchflag (tksurfer PNT,T,S)
# Preferences to dump only cmds to a file
# forcebrik LSB -> MSB HEAD fix message written to cmds-only file
# statbrikstem accepts *Coef*+orig.BRIK (in addition to *+orig_?+orig.BRIK)
# save/pass -wmfillthresh parm to reconditioned fill for dolphin hack
# log writes of csurf.dat (too much clutter?)
# pass nondef -wmfillthresh to tkmedit so edit->white works below wmfillthresh
# define missing stimcycles if VOLAVG (TODO: others?)
# fix tkmedit cmdline: -sub{real,image} => -up{real,imag} 
# fix intro'd bug: add close $id accid. rm'd back into writearrayparms (!)
# add new help: smoothcurvinflatesulchires
# Preferences -> Change Subj for Curr Session to change namefile
# double-click main sessions/scandirs label also raises popups
# rearrange Preferences menu, add more separators
# make MGHTools -> Register Surfer look in FSURF_DIR for tif targ!
# tmp omit read_binary_patch from scripts b.c. setfile patch callback does it!
# mghsphereregcmd warns missing morph register targ (.tif)
# samp2subj pass1: if real, don't skip surf2surf
# samp2subj pass2: if real, don't skip surfclust (N.B.: tstat infix="" => _h)
# samp2subj pass2: if real, look for AFNI -tstat- not csurf-internal -stat-
# add mris_sphere (all default) to MGH Register sequence
# putback mk{3d,flat}script setfile's (tksurfer.tcl w/blocked callbacks work)
# allow single pos/neg delay for rev'd scans in rawaverage (new parm: revtTRs)
# report as commented-out, tmp tcl surf/med script name/cmds in cmds-only log
# popup reports name of cmdsonly file on close
# fixed bug in singlsub randblock not auto-updating StatMask Paintfile
# add wmfilter expert parms: Gauss+trunc, Gauss filter width
# fix rawaverage label after rawaverage shiftrev made like fullFT delay
# add entry for sample surface for 3D stats to phase combine panel
# menu rename WM Filter -> Filter WM (agree with Fill WM)
# don't make old COR dirs (but still do make ~/mri/orig)
# support shuffle stats in parms, addfourscan, fouriercmd
# PAINT Import External Stats phasestatformat=afnibrik if BRIK, if bfloat overrd
# change ps opts from af to uxww for Linux
# rm foundbywhich, canwriteormake (now in wrappers.tcl)
# SetupAlign/Funct "init round" tick INIT old/new regdat, report curr else def=1
# fix addfunctscan showstopper: setinitroundflag before defaults created
# allow FUNCT=>SUBJ button to pass .mgz file to tkregister as MOVEABLE
# change confusing checkbutton label on main interface: surfload -> load2surf
# functscan READ HEADER reads mgh/mgz header w/tkmedit to fill in panel
# getuniqwfilelist checks -[rl]h.w there before strip chars
# getuniqwfilelist accepts *.mgh files (put into Paintfile dropdown)
# silently fix missing TAXIS_FLOATS for auto-set TRs, put note in log
# rawavg: also warn non-informative phavg/surfavg default names not changed
# fieldsigncmd: pass scandir (for new write curvfmt fs/fm functs)
# rename global $scandir to $iscandir (usu. contains "image")
# rename prc getfunctscandirslist -> getfunctiscandirslist
# redundant set iscandir $page's for safety (usu. done by browse notebook)
# add "jt" to View Functional Data panel colscale
### detailed change subversion 35z (3May2014)
# fourier always -fout: N.B.: won't match _r,_i if permute test (for compare)
# cpregcmd copies/reports/updates rounding policy
# paintcmd: if permtest, also paint _p (fourier generates if permtest)
# paintcmd: if permtest, paint/overwrite amp(r,i) '_f' wfile w/real _f from 3D
# getuniqcomplexstemlist: don't trim _p
# select_complexstatsource: asks to reset Data Type cplx (callback does cpx chk)
# paintcmd: if permtest, also run surfclust on _p to get _q (re-use F parms)
# fixswfileprefs: 1sub phase sig+mask: try in order: _f,_h,_p,_q else no mask
# select_complexstatsource: catch -no_mask-, better error checking/messages
# better button name: sig+clustFmask => sig+(clust)Fmask
# better arg: tkmedit -mask (vs. -statmask) parallel to -real,-imag
# medtestrender loads 3D _f mask if sig+(clust)Fmask selected
# fourier panel: expose existing 3D Cluster vars clusterrad/clustervol
# medtestrender mask checks/uses _h if found (N.B.: requires at least _f)
# fouriercmd: also run 3D clust _f=>_h with AFNI 3dmerge for brainstem mask
# shrinkcomboarrows, squish labels/buttons, lengthen entries => smaller
# for fsaverage: add/rec inflatedext2=inflated_avg, load into surface combo
# View Functional Data "fsavg" chk does 1-time mri_surf2surf, load to fsaverage
# single subj -> fsaverage: check/warn fsaverage surface missing
# paintcmd defaults missing permtestcnt (PAINT first action on older config)
# paintcmd: if 3D _f file there, paint it, else old square amp of painted _r,_i
# avgsurfcmd: run make_average_subject w/curr Cross Subj Average panel subjlist
### ==== dist: csurfsrc-140624.tgz ====
# fix {mgh}flattencmd mis-handle Use Existing response
# {mgh}flattencmd warns/allows re-flatten already flat
# if fsavg, check if surf in fsaverage (N.B.: need Return in surface combo) 
# try/rollback set name fsaverage to reload combos: too many surftestrend hacks
# fix crasher: need braces on varname with "...<dash><num>...": ${paint-3D_f}
### ==== dist: csurfsrc-140906.tgz ====
# widen custom translate entries (too easy to miss 100 vs. 10)
# block single quote, redirects in runacmd cmd string, popup error
# reorder mris_flatten -distance parms into cmdline order
# mghspherecmd: $bindir -> $mghbindir (just uncovered -> trying sphere only)
# recognize inflated/sphere steps as a kind of "inflated" surface
# surfaces combo also filled with "inflated????" and "sphere????"
# add AFNI button to rawaverage panel
### ==== dist: csurfsrc-141017.tgz ====
# omit broken "no panel" checkbutton til surftestrendernopanel updated
# runahiddencmd: run cmd in bg, logged, but w/o button
# runahiddencmd for nmovie, mpeg_play to log and avoid writing on csurf cmdline
# no remaining 'eval exec's easily replaceable (e.g., contain redirects)
### ==== dist: csurfsrc-141018.tgz ====
# mghflatten: ?h.full*.patch.* => "full", else use more stringent "occip" parms
# 35zg: freshen notes on binaries included and/or needed above
# fillcmd/surfhirescmd: warn CORdir precendence if both CORdir and mgz present
# wmfilterhirescmd: warn CORdir precedence (try possible 3 pairs before fail)
### ==== dist: csurfsrc-141104.tgz ====
# trim wintitle bgsequence so no trunc long patchname, lengthen patch dropdown
# debug put new session inside existing subject
# when flatten done, reset patch combo to outp if there (was reset to first)
# also load inflated combo w/sphere.reg???? steps
# mghflattencmd now recognizes full*.patch* input patch as a "full"
# new functscanlists(def,statformat): mgzsingle, cbx:select_statimage can set
# paintcmd: rm unused infixlist1,2 junk, allow ExtStats read mgz special case
# readheader: read/correct actual mgz pixsize/thick (was default to 1.0)
# if MGHTools enabled, rm unneeded back compat from MGHTools and Help menus
# prefix afni cmds with: env AFNI_VERSION_CHECK=NO <cmd> ... (for server down)
# fix 3 stale 'ps' options for Linux (csurf startup crash Ubuntu)
# VOLUME-STATS doesn't replace 3D _f with _h if StatMask Paintfile is _f
### ==== dist: csurfsrc-141207.tgz ====
# if empty surfext, surf-missing popup informs existence opposite hemi surfs
# AVGSURF button now auto-fixes giant triangles in poles of inflated_avg
# catch grep -c csurf to make csurf source'able again from wish8.5 prompt
# allow config/save 'w2' (RGBY) wheel color scale on View Functional Data panel
### ==== dist: csurfsrc-150220.tgz ====
# fix typo (rm 's') crashing non-hi-res inflate: inflatescycles->inflatecycles
# load curf surface combo with orig? for import hacking (was orig,orig1,orig2)
# change def morphtarg to buckner40 (for MGHTools->Reg) to match def recon-all
### ==== dist: csurfsrc-150308.tgz ====
# ask to auto-convert AFNI BRIKs provided by FIND to recon-all panel
# recon-all panel: fix start in same dir for second+ input files
# fix kill RECON-ALL purple: hand-kill recon-all's+tee, rm IsRunning files
# Preferences -> Bigger Logs: 18 lines each vs. 7 lines each
### ==== dist: csurfsrc-150322.tgz ====
# make fsaverage a var for global alt fsaverage
### ==== dist: csurfsrc-150410.tgz ====
# ridiculous/effective hack for yosemite slowdown: tmp xterm over setup panels
### ==== dist: csurfsrc-150423.tgz ====
# update to new trace syntax
# add "vd" CARET VanEssen "videen-style" to View Functional Data colscales
# Fourier panel PAINT skips surfclust if cluster area is zero
### ==== dist: csurfsrc-150502.tgz ====
# SubjTools -> Re-make surf 1hemi only tessellates 1 despite possible stale 
### ==== dist: csurfsrc-150513.tgz ====
# mknewfunct: fix "mvlog mv ..." bug in attempting to mv aside session
# middle-click "fsavg" button sets oppfsavghemiflag (disp on opp fsavg hemi)
# change to subject at startup if csurf started in subject's script dir
# SubjectTools -> Inflate Surface Patch (hi-res): tksurferinflatepatch
# tksurferinflatepatch allows write tiffs
# reconallcmd warns missing MGH license file
# tksurferinflatepatch: interactive initial pose adj, final surf inspect
# MGHTools -> Register Surface (to symm) wired up
### ==== dist: csurfsrc-150728.tgz ====
# don't blow away rendertype copied to unconfig'd from Fourier phasetype
# cp prev button on ResetToDefault line
# "cp prev" button on Render panel ResetToDefault line
# "cp prev" button on Fourier panel StimCycles line
# add ColorScale: "w4" (fred tono) to addrender, "jt" -> "jet"
# add Fourier and Render "cp prev" confirm/cancel panel
### ==== dist: csurfsrc-150823.tgz ====
# fixswfileprefs real+mask confirmalert's self-cancel if yosemite_hack
# fix quote smooth_curv command for fixing inflated_avg surf (crashing?)
# reconall warns/explains empty subjdir (vs. ask tick to use edited wm)
# Make Scandirs, Find/Copy Raw better warning if sesion is "__nosession__"
# put TextEdit first in editor list before execrable xedit (!)
### ==== dist: csurfsrc-150910.tgz ====
# SURFACE-STATS skips checkstale{regdat,wfile} if subj fsaverage
# turn off surfclust in SAMP2SUBJ (2nd pass) if clustarea not > 0.0
### ==== dist: csurfsrc-150912.tgz ====
# clickable table of contents of ~320 help panes, one clearable helpwin
# add yosemite_hack to help table of contents
# cleanup startup sequence (check CSURF_DIR before load tix)
### ==== dist: csurfsrc-150922.tgz ====
# better error message on refuse to overwrite NIFTI already conv from BRIK
# startup check tcsh installed (for recon-all), warn/allow start anyway
# check tcsh installed also for reconallcmd, avgsurfcmd w/start anyway
# change reconall/avgsurf script to require tcsh (maybe tcsh installed w/o csh)
# Setup Funct panel "SubjectDir Target Image Set" now controls stats underlay
# if ~/.csurfrc exists, read "export name=val" to tcl env if tcl var exists
# menu item to write .csurfrc using current state of subj/sess/FSURF dirs + vi
# fixswfileprefs: ImportStats no-matching-mask-err popup->log, rm yosemite hack
# env-overriding dotcsurfrc read/write Csurf.app only (Csurf.app can't see env)
# add sphavglists(00,clustsurf) to pick surf used by surfclust for area calc
# add new LUT flag helpfiles, curvtick/offset/cvfact line to all-help
# Render panel: add/cpprev botedgelutflag,zerosymmfadeflag
### ==== dist: csurfsrc-151010.tgz ====
# fix writelog if run dir moved out from under running csurf
# old: #! /usr/bin/env wish8.5 => now fails: env doesn't pass DYLD to subshell
# have to go back to sh vs. tcl comment startup trick to pass DYLD_LIBRARY_PATH
# new: DYLD_LIBRARY_PATH=$CSURF_LIBRARY_PATH exec wish8.5 $0 ${1+"$@"}
# mk3dscript, mkviewcutscript, mkflatscript source readenv.tcl
# surfercmd: tclenv->file, if $csurftclenv != "", readenv.tcl uses it to set
# rm env: fixinflatedavg, fieldsigncmd, findretinborderscmd
# rm env: surftestrendernopanel, medtestrender, surftestrender
# all help: add omitted "val:" line help for "W" button
# R-click help for all SessionTools setup panels
# R-click csurf help from intermenu, above "Structural"/"Functional"
# add explicit csurf "h" help button to lower right (parallel to tksurfer etc)
# medtestrender checks functscanlists($page,tkregtargdir) exists old csurf.dat
# rename yosemite_hack mac_appnap_hack
# surface combo now includes $hemi.{orig,inflated}* at end, better sorting
### ==== dist: csurfsrc-151121.tgz ====
# use wrapper26nm.tcl onefindpanel for onehelp window in allhelp
# finish R-click help (hemi, 3d radios, surf radios, other 3d vol)
# add hemi,3dradios,surfradios,other3dvol to help TOC
# rename ifont->ifontb, add ifont for allhelp
# italicize (bold/unbold) main allhelp headings
# file chooser height 400->500
# check/block/warn "#" in recon-all pathname (subshell fails)
# move replchar to wrappers (needed by helpwin there)
# viewonehelp: fix alt-f to work on Linux
# viewonehelp: focus on helptext, position cursor beginning
# fix 3 selected text widget logs black on linux (-selectforeground black)
# mid-click on csurf "h" button brings up full help
# Re-Make Surf (hi-res): block use mri_fill 
# block/explain {SURFACE/VOLUME}-STATS if this notebook page not config'd
# prev change forces error/explain on trying to misconfig FunctDir or SphAvgDir
# fixsurfaces trace for fsaverage: if inflated_avg there, use it
# add View:Save/Goto and F3 VTK write surf to all-help
### ==== dist: csurfsrc-151230.tgz ====
# better on-panel instructions for Run recon-all
# stop "Now, locate single sub ..." message from wrapping on "functional"
# block/explain non-integer Num TRs to timeshift
# block/explain non-integer Stim Cycles Per Scan
# Fourier panel calculates angle_offset for 1sec delay ($page,angle_offset1sec)
# add angle_offset for 1sec delay to View Functional Data
# fix reconall ADD/DEL file not found bug: unset mghinprawscanfiles(last=num-1)
# better: "Now, locate single sub dir containing surf for this funct scan"
# squish padx RIGHT LEFT BOTH for freakishly large Fedora Helv 14
# earlier warn wrong render type (View Funct/SphAvg Data menu before set dir)
# SURFACE/surfercmd: env=>opts: late csurftclenv read broke openwin configs
# prev makes Preferences->SmallScreen work again for SURFACE button
# load2surf bug (forgot to global inflatedext2)
# add new complex/real smoothing to all-help panel
### ==== dist: csurfsrc-160130.tgz ====
# 35zp: wrong type (funct/sphavg) warning now closes setupscans panel
# editfile: TextEdit case (irrelevant geom arg -> permissions err begin 10.9+)
# change: exec $editor $file >& /dev/null & => exec open -e $file (no multiple)
# add setenv SUBJECTS_DIR to recon-all script (ElCapitan no longer passes)
# add TkStrip to all-help panel
# shift-mid-click on VOLUME opens tkstrip on currently selected volume
# differentiate choosedir entry title strings (Choose vs. Enter)
# choosedir (mabye dir/file) uses entry title vs. "Choose Directory"
# inline env AFNI_ENFORCE_ASPECT=YES for afni
# fix auto-cancel ViewFunct/Sphere type (no tkwait, set makingsetupscan)
# convert mritype entry to autofill combo to allow loading non-standard volumes
# localize csurf help next to each widget code
# [see NOTES for combobox listbox fix details]
# 6 on main win: tixComboBox -listwidth 208 vs. -options listbox.width 25
# 30 combos on notebook pages (all -listwidth <pix> only), adjust some
# more bakcompat in addrawavgscan for 000319CF
# if paint single subj onto fsaverage, allow use fsaverage-only patches
# shift-middle-click fsavg sets up: curr -> fsaverage -> othersubj
# R-click fsavg gives widget-specific help (click anywhere else: setuprender)
# disablecallback @colscaletype bind stops select_colscaletype reset config'd
# add shrink/morph help to all-help panel
### ==== dist: csurfsrc-160411.tgz ====
# add samevtx,wmgmext to allhelp
# add samevtxthickflag as "Same" to addfunctscan, pass to tksurfer
# add Preferences -> Clear Logs (clearlogs)
# pass functscanlists($page,paintext) to tksurfer -wmgmext (live paint)
# fix bak compat addrender missing paintext used in surftestrender
# autoconfig functscan type (block err) on 1st render-open of prf2sess'd SamSrf
# setupsphavgcx blocks open single scandir config'd as functscan
# setupsphavgcx blocks open image/prf (e.g., unopened single subj conversion)
# mksphavgdir blocks make avg scandir named "image/prf"
# better csurf -help (was version mismatch crash!)
# rename SamePlane StructDir -> SamePlane AlignDir
# cbx:select_{raw,sig}toavgdir: allow extstatscan, not just functscan
# always warn/nag too-long (>7) paradigmfile stem, space vs. tab if toolong
# add "All Help In One Panel" entry to Help Contents
# add "m" tick render panel 3D smooth for parm $smoothoverlaymaskflag
# fix misleading labels (units=vox,not mm)(connected,not rad) for 3DClust
# fixed 3DClust labels here: Fourier panel and Import External Stats panel
# changed defaults to respect -dxyz=1: clusterrad:10->1, clustervol:150->40
# changed surfclust default to 150 (what help says!)
# change killbox -> killboxOK (wrappers proc name change not propagated!)
# Mac: force start from xterm, not Mac Terminal (nmovie fail, then can't kill)
# Fourier: no tix opts: Painted Vertex List Files was inserting "image/align"
# checkconcurrent ignores running nmovie
# getfunctimageslist filter TmpClustMask+orig, MY_AREA+orig from "Image File:"
# Setup Funct/Align ALL=>T catches inconsistent target TR's (e.g., w/diff reps)
# live sample/PAINT: warn using midpoint when normsearch OFF w/non-0 range
# if using midpoint, also set max's to it to override unset tksurfer def=0.4
# N.B.: left midpoint contrast w/paint_surf,write_label_tcourse set max to min
# 35zr: allow start from Terminal with -f
# add UniqVtx tick to Setup Align/Funct to make PAINT dump uniqsamp label
### ==== dist: csurfsrc-160527.tgz ====
# visually separate off options for PAINT on Setup Funct panel
# change CLONE FUNCT to just copy everything (was make links to big files)
# setting minvol (clustervol) to 0 skips 3D clustering (like 2D disable)
# rename uniqsamplabelflag -> normdsampuniqvtxflag, also pass to tksurfer
# normdsampuniqvtxflag forces normdsampuniqvoxflag (like tksurfer.c)
# add nsamp_uniqvtx to All Help
# addrenderscan fix missing bak compat default for new uniqvtx var
# fouriercmd: forcebrikMSB _h BRIK output (from apply clustermask)
# fouriercmd: forcebrikMSB fourier pre-smooth out (smooth prob?)
# add new write .off and .stl help panels to All Help panel
# fix paintmultibrik bug/typo: uniqsampvtxs2labelflag -> normdsampuniqvtxflag
### ==== dist: csurfsrc-160624.tgz ====
# load "surface:" dropdown w/non-hemi-prefixed GIFTI surfs incl flat
### ==== dist: csurfsrc-161004.tgz ====
# fixinflatedavg: fixed curv/sulc not being written out for AVGSURF
# fixinflatedavg: use $CSURF_DIR/subjects/fsaverage-ADDITIONS FIX-POLES labels
# add hist button help panel to all-help
### ==== dist: csurfsrc-161217.tgz ====
# add $hemi.surftmp* to surfaces dropdown (like tksurfer, tkmedit)
### ==== dist: csurfsrc-170320.tgz ====
# add tkmedit CORONAL/SAGITTAL/HORIZON to all help window
### ==== dist: csurfsrc-170621.tgz ====
# missing startup env var: better err: both tcsh (setenv) and bash (export)
# explicit tixSelect -padx 11 fixes VBOX update def reset of "Views: lat med.."
# improved cmdline help, also accept --f (force start csurf from Mac Terminal)
# if Ubuntu/Debian, use ldd to check of libXp missing, warn and explain fix
# if Ubuntu/Debian, turn doublebufferflag OFF (tmp, til fix, so startup works)
# new File menu items to open xterm/gnome-terminal in subj/sess scripts dir
# add gl button (glTF,*.glb) all-help panel
### ==== dist: csurfsrc-171018.tgz ====
# load non-pre-appended *.vtk, catch/warn on click SURFACE (CHROMA)
# add 36 new helpfile to All Help Contents
### ==== dist: csurfsrc-180125.tgz ====
# VOLUME-STATS can open no-functionals fs scandir for F4 tkmedit SURFPAINT
# add tkmedit surfpaint to all-help panel
# fix crash on Make Scandirs, Find Copy Raw w/invalid session
# SURFACE passes curr csurf iscandir tail (e.g., image/pol1) to tksurfer
# fix SURFACE button crash on initially empty iscandir (rm tmp 180520 release!)
# tksurfercmd guesses 1st funct for annot2roi (req's SessionTools once open)
# setupscans updates scandir entry on go back and show first page
# "csurf -h" err if CSURF_LIBRARY_PATH not set
# CSURF_LIBRARY_PATH not set err before try load tix (prints after load fail!)
# explicit -padx 11 fixes Linux extra-wide "Slice Ord" tixSelect
### ==== dist: csurfsrc-180621.tgz ====
# add separated tcl script helps
# tmp disable doublebuffer for CentOS 7 (3.0+ kernels) 
# "csurf -db" or "csurf -sb" to force start doublebuffer or singlebuffer
# sort fix{surface,patch} glob list before re-sort (10.6=sorted, CentOS7=rand)
# CentOS 7 back to doublebuffer if nvidia kernel module there
# add "clo" tickbox help to csurf allhelp panel
# block all abspath paradigmdir's in deconvcmd, rawaveragecmd (concat)
# fix afni crash newer Mac: add to DYLD if exists /opt/X11/lib/flat_namespace
### ==== dist: csurfsrc-190208.tgz ====
# setup align/funct page sets iscandir so AFNI button goes to right dir
# also fix 'poles' on fsaverage pial (for final display, not sample)
# AVGSURF also fixes fsaverage pial 'poles' (for final disp, not sample)
# new $softtruncphase helpfile: truncphasesoft
# check in CSURF_DIR for either .license *or* license.txt (fs6.0 on centos7)
# bin/noarch/recon-all5.3b: copy of recon-all w/new opt: -all-skipstep1
# add "start from edited orig.mgz" tick to Run MGH recon-all panel
# readheader (READ HEADER) init's alignscanparms(brightness) to 1.0 if align
# add View Functional Data tickbox for softtruncphaseflag ("Sft")
# ### begin spaces-in-PATH nightmare
# better example on error popup HOWTO fix path with spaces (rm'd: didn't work!)
# make space-safe: cdlog/mkdirlog/rmlog/mvlog/cplog (replace some stray exec's)
# csurf -f also overrides spaces in PATH
# backslash (new proc) bindir/afnidir/mincdir/noarchdir spaces for runacmd sh
# backslash spaces in tcl source file args
# MGHTools -> Run recon-all warns/cont's if space(s) in FSURF_DIR, SUBJECTS_DIR
# rm popup warning allowed tixDirList to work correctly w/path with spaces (!)
# choosedir: strip curly braces in path-with-space added by glob (found it!):
#  spaces OK: mknew{subject,funct}, choose{subject,funct}dir, cpdir, avgsurfcmd
#  spaces OK: opencmdsonlyfile, "Set {Subjects, Funct Sessions} Directory"
# choosedir strips double-slash seen by tcl file exists but not by tixDirTree
# backslash-quote maybe-space-containing DYLD cmdline passed to afni
# medtestrender: backslash spaces in -real, -imag, -mask args passed to tkmedit
# backslash spaces in runacmd pwd report
# {l}backslashspaces runacmd args/listargs that possibly contain space (~135)
# use AFNI_PATH_SPACES_OK=YES if detect FUNCTIONALS_DIR space (multiple)
# afnicmd: if no namespace fix, omit empty dyld (env uses as arg not pre-arg!)
# refactor dyld/path spaces runafni proc for afni{cmd,allcmd,structcmd}
# ### end spaces-in-PATH nightmare
### ==== dist: csurfsrc-190722.tgz ====
# AFNI_PATH_SPACES_OK=YES: avgstruct,reconall,stripinit,3dvolreg,fourier
# VOLUME button: if volume not found, suggest found *.mgz's from vollooklist
# block AFNI,AFNI-ALL buttons cd'ing, e.g., if 3dvolreg/2swap running in bg
# re-flatten sets subprocessredo to avoid second confusing overwrite query
# add morph_wcpx2 to all-help
# add im,im2,im3,im-label to all help panel
# use recon-all6.0b w/-all-skipstep1 option for fs6.0 (was just fs5.3)
# SUBJECTS_DIR crasher!
# don't complain about xterm if not Mac!
# change default "Surface for Sampling 3D Data" orig->white (orig: S-I bad!)
# add selecthemi to fieldsigncmd to allow doing fieldsign for one hemi
# "Update Subjects/Sessions" warns when subject changed to match curr session
# MacOS 10.15/kern=19 fast tk after logout/in w/o hack: add -[no]hack opt
# -[no]hack opt passes -macappnaphackflag (-1,1,0) to {surf,med}testrender
# -[no]hack opt passes -macappnaphackflag (-1,1,0) to tk{surfer,medit}cmd
# allow multiple csurf cmdline flags
### ==== dist: csurfsrc-191216.tgz ====
# change default startup volume to orig (was T1)
# csurf accepts subject or session dir as arg
# also load surface dropdown with $inflatedext? $pialext?
# add insidesurffact to all help
# load all *.obj (regardless of hemi) to "surface:" dropdown
# add Flip (FlipHemi) to all help panel
# load all *.srf (regardless of hemi) to "surface:" dropdown, fixsurfaces
# fixsurfaces (fill "surface:" dropdown upon new subj): load all *.obj,*.srf
# fixsurfaces: only strip hemi from globbed surf tail if present!
# tksurfercmd: special case for non-freesurfer-style *.obj,*.srf names
# => w/no surfext prefix, can't tell if intended file is ?h.*.obj or *.obj
# => parallel to tksurfer:make_filenames() -> not found, try no pre-append
# warn read *.srf (but not *.obj), kill popup after 8sec
# chklefthandedsurf: change subject re-arms chk for left-handed
# add lights,blufact to all-help
# fix bug in -nohack option
### ==== dist: csurfsrc-200629.tgz ====
# use -listcmd to live update patches dropdown (e.g., tksurfer wrote new)
# bgsequencewin optional title, shows inputs for Flatten, Sphere/Register
### ==== dist: csurfsrc-200629.tgz ====
# recon-all start w/edited orig.mgz works MGH FreeSurfer7.1.1 (was 5.3.0/6.0.0)
# require freesurfer buildstamp sub-sub-version for safety
# also chk editor: /System/Applications/TextEdit.app/Contents/MacOS/TextEdit
# dist/patch/Tix8.4.3/DirList.tcl: strip vpath/npath double-slash crasher
# Preferences -> Newest Functional At Top
# subject/sessions auto select if only one pattern match
# NormSearch default now frac=0.8 (paint/paintmulti now chk for thickness file)
# fix didn't pass -softtruncphaseflag to tksurfer in Render panel
### ==== dist: csurfsrc-210614.tgz ====
# Setup Sphavg help: open correct help rather than just warn
# Preferences -> Cover/Uncover Speedup Hack (mac_appnap_hack) if Mac
# reinstate macos 10.{14,15) mac_appnap_hack=1
# procs using mri_surf2surf check/block '#' in {FUNCTIONALS,SUBJECTS}_DIR
# add appnap hack because of ugly startup
# showlogs raises main csurf window (helps w/many csurf's)
# double-clk on render panel raises csurf main (can't do diff proc tksurfer...)
# change Help Contents view 47->48 for less wrap (N.B.: helpwin is 50)
# movie panel plays mpgdir mp4/m4v's w/QuickTimePlayer (mac), vlc (lnx)
# all-help panel: separate read write (SurfaceR,SurfaceW), mv c2lab to Label
# Setup Structural Scans auto-converts *.nii (AFNI 3dcopy)
# double-click setupscan panel raises csurf only from bottom buttons frame
# block check scandir callback from set iscandir if aspect equals struct
# double-click setupscans upper-left "Session:" label to get current location
# setup structs: 3-way opt (cancel, use, don't use) if no -zeropixwidth found
# list other brik2cor options on setup struct panel
### ==== dist: csurfsrc-220324.tgz ====
# longer listbox for surfaces (fsaverage)
# getcmdpidnam for add'l cmdpid vars for better kill w/multiple bitmaps wins
# redundant helpwin on Expert Preferences WMFill,Flatten tabs
# repeat Help on ExpertPrefs: RmSkull,FilterWM,FillWM,InflateP,Flatten,Sphere
# fix SubjectTools -> Inflate Surface Patch (also calling mk final surfaces)
# rotate any subj containing "cereb" in name to posterior (vs. side) view
# recognize IRIX64 so libTix8.4.3.so loads on sgi
# print README.txt tarfile date (if there!) into csurf title bar
### ==== dist: csurfsrc-221002.tgz ====
# new procs: getafnitaxisoffsets, getafnimbaccel
# new saved functscanlists parms: mbaccel, taxisoffsets
# Setup Align/Funct: add Multiband Accel Factor, Slice Time Offsets List
# READ HEADER ask biff already-read TAXIS_OFFSETS (b/c 3dvolreg non-propagate)
# addfourscan: UseTAXIS vs. UseSliceOrd, check/warn parms
# fouriercmd: can use fourier ... -taxisoffsets <TR> <sl> <s2> ... <slast>
### ==== dist: csurfsrc-230925.tgz ====
#  [tmprelease: 231219]
# cbx:listcmd_mri for mritypes combo to force update before dropdown
### ==== dist: csurfsrc-240426.tgz ====
#  [7 tmprelease's w/no csurf update]
# hack^2: slow mac10.15 csurf log hangs tkwait/GLwin if appnaphack so blk if log
#  [tmprelease: 240709]
### ==== dist: csurfsrc-241112.tgz ====
# change startup subject to fsaverage if it exists
#  [tmprelease: 250217]
# fix forgot ${smoothwm}* surf ext patterns in "surface:" dropdown
# versions to startup stdout, regularize title bar versions
#  [tmprelease: 250217]
# turn off appnap for all apple silicon (kernvers=BigSur20+)
### ==== dist: csurfsrc-250507.tgz ====
# empty tarfiledate -> none (from local compile vs. mk0 insttmp tarfile)
# setdefaultparms: new: renderscanlists(def,cpxangrealampflag) 0 ;# ignore disp
# surftestrender: pass $cpxangrealampflag by env to scripts
# addrenderscan: bare tick to ignore dispersion w/smooth (cpxangrealampflag)
# addrenderscan: cryptic "m" tick (smoothoverlaymaskflag) explain if changed
# setdefaultparms: new: renderscanlists(def,smoothstepsstat) 5 ;# stat only
# surftestrender: pass $smoothstepsstat by env to scripts
# addrenderscan: add entry to distinguish data and stat smoothing
# addrenderscan: rm "m" tickbox (smoothoverlaymaskflag now only used 3D/tkmedit)
#  [tmprelease: 250516]
# update/homogenize/improve View Functional Data panel dual-field labels
# fix change to fsaverage if started from scripts dir
# def smooth way down if fsaverage: ecc:20/20->3/2 (rend,stat), pol:10/10->2/1
#  [tmprelease: 250529]
# add remaining SMOOTH types to all-help panel (valonly,stat,grad)
#  [tmprelease: 250617]
# paintcmd (PAINT button) also paints new fourier.c _c coherence output
# [View Functional Data will already load new *_c-$hemi.w]
# All Help Contents defaults to all-help
# fourier panel Painted VertexList Files (outputs) adds _c coherence
#  [tmprelease: 250703]
# addrenderscan: add sig+coher PhaseMask:, fix select buttonnames, shrink title
# select_complexstatsource asks reset thresholds on select "PhaseMask:"
# extract ask reset code to proc askresetcmplxthresh2sane
# reset also chks $renderscanlists($page,fourierampflag): sm sqrtF vs. lg FTamp
# tick/untick "FTamp" triggers ask reset using askresetcmplxthresh2sane
#  [tmprelease: 250808]
# csurf: add Expert Preferences->Views alt font, pass -fontfile to tksurfer
#  [tmprelease: 250810]
# Setup Calculate Fieldsign, Borders: dividers for fieldsign vs. grow borders



#INPROG: cross subj FDR

# TODO: debug occasional initial 2min 100% CPU of wish8.5 process on VOLUME
# TODO: now easy way to pop csurf window from tksurfer (diff process)

### TODO: check exec ... >& ... OK with sh/bash in Ubuntu!!
#csh:  >& file       (new bash now accepts this, but sh doesn't)
#sh:   > file 2>&1   (safer sh bak compat, different order than pipe!)
### TODO: check exec ... |& ... OK with sh/bash in Ubuntu!!
#csh:  |&            (new bash now accepts this, but sh doesn't)
#sh:   2>&1 |        (safer sh bak compat, don't forget final pipe!)

### TODO: auto-load/read .label files in VtxListPref? considered w/samsrf
### TODO: already skipped w/samsrf: complex-val? real? all labels? nameconv?

### available wfile infixes: _l,_m,_n,_o,_u,_v,_w,    _s,_z
### TODO: amp(_x,_y) -> _c
### TODO: dispersion for _x,_y -> _o

### TODO: add Mariam autoreg
### TODO: add Mariam FSL ICA motion correct

### TODO: add T2, rm PDbrain, bigger entry (processing step on way to "brain")

### TODO: N.B.: .afnirc *is* read with afni started with AFNI button
### TODO: check ~/.afnirc (req's ***ENVIRONMENT line before VAR = VAL lines!)

### TODO: 10.11: test AFNI, recon-all, avgsubj, inflated3d, [4th] all subshells

### TODO: rm backslash from start bracket multiline  (1/3 done)
### TODO: regularize confirmalert backslashes (1/3 done)

### TODO: compile nedit (only needed for Mac for fullscreen)

###INPROG!!: code to use oppfsavghemiflag
## xhemireg just reverses 3D vol, then usual run!
#vi /Applications/freesurfer/bin/xhemireg
#mri_surf2surf --help
###TODO: fix all splits as follows to discard last empty element!
# [split [read -nonewline $id] "\n"]


###############
# YOU ARE HERE
###############

#TODO: wrap all open's in catch
#TODO: could port ftmpcsh/gtmpcsh to bash (N.B.: but MGH needs csh anyway)
#TODO: smooth single sub stats *before* surfclust?
#TODO: insert _t into surf2surf real out, use _v for surfclust'd tstat
#TODO: figure out why run fs-make requires set iscandir? (used last scandir)
#TODO: cmdsonly: touch tmpfile, echo << ZZZ >> tcllines (vs. just comments)
#TODO: file manip by csurf tcl not (c)sh scriptable -> put in message or script
#TODO: cross subject permutation test stats -> postpone
#TODO: afni.log records all commands
#TODO: no effect of nm/mx/av on timecourse sample
#TODO: debug non-appearing but config'd average panel (but lost example dir...)
#TODO: ugh: complex bfloatstem lacks +orig, real bfloatstem has it
#TODO: check any other downstream bfloat users to be sure they accept BRIK
#TODO: flip colorwheel inset if polar2 type (detect hemi plus reverse state)
#TODO: check xsubj rm bfloat stats OK (only prob w/VOLAVG)
#TODO: check all combos: med/surf, single/cross-subj, real/complex, stat/nostat
#TODO: add read statmask logic to real-{views/flat}.tcl (TODO:->cmdline)
#TODO: make hi-res pial: pialwhitethk.tcl script for above hi-res
#TODO: put "clust" into *subbrik label name* of 3dmerge output??
#TODO: change to mritype w/.mgz, then trim to try COR dir if not found
#TODO: remove csh dependence in csurf -> finish FreeSurferEnv.sh
#TODO: t-stats always re-run deconv w/all 1's for all cond (like Full_fstat)
#TODO: 3dmerge save numbered clusters instead of 0/1
#TODO: rev singlescsan w/3drawavg, FOURIER, no PAINT, render3d stale floatstem
#TODO: only 1 alignscan(imagepatt) per sess: fails w/2 align scans w/o Unset!!
# --need pg-specific, but also back compat; (imagepatt) + ($page,imagepatt) OK
# --COPY ALIGN TO ALL FUNCTS useless w/two aligns: need COPY PREV TO ALL FUNCTS
#TODO: count concatenated 1D file lines in case missing CR
#TODO: can't unextstat accident extstat'd functscan (1st regrok extstatfunctims)
#TODO: viewallscandirs needs to distinguish xsubj (or ignore them!)
#TODO: add 3dmema, use 3dttest++ instead of 3dttest
#TODO: allow AFNI 3d smooth of rawaverage
#TODO: sphavg warn if found .w files but none matching complex infixes
#TODO: add cmdline getenv/opts when 12 new light0x-etc vars opt'd tksurfer
#TODO: update surftestrendernopanel to mostly-opt cmdline like surftestrender 
#TODO: dispersion index occasionally goes above 1?
#TODO: restored cbx in extended select doesn't autoload
#TODO: afni: -DAFNI_ENFORCE_ASPECT => doesn't work
#TODO: put sphavglists into functscanlists, user setupscsans, for multiscandirs

############################################################################
# startup checks
############################################################################
### command line help
set forceuseterm 0
set forcedoublebuffer 0
set forcesinglebuffer 0
set appnapstateforced 0
set mac_appnap_hack 0
# multiple flags OK
for {set i 0} {$i < [llength $argv]} {incr i} {
  set arg [lindex $argv $i]
  if { "$arg" == "-help" || "$arg" == "--help" ||
       "$arg" == "-h"    || "$arg" == "--h" } {
    if ![info exists env(CSURF_LIBRARY_PATH)] {
      puts ""
      puts "================================================================="
      puts "### csurf: environment variable CSURF_LIBRARY_PATH not set!!"
      puts " => tcl/tk/tix won't be able to find csurf tcl/tk/tix libraries!!"
      puts "### HOWTO fix:"
      puts "cd <your_install_dir>/csurf"
      puts "source FreeSurfer.{c}sh"
      puts "csurf"
      puts "================================================================="
      puts ""
      exit
    }
    if { "$arg" == "-h" || "$arg" == "-help" } {
      puts ""
      puts "====== (ignore above) ==========================================="
    } else {
      puts ""
      puts "================================================================="
    }
    puts "### usage: csurf \[-opt ...\]"
    puts " \[no options\]   start csurf interface (or in bg: csurf &)"
    puts " --h (or -h)    print this help and exit"
    puts \
     " -f             force use Terminal vs. xterm (Mac), allow spaces in path"
    puts " -db            force doublebuffer (def: Ubuntu/CentOS off)"
    puts " -sb            force singlebuffer (fix black-after-1st-clk)"
    puts " -hack          force use draw speedup hack (xterm cover/uncover)"
    puts " -nohack        force don't-use drawing speedup hack"
    puts \
     " <subject>      start csurf using this subject (in curr \$SUBJECTS_DIR)"
    puts \
    " <session>      start csurf using this session (in curr \$FUNCTIONALS_DIR)"
    if { [exec uname] == "Darwin" } {
      puts "================================================================="
      puts "### Mac-specific:"
      puts " => requires XQuartz.app is first installed"
      puts " => run csurf from XQuartz.app xterm, not Terminal (or use -f)"
    }
    puts "================================================================="
    puts "### HOWTO set up environment, start csurf:"
    puts "cd <your_install_dir>/csurf"
    puts "source FreeSurfer.{c}sh"
    puts "csurf"
    puts "================================================================="
    puts "### HOWTO run csurf with a tcl interpreter for debug/inspect/hack:"
    puts "cd <your_install_dir>/csurf"
    puts "source FreeSurfer.{c}sh"
    puts "wish8.5"
    puts "% source ./bin/noarch/csurf"
    puts " (example of HOWTO use csurf tcl interpreter)"
    puts "% info commands *subject*"
    puts "% choosesubjectdir"
    puts "================================================================="
    puts "### HOWTO use wrappers.tcl functions (e.g., confirmalert <msg>)"
    puts "cd <your_install_dir>/csurf"
    puts "source FreeSurfer.{c}sh"
    puts "wish8.5"
    puts "% source ./lib/tcl/wrappers.tcl"
    puts " (example of HOWTO use wrapper function)"
    puts "% confirmalert \"Hello world\""
    puts "================================================================="
    puts ""
    exit
  } elseif { "$arg" == "-version" || "$arg" == "--version" } {
    puts $csurfsubversion
    exit
  } elseif { "$arg" == "-db"           || "$arg" == "--db" ||
             "$arg" == "-doublebuffer" || "$arg" == "--doublebuffer" } {
    set forcedoublebuffer 1
  } elseif { "$arg" == "-sb"           || "$arg" == "--sb" ||
             "$arg" == "-singlebuffer" || "$arg" == "--singlebuffer" } {
    set forcesinglebuffer 1
  } elseif { "$arg" == "-f"     || "$arg" == "--f" ||
             "$arg" == "-force" || "$arg" == "--force" } {
    set forceuseterm 1
  } elseif { "$arg" == "-hack" || "$arg" == "--hack" } {
    if { [exec uname] == "Darwin" } {
      set mac_appnap_hack 1
      set appnapstateforced 1
    } else {
      puts "$program: ### N.B.: non-Mac: not using Mac draw speedup hack"
    }
  } elseif { "$arg" == "-nohack" || "$arg" == "--nohack" } {
    set mac_appnap_hack 0
    set appnapstateforced 1
  } elseif { ![string match -* $arg] &&
             [info exists env(SUBJECTS_DIR)] &&
             [file exists $env(SUBJECTS_DIR)/$arg/scripts] } {
    cd $env(SUBJECTS_DIR)/$arg/scripts
  } elseif { ![string match -* $arg] &&
             [info exists env(FUNCTIONALS_DIR)] &&
             [file exists $env(FUNCTIONALS_DIR)/$arg/image/scripts] } {
    cd $env(FUNCTIONALS_DIR)/$arg/image/scripts
  } else {
    if [string match -* $arg] {
      puts "$program: ### bad option ($arg)  ...ignored"
    } else {
      puts "$program: ### bad subject or session ($arg)  ...ignored"
    }
  }
  unset arg
}

### block start from Mac Terminal unless force (nmovie fail, harder to kill)
## include next in 'if' to skip blocking run without -f
#    [string range [exec uname -r] 0 \
#       [expr [string first . [exec uname -r]] - 1]] <= 16
if { [exec uname] == "Darwin" &&
     [info exists env(TERM)] && $env(TERM) != "xterm" } {
  if {!$forceuseterm} {
    puts \
     "$program: ### better to run csurf from xterm in XQuartz.app, not Terminal"
    puts "$program: ### to force run from Terminal, use \"csurf -f\" (or --f)"
    exit
    ### change to next if 10.12, 10.15 nmovie OK
    #puts ""
    #puts "$program: better to run from xterm in XQuartz.app (vs. Terminal)"
  } else {
    #puts ""
    #puts "$program: better to run from xterm in XQuartz.app (vs. Terminal)"
  }
}

### check CSURF_LIBRARY_PATH -- helpfully prints *after* err from next load tix!
if ![info exists env(CSURF_LIBRARY_PATH)] {
  puts ""
  puts "### csurf: environment variable CSURF_LIBRARY_PATH not set!!"
  puts " => tcl/tk/tix won't be able to find csurf tcl/tk/tix libraries!!"
  puts "### HOWTO fix:"
  puts "cd <your_install_dir>/csurf"
  puts "source FreeSurfer.{c}sh"
  puts "csurf"
  puts ""
  exit
}

### load tix lib, check tix got loaded, restore old tk look
if ![info exists env(CSURF_DIR)] {
  puts "\ncsurf: ### CSURF_DIR not set\n"
  puts "set up environment, try again:\n"
  puts "  cd <your_install_dir>/csurf\n  source FreeSurfer.{c}sh\n  csurf\n"
  exit
}
if {[exec uname] == "Linux"}  {
  load libTix${tixsubversion}.so     ;#uses LD_LIBRARY_PATH
}
if {[exec uname] == "Darwin"} {
  load libTix${tixsubversion}.dylib  ;#uses DYLD_LIBRARY_PATH
}
if {[exec uname] == "IRIX" || [exec uname] == "IRIX64"} {
  load libTix${tixsubversion}.so     ;#uses LD_LIBRARYN32_PATH
}
if ![info exists tix] {
  puts "$program: ### no Tix: csurf req's tixwish or tk \"package require Tix\""
  exit
}
::tk::classic::restore  ;# newpkgtix: restore orig thick relief entries/buttons

### check env vars (var exists, pointed-to exists, no final /, no spaces)
foreach envvar { CSURF_DIR SUBJECTS_DIR FUNCTIONALS_DIR } {
  if ![info exists env($envvar)] {
    puts "$program: ### env variable $envvar undefined"
    puts "to fix:"
    puts "  in sh/bash: export $envvar=<any-writable-dir>"
    puts "  in csh/tcsh: setenv $envvar <any-writable-dir>"
    puts "  => then re-run csurf"
    exit
  }
  if ![file exists $env($envvar)] {
    puts "$program: ### $envvar: $env($envvar) not found"
    puts "to fix:"
    puts "  in sh/bash: export $envvar=<any-writable-dir>"
    puts "  in csh/tcsh: setenv $envvar <any-writable-dir>"
    puts "  => then re-run csurf"
    exit
  }
  if {$env($envvar) == "/"} {  ;# see next
    puts "$program: ### $envvar: $env($envvar): cannot be root (/)"
    exit
  }
  if [string match */ $env($envvar)] {  ;# breaks path parsing
    puts "$program: ### $envvar: $env($envvar): remove final slash"
    exit
  }
  if [string match "* *" $env($envvar)] {  ;# breaks path parsing (fix IN PROG)
   puts ""
   puts "$program: ### one or more spaces detected in path name:"
   puts ""
   puts "  $envvar: $env($envvar)"
   puts ""
   puts "  => N.B.: space in SUBJECTS_DIR path breaks MGH freesurfer"
   puts "  => N.B.: space in FUNCTIONALS_DIR path req's AFNI_PATH_SPACES_OK=YES"
   puts "  => Do one of the following:"
   puts ""
   puts "   (1) remove space(s) from path (are spaces really necessary??)"
   puts "   (2) copy to a directory without a space in path (if 1 not possible)"
   puts "   (3) force start anyway, use:  csurf -f  (all but MGH will work!)"
   puts ""
   if {!$forceuseterm} { exit }
  }
}
unset forceuseterm

### check MGH
if ![info exists env(FSURF_DIR)] {
  puts \
"$program: env var FSURF_DIR (curr MGH inst) undef'd -> MGHTools menu disabled"
  set mghsubjtoolsflag 0
  set mghbindir /FSURF_DIR_not_set/bin
} else {
  set mghbindir $env(FSURF_DIR)/bin
}
set initfspacedir $env(FUNCTIONALS_DIR)

### override $path w/arch-specific absolute
# known:  Darwin-{ppc,i386,x86_64}, Linux-{i386,x86_64}, IRIX-mips, IRIX64-mips
set oldonearch [exec uname -s]
set onearch [exec $env(CSURF_DIR)/bin/noarch/getonearch] ;# e.g., Linux-i386
set bindir     $env(CSURF_DIR)/bin/$onearch           ;# csurf binaries
set tcldir     $env(CSURF_DIR)/lib/tcl                ;# csurf tcl lib scripts
set noarchdir  $env(CSURF_DIR)/bin/noarch             ;# csurf exec scripts
set afnibindir $env(CSURF_DIR)/afni/bin/$onearch      ;# afni binaries, plugins
#set mincbindir $env(CSURF_DIR)/local/bin/$oldonearch ;# old: also $mnimodeldir
set mincbindir $env(CSURF_DIR)/mni_autoreg/bin/$onearch ;# mni binaries

### rm'd/distributed $LOCAL_DIR: NOTES
# TODO: mni -> minc: bin/Linux-i386, bin/noarch, lib/Linux-i386 
# TODO: AFNI motif libs => $CSURF_DIR/afni/lib/$onearch, add to FreeSurferEnv

### source standard widget wrapper code
set wrappers $tcldir/wrappers.tcl
if ![file exists $wrappers] {
  puts "$program: ### Can't find wrappers.tcl setup code--CSURF_DIR set wrong?"
  exit
} else {
  source $wrappers
}

### check tcsh: recon-all requirement (my recon-all-running script left csh)
set bintcsh_is_installed 1
if ![file exists /bin/tcsh] {   ;# N.B.: recon-all won't run w/just /bin/csh
  if ![okreplace "" "/bin/tcsh not found\
                 \n\nThese MGH programs *won't* work without tcsh:\
                 \n\n    recon-all  =>  needed to make surface!\
                   \n    make_average_subject\
                 \n\nCancel, and first install tcsh\
                   \n(e.g., sudo apt-get install tcsh)\
                 \n\n    or\
                 \n\nStart Csurf Anyway" \
                 "Start Csurf Anyway"] {
    exit
  }
  set bintcsh_is_installed 0
}

### check tmps
set tmpdir /tmp
#if {[exec uname] == "Darwin"} {  ;# fixes swapbytes fail?
#  set tmpdir $env(HOME)/.csurftmp  ;# N.B.: backslashspaces all derivatives!
#  if ![file exists $tmpdir] { mkdirlog $tmpdir }
#}
set stmptcl $tmpdir/TmpTclSurf.[pid]    ;# tksurfer surf, stats script
set stmptcl2 $tmpdir/TmpTclSurf2.[pid]  ;# tksurfer fix inflated_avg (need?)
set stmptcl3 $tmpdir/TmpTclSurf3.[pid]  ;# tksurfer inflate patch (need diff?)
set mtmptcl $tmpdir/TmpTclMed.[pid]     ;# tkmedit script (also flip, stats)
set etmptcl $tmpdir/TmpEnvCsurf.[pid]   ;# tcl env vars
set ftmpcsh $tmpdir/TmpCshMgh.[pid]     ;# recon-all command
set gtmpcsh $tmpdir/TmpCshMgh.[pid]     ;# MGH avgsurf command
set tmpmpg TmpMpegEncode.[pid]          ;# parmfile for mpeg_encode
set tmpafnidir $tmpdir/TmpAfniLinks     ;# to hold links
if ![file writable $tmpdir] { puts "$program: ### $tmpdir not writable"; exit }
foreach tmpfile \
  "$stmptcl $stmptcl2 $stmptcl3 $mtmptcl $etmptcl $ftmpcsh $gtmpcsh" {
  if { [file exists $tmpfile] && ![file writable $tmpfile] } {
    puts "$program: ### tmpfile: $tmpfile not writable"; exit
  }
}

### override oldsubjtoolsflag if not FreeSurfer0.8
if {$oldsubjtoolsflag && ![string match *FreeSurfer0.8 $env(CSURF_DIR)] } {
  set oldsubjtoolsflag 0  ;# e.g., Linux compile of csurfsrc
}

### distribution definitions
set coresubjbinlist { \
  orig2cor regcor \
  mri_normalize \
  mri_average mri_strip_skull mri_segment mri_fill \
  mri_tessellate mris_smooth mris_inflate mris_make_surfaces \
  mris_flatten mris_sphere mris_register \
  mris_fix_topology mri_watershed }
set newsubjbinlist { brik2cor cor2brik calcimg tkstrip wmfilter fill surf }
set coresessbinlist { \
  tksurfer tkmedit tkregister \
  brik2bfloat paint calcvert \
  rawaverage fourier phasecombine surfcombine rcxcombine bresize \
  mpeg_encode mpeg_play mytoppm \
  mri_surf2surf nmovie mri_convert } ;#!spm2bfloat,mri_surf2surf/convert,nmovie
set mincbinlist { \
  mritotal autocrop mincresample mincreshape mincblur \
  volume_cog minctracc check_scale minc_modify_header }
set afnibinlist { \
  afni to3d 3dvolreg 3dcalc 3dTcat 3dmerge 3dDeconvolve 2swap 4swap \
  3drefit 3dttest 3dbucket 3drename 3dinfo }
#set afniliblist { libXm.so.3 }
set afniliblist {  }
set tclscrlist { \
  readenv.tcl twocond-views.tcl twocond-flat.tcl \
  real-views.tcl real-flat.tcl eccen-views.tcl eccen-flat.tcl \
  polar-views.tcl polar-flat.tcl fs-make.tcl fs-views.tcl fs-flat.tcl \
  saveflat.tcl saveviews.tcl setdefpatchview.tcl \
  phasemovie.tcl offsetmovie.tcl \
  tkmedit.tcl tkregister.tcl tksurfer.tcl }

### check core binaries, incl mpeg (report at end)
set notfoundbin ""
if {$oldsubjtoolsflag} {
  foreach bin $coresubjbinlist {
    if ![file exists $bindir/$bin] {set notfoundbin "$notfoundbin $bin\n"}
  }
}
if {$newsubjtoolsflag} {
  foreach bin $newsubjbinlist {
    if ![file exists $bindir/$bin] {set notfoundbin "$notfoundbin $bin\n"}
  }
}
foreach bin $coresessbinlist {
  if ![file exists $bindir/$bin] {set notfoundbin "$notfoundbin $bin\n"}
}

### check AFNI bins and motif lib used by AFNI
set notfoundafnibin ""
foreach bin $afnibinlist {
  if ![file exists $afnibindir/$bin] {
    set notfoundafnibin "$notfoundafnibin $bin\n"
  }
}
set notfoundafnilib ""
foreach lib $afniliblist {
  if { [llength afniliblist] > 0 } { set found 0 } else { set found 1 }
  foreach libdir { /usr/lib /usr/X11R6/lib } { ;# TODO: motif in afni/lib/$arch
    if [file exists $libdir/$lib] { set found 1 }
  }
  if {!$found} {set notfoundafnilib "$notfoundafnilib $lib\n"}
}

### check MNI binaries (not Darwin)
set notfoundmincbin ""
if {$talairachflag && $oldsubjtoolsflag} {
  if { [exec uname] == "IRIX" || [exec uname] == "Linux" } {
    foreach bin $mincbinlist {
      if ![file exists $mincbindir/$bin] {
        set notfoundmincbin "$notfoundmincbin $bin\n"
      }
    }
  }
}

### backslash spaces in bindir path for runacmd sh
set bindir [backslashspaces $bindir]
set noarchdir [backslashspaces $noarchdir]
set afnibindir [backslashspaces $afnibindir]
set mincbindir [backslashspaces $mincbindir]

### check tcl scripts
set notfoundtcl ""
foreach tclscr $tclscrlist {
  if ![file exists $tcldir/$tclscr] {set notfoundtcl "$notfoundtcl $tclscr\n"}
}

### find an editor
foreach editor $editorlist {
  if [info exists env(CSURFEDITORVIGTERM)] {
    if [foundbywhich gnome-terminal] { set editor vigterm; break }
    if [foundbywhich xterm ] { set editor vixterm; break }  ;# fallback
  }
  if [info exists env(CSURFEDITORVIXTERM)] {
    if [foundbywhich xterm] { set editor vixterm; break }
  }
  if [foundbywhich $editor] { break }  ;# first found in list
}
if {$editor == ""} {
  puts "$program: ### no text editor found (tried: $editorlist)"
}

### check missing libXp (Ubuntu 16.04: breaks AFNI utils inclhere)
if { $mainrelease == "Debian" || $mainrelease == "Ubuntu" } {
  if { ![catch { exec ldd $env(CSURF_DIR)/afni/bin/$onearch/2swap | \
       grep libXp | grep -c "not found" } ret] } {  ;# -c: count matching lines
    if {$ret > 0} {
      confirmalert "libXp (X11 shared lib):  not found:  breaks AFNI utils!\
                \n\n  (1) Ubuntu 16.04: download 15 (OK) libXp from:\
                  \n   https://launchpad.net/ubuntu/+archive/primary/+files/libxp6_1.0.2-2_amd64.deb\
                \n\n  (2) Ubuntu 16.04: install libXp:\
                  \n   sudo dpkg -i libxp6_1.0.2-2_amd64.deb\
                \n\n  N.B.: local copy of .deb available here:\
                  \n   $env(CSURF_DIR)/lib/deb/libxp6_1.0.2-2_amd64.deb"
      puts "$program: ### libXp (X11 shared lib) missing: breaks AFNI utils!"
    }
  }
}

#xxxxxxxxxxxx -- TODO: fix underlying draw-to-front buffer problem!!
### disable some doublebuff, with cmdline override
if { $mainrelease == "Debian" || $mainrelease == "Ubuntu" } {
  # tmp: guarantee works at startup (TODO: OK on working Ubuntu14.04/nvidia?)
  set doublebufferflag 0
  puts "$program: Debian/Ubuntu: using singlebuffer (see csurf -> Preferences)"
}
if { $mainrelease == "CentOS" } {  ;# CentOS 7: disable doublebuff if 3.* kern
  if { [string range [exec uname -r] 0 0] > 2 } { ;# don't break earlier CentOS
    catch { exec lsmod | grep -o "^nvidia\\b" } ret
    if { "$ret" == "nvidia" } {  ;# TODO: others
      set doublebufferflag 1
      puts "$program: CentOS 7NV: using doublebuffer (see csurf -> Preferences)"
    } else {  ;# tmp: guarantee default onboard works at startup
      set doublebufferflag 0
      puts "$program: CentOS 7: using singlebuffer (see csurf -> Preferences)"
    }
  }
}
# csurf cmdline override
if { $forcedoublebuffer } {
  if { $doublebufferflag } {
    puts "$program: already doublebuffered (see csurf -> Preferences)"
  } else {
    set doublebufferflag 1
    puts "$program: force use doublebuffer (see csurf -> Preferences)"
  }
}
if { $forcesinglebuffer } {
  if { !$doublebufferflag } {
    puts "$program: already singlebuffered (see csurf -> Preferences)"
  } else {
    set doublebufferflag 0
    puts "$program: force use singlebuffer (see csurf -> Preferences)"
  }
}
unset forcedoublebuffer forcesinglebuffer

### find tarfile date if there
set tarfiledate "none"
set id [open $env(CSURF_DIR)/README.txt r]
foreach line [split [read $id] "\n"] {
  if [string match "*tarfile made:*" $line] {
    set tarfiledate "[lindex $line 2]"
  }
}
close $id

### only default startup printf
puts "version: pid=[pid], csurf=$csurfsubversion, tcl=$tclsubversion, tix=$tixsubversion, tardate=$tarfiledate"

### horrible tmp hack: 20x draw speedup (Yosemite-Mojave 14sec->700ms, AppNap?)
if { [exec uname] == "Darwin" } {
  if {!$appnapstateforced} {
    set kernvers [file rootname [file rootname [exec uname -r]]]
    # SnowLeop=10,Yosem=14,ElCap=15,Catalina=19,BigSur=20,Sequoia=24
    #if { $kernvers > 13 } { set mac_appnap_hack 1 }
    if { $kernvers > 13 && $kernvers < 20 } { set mac_appnap_hack 1 }
    unset kernvers
  } else {
    if {$mac_appnap_hack} {
      puts "$program: force use draw speedup hack (xterm cover/uncover)"
    } else {
      puts "$program: force don't-use draw speedup hack (xterm cover/uncover)"
    }
  }
}
#set mac_appnap_hack 0  ;# uncomment forces disable hack, overriding all
#set mac_appnap_hack 1  ;# uncomment forces enable hack, overriding all

############################################################################
# global name defines and widgets (constants)
############################################################################
### volume names
set volumedir  mri
set origdir    orig         ;# orig, possibly hand-normalized
set t1dir      T1           ;# after mri_normalize
set t2dir      T2           ;# TODO
set pddir      PD           ;# new: usu. qPD
set pdbraindir PDbrain      ;# after skull strip
set braindir   brain        ;# after skull strip
set wmdir      wm           ;# after wm segmentation
set filleddir  filled       ;# after 3D flood fill of each hemi
set vollooklist { orig T1 PD PDbrain brain wm filled }  ;# search order

### filename/dirname/analysis infix defaults
set origsubdirstem mprage   ;# orig rawdirs
set surfdir surf            ;# created at mknewsubj
set labeldir label          ;# created at mknewsubj
set avgdir average          ;# DEFUNCT
#set svitdir svit           ;# defunct (dir no longer made by make new subj)
set vregname vreg           ;# afni 3d vol reg infix
set realname _r             ;# real component sig (amp usu. sqrtF, was 2)
set complexname _i          ;# imag component sig (amp usu. sqrtF, was 3)
set amprealname _x          ;# real component raw stimfreq amp
set ampcomplexname _y       ;# imag component raw stimfreq amp
set fullFTname f            ;# BRIK infix indicating fullFT
set amplname _a             ;# cplx amp infix: hypot(_r,_i) (tstat->same name)
set powname _b              ;# cplx power infix: _a^2 (tstat->same name)
set dispername _d           ;# dispersion index (vectavgamp/avgampvect)
set realfname _f            ;# new real F-ratio from complex or other
set realfclustname _h       ;# singlesub clustfiltered F-ratio (=cplxstatname6)
set realfclustname2 _j      ;# (not used) like _h but from _g (instead of _f)
set realpname _p            ;# -log10(p) for singlesub p from permutation test
set realpclustname _q       ;# singlesub clustfiltered -log10(p) from permtest
set realbordcntname _k      ;# count of vertices blocked during retin floodfill
set cplxstatname1 _f        ;# cross subject F-ratio (Hagler) from complex amp
set cplxstatname2 _g        ;# cross subject F-ratio (Hagler) from complex sig
set cplxstatname3 _a        ;# cross subject t-test amp complex sig vs. num
set cplxstatname4 _e        ;# cross subject pos Rayleigh test p-value exponent
set cplxstatname5 _b        ;# cross subject t-test complex power sig vs. num
set cplxstatname6 _h        ;# cross subject cluster-filtered F-ratio
set cplxstatname7 _c        ;# coherence: sigfreqamp/sqrt(sum(noisefreqamps))*/
set cplxstatname8 _z        ;# TODO: cross subject F-ratio converted to Z
set statname f              ;# within subj F-ratio (deprecated, not made now)
set fsdir fs                ;# default new fieldsign directory
set rawavgdir rawavg        ;# default new raw avg dir
set sigavgdir phavg         ;# default new sig avg dir
set surfavgdir surfavg      ;# default new surf avg dir
set sphavgdir image/__no_dir__ ;# default new surf avg dir
set paradigmdefdir stim1Ds  ;# default new paradigm dir
set genlintestmatdir gltmats   ;# genlintest dir
set boundsfile runs.1D      ;# stop deconv from going across concat'd runs
set deconvscript deconv.sh  ;# editable record of 3dDeconvolve command
set bitmapdir rgb
set bitmapsufflist { tiff rgb }
set moviedir mpg
set movie1suff mpg
set movie4sufflist { mp4 m4v }
set parasuff 1D
set afnistatsinfix stats    ;# infix for 3dDeconvolve output BRIKs
set diffinfix -VS-          ;# infix for condition subtractions
set diffprefix VS-          ;# in case no positive num in GLT
set addinfix -AD-           ;# infix for condition additions 
# next: skip these scandirs in session dir
set skipfunctlist { scripts scripts~ rgb rgb~ tmp tmp~ mpg irp shim raw }
set skipimsufflist { .float .dat .dat~ .w }  ;#skip load to funct "Image File:"
set talairachmeth mni       ;# mni (removed mgh)
set mniproto icbm           ;# in $CSURF_DIR/local/etc/mni_autoreg
set notesfile NOTES         ;# in subj or funct scriptsdir
set userdefnotesfile .csurfnotes     ;# user-specific defaults
set sysdefnotesfile $env(CSURF_DIR)/lib/help/csurf/defnotes    ;# site-specific
set datfile $program.dat    ;# for both subjects and funct dat
set wasbrak @               ;# replaces AFNI label brackets ('#' chokes nmovie)
set wasbrakold #            ;# replaces AFNI label brackets (old)
set washash @               ;# replaces new AFNI label # ('#' chokes nmovie)
set defnumTRstostrip 0      ;# was 2
set fsaverage fsaverage     ;# in case it changes
set anothersub1time __nobody__ ;# one-time samp to another subject

### 3D surf names and parts
set origext orig            ;# was orig tessellated faces-od-cubes, now smooth
set orig1ext orig1          ;# 1 smoothstep
set orig2ext orig2          ;# 2 smoothsteps
#set otherorigs "orig0 orig3 orig4 orig5 orig6 orig7 orig8 orig9" ;#import hacks
set foldedext smoothwm      ;# standard folded display surface
set whiteext white          ;# exact gray/white boundary
set graymidext graymid      ;# surface in middle of gray matter
set pialext pial            ;# exact pial surface (long time ago: gray)
set thkext thickness        ;# thickness file
set curvext curv            ;# local curvature
set areaext area            ;# local area
set sulcext sulc            ;# summed perpendicular movement smoothwm->infla'd
set oldinflatedext 1000a    ;# 1000 steps with preserve area
set inflatedext inflated    ;# standard inflation
set inflatedext2 inflated_avg  ;# fsaverage average of inflations
set qsphereext qsphere      ;# quick sphere for topology fixing
set sphereext sphere        ;# exact area-corrected sphere
set regext reg              ;# appended to registered-to-sphere surfs
set fixext ""               ;# appended to topological repairs (was _fix)
#set avgext average         ;# morph target (now adj in expert prefs)
set icosize 10242           ;# subtessellation level
set surfextlist "$origext $origext? ${origext}* $foldedext ${foldedext}* \
                 $inflatedext $inflatedext? $oldinflatedext \
                 ${inflatedext}???? $inflatedext2 ${inflatedext}* \
                 $whiteext $graymidext $pialext $pialext? plump gray \
                 $sphereext ${sphereext}???? \
                 $sphereext.$regext ${sphereext}${regext}???? \
                 $origext-actual $inflatedext-actual \
                 $whiteext-actual $pialext-actual \
                 surftmp* *.obj *.srf"  ;# sort order (after match $hemi.*)
set surfextrmlist "inflated.H inflated.K *.nofix"
#set surfextlist "$origext $orig1ext $orig2ext $otherorigs \
#                 $foldedext $inflatedext $inflatedext2 $whiteext \
#                 $graymidext $pialext $qsphereext $sphereext \
#                 $sphereext.$regext"
#could add: {orig/qsphere/smoothwm/inflated}.nofix, or any w/tilde

### flattened surf names and parts
set fullpref full           ;# full patch w/midline removed (was patch-nomid)
set occippref occip         ;# standard occipital patch (was patch)
set patchlist "$fullpref $occippref"    ;# could add more st'd patch prefs here
set patchinfix patch        ;# also looks for any name containing this
set fullpatch $fullpref.$patchinfix     ;# just midline gone (was patch-nomid)
set partialpatch $occippref.$patchinfix ;# standard occipital patch (was patch)
set begin3dext 3d           ;# 3D surface w/cuts
set beginflatext 0          ;# flattened but not unfolded surface
set endflatext flat         ;# flattened surface (was 1000)
set patchextlist "$begin3dext $endflatext" ;# begin/end patch suffixes

### flattened backward compat
set oldendflatext 1000
set patchlist "$patchlist patch patch-nomid"
set patchextlist "$patchextlist \"\" 0 1000"

### permanent logs
# $cmdlog  (.cmd.lg.log)    ;# top log
# $medlog  (.med.lg.log)    ;# middle log
# $surflog (.sur.lg.log)    ;# bottom log

### permanent main comboboxes
# subjectscombo             ;# Main panel: subject
# surfacescombo             ;# Main panel: surface
# patchescombo              ;# Main panel: patch
# sessionscombo             ;# Main panel: session
# scandirscombo             ;# Main panel: iscandir
# mritypescombo             ;# Main panel: mritype

### TODO: global vars only declared in procs
# mghinprawscanfiles($index)

#### next transient widget global variables all created by global in proc
### transient notebook-page-specific setup panel combo boxes
# imagescombo($page)        ;# Setup Funct Scan Parms panel: Image File
# alignscombo($page)        ;# Setup Funct Scan Parms: Same-Plane Struct Dir
# vregtargscombo($page)     ;# Setup Funct Scan Parms panel: Targ
# statscombo($page)         ;# Ext Stats panel: External Statistics Image Set
# rawtoavgcombo($page)      ;# Combine 3D Raw Images panel: Scan Directory
# paradigmscombo($page)     ;# Random Block panel: Paradigm File
# condnamescombo1($page)    ;# Calculate Surf Cond Diffs panel: Condition Name
# condnamescombo2($page)    ;# Calculate Surf Cond Diffs panel: (nothing)
# sigtoavgcombo($page)      ;# Combine 3D Phase Stats: Scan Directory
# surftoavgcombo($page)     ;# Calculate Surf Cond Diffs: Scan Directory
# surftoavgwfileprefcombo($page)  ;# Calc Surf Cond Diffs: Vertex List Prefix
# eccenscombo($page)        ;# Fieldsign panel: Scan Directory
# polarscombo($page)        ;# Fieldsign panel: Scan Directory
# eccenwfileprefscombo($page)  ;# Fieldsign panel: Vertex List Prefix
# polarwfileprefscombo($page)  ;# Fieldsign panel: Vertex List Prefix
# wfileprefscombo($page)    ;# View Functional Data: Painted VertexList Pref
# swfileprefscombo($page)   ;# View Functional Data: Painted VertexList Pref
# viewstclcombo($page)      ;# View Functional Data: 3D
# flattclcombo($page)       ;# View Functional Data: Flat
# dispnamecombo             ;# Cross Sess Spherical Average (N.B.: single page)
# surfacescombo2            ;# View Functional Panel dup: surface
# patchescombo2             ;# View Functional Panel dup: patch

### transient setup panel notebook-page-specific hlists, scrolled windows
# rawtoavghlist($page)      ;# Combine 3D Raw Images panel
# sigtoavghlist($page)      ;# Combine 3D Phase Stats panel
# sigtoavgckwidget($page)   ;# Combine 3D Phase Stats panel
# surftoavghlist($page)     ;# Combine Surface Stats panel
# surftoavgckwidget($page)  ;# Combine Surface Stats panel
# scrwinmultibrik($page)    ;# Ext Stats panel

### transient setup panel bgprocess buttons, notebook-page-specific actions
# align2subjbu($page)       ;# Setup Funct Scan panel (alignscan):ALIGN=>SUBJ
# funct2subjbu($page)       ;# Setup Funct Scan panel (functscan):FUNCT=>SUBJ
# vregall2selbu($page)      ;# Setup Funct Scan panel (functscan):ALL=>T
# vregcurr2selbu($page)     ;# Setup Funct Scan panel (functscan):CURR=>T

### transient setup panel bgprocess buttons, actions apply to all panel pages
# rawaveragebu              ;# Combine 3D Raw Images panel: COMBINE
# calcfourbu                ;# Calculate 3D Fourier Stats panel: FOURIER
# calcrandbu                ;# Calculate 3D Rand Block Stats panel: DECONVOLVE
# sigaveragebu              ;# Combine 3D Phase Stats panel: COMBINE
# convertfunctbu            ;# Import External 3D Statistics: EXTRACT/CONVERT
# paintbu                   ;#Fourier/RandBlock/CombinePhaseCond/ExtStats:PAINT
# surfaveragebu             ;# Combine Surface Stats panel: SURFCOMBINE
# calcfieldbu               ;# Calculate Visual Fieldsign panel: FIELDSIGN
# bordersbu                 ;# Calculate Visual Fieldsign panel: GROWBORD
# surfrenderbu              ;# View Functional Data panel: SURFACE-STATS
# medrenderbu               ;# View Functional Data panel: VOLUME-STATS
# sphereavgbu               ;# Cross Sess Spherical Average panel: SPHEREAVG
# avgsurfbu                 ;# Cross Sess Spherical Average panel: SURFAVG
# samp2subjbu               ;# Cross Sess Spherical Average panel: SAMP2SUBJ
# volavgbu                  ;# Cross Sess Spherical Average panel: VOLAVG
# reconallbu                ;# Recon-all panel: RECON-ALL

### transient render panel disable-able statmask parm widgets
# statmaskparmslist($page)  ;# View Functional Data

############################################################################
# live interface vars
############################################################################
### flag defaults
#set logflag 0              ;# live var at top for settable default
set force 0                 ;# don't ask overwrite
set cmdpid -1               ;# tkwait this variable to detect process finished
set surfpid -1              ;# tksurfer running if not -1
set medpid -1               ;# tkmedit running if not -1
set otherhemi 0
set fulldtree 0             ;# no longer works in tk/tix 8.5
set startupdone 0
set docutsflag 0            ;# set by editcmd, rotates to medial file
set medsurfflag 0
set savergbflag 0           ;# used to include/omit nosave env
set exitrenderflag 0        ;# implements tcl script noexit
set norenderpanelflag 0     ;# viewallscandirs: start tksurfer w/o renderpanel
set makingnewsubject 0
set makingnewsession 0
set makingsetupscan 0       ;# prevent kill til all panels made
set makingfunctscan 0       ;# making align/funct panel for detectchng normtype
set makingextstatscan 0     ;# making extstats panel for detectchng normtype
set choosingsubjectdir 0
set choosingavgsurfdir 0
set choosingfunctdir 0
set editingsurface 0
set matchsubject 0          ;# only show sessions from current subject
set purplekill 0            ;# runacmd resets (for log: finished vs. killed)
set purplekillseq 0         ;# for interrupting sequence of runacmd's
set tiffoutflag 1           ;# menuflag pass to tk{surfer,tkmedit}
set tksurferlogflag 0       ;# menuflag pass to tksurfer
set tkmeditlogflag 0        ;# menuflag pass to tkmedit
set black2transparentflag 0 ;# menu flag passed to tksurfer
set loadMRIflag 0           ;# always-reset load MRI flag (any, but e.g., brain)
set loadMRIauxflag 0        ;# always-reset load MRI aux's flag (filled, T2)
set sing2fsavgflag 0        ;# onetime surftestrender resets for 1sub->fsavg
set oppfsavghemiflag 0      ;# onetime display on opposite hemi of fsaverage
set sing2singflag 0         ;# onetime surftestrender resets for fsavg->1sub

### other var defaults
set name __nobody__
set dispname __nobody__
set hemi rh                 ;# rh lh both
set hemitype 0              ;# 0=rh 1=lh 2=both
set surfext $foldedext      ;# surface suffix
set patchext $fullpatch.$endflatext   ;# live multipart extension to rh,lh
set viewtype inflated       ;# folded, inflated, viewcuts, flattened
#set mritype $t1dir          ;# $origdir, $t1dir, $braindir, $wmdir, $filleddir
set mritype $origdir        ;# $origdir, $t1dir, $braindir, $wmdir, $filleddir
set session __nosession__   ;# e.g.: 100625MS (tksurfer: ..../100625MS/image)
set iscandir ""             ;# scandirscombo (usu composite: image/pol1=>$page
set currpage def            ;# just config'd functpage (for propagating parms)
set prevpage def            ;# use default parm values
set newrawavgdir $rawavgdir ;# Make Dir entry textvar
set newsigavgdir $sigavgdir ;# Make Dir entry textvar
set newsurfavgdir $surfavgdir  ;# Make Dir entry textvar
set newsphavgdir image/__no_dir__ ;# Make Dir entry textvar
set newfsdir $fsdir         ;# Make Dir entry textvar
set rawtoavgdir -unset-     ;# curr dir-to-rawaverage
set sigtoavgdir -unset-     ;# curr dir-to-sigaverage
set sesstoavgdir -unset-    ;# curr sess-to-surfaverage
set surftoavgdir -unset-    ;# curr dir-to-surfaverage
set surftoavgbfloatstem -unset- ;# curr wfile-to-surfaverage
set surftoavgbigstem -unset-    ;# curr surfavg sess/scan/stem
set condnames2difforadd -unset- ;# curr condnamesnums-to-diff or add
set selectmemb ""           ;# selected members of selectfromlist
set selectparm ""           ;# current value of optional selectfromlist parm
set cmdsonlyid fileNONE     ;# single possibly open file to dump cmds only in
set cmdsonlyfile ""         ;# single possibly non-empty curr cmdsfile
set lastmghscandir ""       ;# second start same dir

### saveable single parm arrays
# convparms($val)           ;# averagestructscmd
# stripskullparms($val)     ;# stripskullcmd
# normalizeparms($val)      ;# normalizecmd
# wmfilterparms($val)       ;# wmfiltercmd
# wmfillparms($val)         ;# wmfillcmd
# surfparms($val)           ;# surf,tksurfer
# inflateparms($val)        ;# inflatecmd
# finalparms($val)          ;# mkfinalsurfcmd
# flattenparms($val)        ;# flattencmd
# sphereparms($val)         ;# spherecmd,sphereregcmd
# postclparms($val)         ;# for position.tcl
# lightparms($val)          ;# default settings of lights (+font)
# alignscanparms($val)      ;# align panel(s)
# functscanparms($val)      ;# old funct panels (backward compat)
### alternately disable fill parms
set oldfillentlist ""       ;# fill
set newfillentlist ""       ;# mri_fill

### saveable scandir-specific state arrays ($page example: "image/1-polar1")
# structscanlists($page,$val)   ;# struct panels
# sessionscanlists($page,$val)  ;# type of each scandir
# functscanlists($page,$val)    ;# parms/state for funct analysis panels
# renderscanlists($page,$val)   ;# parms/state for render panels
# sphavglists($index,$val)      ;# xsub parms/state ($index: 00,01,02,.. )


############################################################################
# begin tcl procedures
############################################################################
### initialize state saveable to csurf.dat
proc setdefaultarrays { {clearlists 1} } {
  global convparms stripskullparms normalizeparms wmfilterparms wmfillparms
  global surfparms inflateparms finalparms flattenparms sphereparms lightparms
  global structscanlists
  global sessionscanlists alignscanparms functscanlists
  global renderscanlists postclparms sphavglists
  global functscanparms

  if {$clearlists} {
    if [info exists structscanlists]  { unset structscanlists }
    if [info exists sessionscanlists] { unset sessionscanlists }
    if [info exists functscanlists]   { unset functscanlists }
    if [info exists renderscanlists]  { unset renderscanlists }
  }

  ### orig2cor
  set convparms(aligntype) afnihalign  ;# {no/int/mni/afni/afnih/manual}align
  set convparms(adjusttargflag) 0

  ### mri_strip_skull
  set stripskullparms(action)       1   ;# 0=no,1=br,2=in,3=out,4=skn,5=brpd
  set stripskullparms(fzero)       40   ;# norm MRIforce=0 at MRI<val
  set stripskullparms(fmax)       130   ;# inforce=0 if MRI>fmax (shrinkmode=1)
  set stripskullparms(dfrac)      0.7   ;# start size
  set stripskullparms(istilt)     1.0   ;# inside stilt
  set stripskullparms(fsteepness) 0.5   ;# MRI->force tanh
  set stripskullparms(fstrength)  1.0   ;# shrinkmode=4 only: pnt-force tanh
  set stripskullparms(update)     0.9   ;# update: d{x,y,z} += update*d{x,y,z}
  set stripskullparms(decay)      0.9   ;# momentum: d{x,y,z} += decay*m{x,y,z}
  set stripskullparms(usehiresstripskullflag) 0 ;# for detect OK to open expert
  set stripskullparms(usescript)  0                 ;# vs. "none" for below
  set stripskullparms(tclscript)  stripskullPD.tcl  ;# multiple stages

  ### mri_normalize
  set normalizeparms(intensgradlim)  default  ;# 0.6
  set normalizeparms(normsteps)      default  ;# 2
  set normalizeparms(manualcontrol)  0

  ### mri_segment/wmfilter parms
  set wmfilterparms(wm_hi)       default  ;# 125
  set wmfilterparms(wm_low)      default  ;#  90
  set wmfilterparms(gray_hi)     default  ;# 100
  ## mri_segment only
  set wmfilterparms(keepedits)    0
  #TODO: other mri_segment
  #set wmfilterparms(wsize)        11
  #set wmfilterparms(pct)         0.8
  #set wmfilterparms(nslope)      1.0
  #set wmfilterparms(pslope)      1.0
  #set wmfilterparms(thicken)      1
  #set wmfilterparms(fillbg)       0   ;# basal ganglia
  #set wmfilterparms(fillv)        0   ;# ventricles
  #set wmfilterparms(nseg)        20
  ## new wmfilter only
  set wmfilterparms(usehireswmfilterflag) 0 ;# for detect OK to open expert
  set wmfilterparms(gausstruncflag) 0  ;# ignore w/o usehiresewmfilterflag
  set wmfilterparms(kfwhm)        1.5  ;# kernel FWHM (float pix) for above

  ### mri_fill
  set wmfillparms(max_same_neigh)     8    ;# def=10  lax=8
  set wmfillparms(ponspnt)  0
  set wmfillparms(ponsx)   0.0
  set wmfillparms(ponsy)   0.0
  set wmfillparms(ponsz)   0.0
  set wmfillparms(callpnt)  0
  set wmfillparms(callx)   0.0
  set wmfillparms(cally)   0.0
  set wmfillparms(callz)   0.0
  set wmfillparms(ccmask)   1
  ## fill (refurbished fill for hi-res)
  set wmfillparms(usehiresfillflag)   0    ;# set grays-out unsed parms
  set wmfillparms(max_fill_iter)      10   ;# def=10  lax=20
  set wmfillparms(min_filled_per_cyc) 100  ;# def=100 lax=50
  set wmfillparms(seed1A)   112
  set wmfillparms(seed1S)   157
  set wmfillparms(seed1L)   128
  set wmfillparms(seed2A)   112
  set wmfillparms(seed2S)   157
  set wmfillparms(seed2L)   132
  set wmfillparms(callP)     95
  set wmfillparms(callA)    121
  set wmfillparms(callI)      0
  set wmfillparms(callS)    160
  set wmfillparms(callR)    128
  set wmfillparms(callL)    130
  set wmfillparms(midbP)     95
  set wmfillparms(midbA)    121
  set wmfillparms(midbI)    110
  set wmfillparms(midbS)    112
  set wmfillparms(midbR)    113
  set wmfillparms(midbL)    147
  set wmfillparms(clipfeedback) 0
  set wmfillparms(seed1valRH) 127          ;# 80->127 to agree w/MGH
  set wmfillparms(seed2valLH) 255
  set wmfillparms(wmfillthresh) 2.0        ;# min val to fill, not edit->wht

  ### surf, tksurfer
  set surfparms(dividequadsflag)  1
  set surfparms(undividequadsflag) 0
  set surfparms(newquadoutputflag) 0       ;# def->ON w/new FreeSurfer0.8 bins
  set surfparms(newcurvareaoutputflag) 1   ;# def->ON (float curv, area not 2x)

  ### mris_smooth, mris_inflate, tksurfer
  set inflateparms(smoothcycles)       10   ;# 10
  set inflateparms(inflatecycles)      10   ;# 70, 10
  set inflateparms(smoothhirescycles)  25   ;#
  set inflateparms(inflatehirescycles) 50   ;#
  set inflateparms(metric2smooth)   default ;# 0.1, geom vs. smooth
  set inflateparms(write_per_iters) default ;# def just write last
  set inflateparms(nbrs)            default ;# def=2
  set inflateparms(nbrshires)          5    ;# 2->5 incrs rms_height -> unfolds
  set inflateparms(tkstepspercycle)    15   ;# area_shrink, normalize
  set inflateparms(tkinflatecycles)   100   ;# if dump tiffs, also num tiffs 
  set inflateparms(tktiffpercycleflag)  0   ;# dump a tiff every cycle
  set inflateparms(ws)                0.5   ;# tangential force
  set inflateparms(wn)                0.5   ;# normal force
  set inflateparms(wa)                0.5   ;# area ratio force
  set inflateparms(wc)                0.0   ;# neg area ratio -> normal force
  set inflateparms(bordneiflag)        1    ;# 1->usebordnei, 0->radial
  set inflateparms(rmvtx2nonbordflag)  1    ;# 1->rm, 0->save
  set inflateparms(wt)                0.5   ;# radial border force

  ### mris_make_final_surfaces
  set finalparms(selfintersect)       1    ;# defunct, was trans->-graymid
  set finalparms(quickfinalflag)      0    ;# 1 => quick => -q
  set finalparms(whiteonlyflag)       0    ;# 1 => -whiteonly (same as above?)
  set finalparms(noasegflag)          0    ;# 1 => -noaseg
  set finalparms(noaparcflag)         0    ;# 1 => -noaparc
  set finalparms(noautoflag)          0    ;# 1 => noauto stats
  set finalparms(longflag)            0    ;# longitudinal (older) stream
  set finalparms(max)              default ;# 3.5, for longitudinal
  set finalparms(usescript)          0    ;# defunct, was trans->-graymid
  set finalparms(tclscript)     pialwhitethk.tcl ;# multiple stages

  ### mris_flatten
  set flattenparms(vertices_per_full)   12 ;# 12 at each distance
  set flattenparms(sampledist_mm_full)   7 ;# out to 7-connected neighbors
  set flattenparms(vertices_per_patch)  12 ;# 10
  set flattenparms(sampledist_mm_patch) 20
  set flattenparms(write_per_iters)      0 ;# 0=logfile,>0=write surface every
  set flattenparms(writefloatpatchflag)  1 ;# 1=new/float, 0=old/short*100

  ## mris_sphere
  set sphereparms(vertices_per)   default  ;# (8) sphere only
  set sphereparms(sampledist_mm)  default  ;# (7) sphere only
  set sphereparms(write_per_iters)   0     ;# 0=logfile, >0=write surface every
  set sphereparms(tol)            default  ;# spherereg: (10.0->0.5)
  set sphereparms(nav)            default  ;# spherereg: (256->1024)
  set sphereparms(sulcfirst)      default  ;# spherereg: -curv => curv touchup
  set sphereparms(parea)          default  ;# spherereg: (0.2) high stiff
  set sphereparms(corr)           default  ;# spherereg: (0.1) omitted if -p,-d 
  set sphereparms(dist)           default  ;# spherereg: (0.1->5.0) high stiff
  #set sphereparms(morphtarg)     average  ;#average.curvature.filled.buckner40
  set sphereparms(morphtarg) average.curvature.filled.buckner40 ;# 27Feb2015

  ## viewing parms
  set lightparms(light0)    0.4    ;# light0: from eye
  set lightparms(light0x)   0.0
  set lightparms(light0y)   0.0
  set lightparms(light0z)   1.0
  set lightparms(light1)    0.0    ;# light1: behind brain (OFF)
  set lightparms(light1x)   0.0
  set lightparms(light1y)   0.0
  set lightparms(light1z)  -1.0
  set lightparms(light2)    0.8    ;# light2: upper right
  set lightparms(light2x)   0.6
  set lightparms(light2y)   0.6
  set lightparms(light2z)   1.6
  set lightparms(light3)    0.2    ;# light3: left
  set lightparms(light3x)  -1.0 
  set lightparms(light3y)   0.0
  set lightparms(light3z)   0.0
  set lightparms(offset)    0.3    ;# overlay: background gray
  set lightparms(cvfact)    1.3    ;# overlay: light/dark gray contrast

  ### scandirs in current struct setup
  set structscanlists(def,modelimage)  -unset-  ;# from combobox
  set structscanlists(def,imagepatt)   -unset-  ;# C-printf patt, literal OK
  set structscanlists(def,type)        -unset-  ;# structscan if config'd
  set structscanlists(def,imtype)      -unset-  ;# maybe pass to orig2cor
  # imtypes: coronal slice directory, noheader, ignoreheader, noheadbrik
  # imtypes: siemens, genesis, GE LX, minc, mgh, analyze, brik, bshort, sdt
  set structscanlists(def,firstslice)  -unset- 
  set structscanlists(def,slices)      -unset- 
  set structscanlists(def,xres)        -unset-
  set structscanlists(def,yres)        -unset-
  set structscanlists(def,inplane)     -unset-
  set structscanlists(def,thickness)   -unset-
  set structscanlists(def,extraopts)     ""
  set structscanlists(def,flipx)          x
  set structscanlists(def,flipy)          y 
  set structscanlists(def,flipz)          z
  set structscanlists(def,regdat)    register.dat
  set structscanlists(def,mgzout)         1     ;# new def: Mar2013

  ### overall functional scandir type (page/scandir-specific)
  # sessionscanlists not used/set for aspect=struct, aspect=sphavg (?)
  # info exists sessionscanlists($page,type) -> see if existing dir config'd
  #  => functscan,alignscan,fsscan,extstatscan,sphavgscan,rawscan(not used)
  set sessionscanlists(def,type)   functscan
  # aspect argument further differentiates scandir/panel types
  #  => mkorigdirs,mkscandirs,alignfunct,rawavg,calcfour,calcrand,sigavg
  #  => surfavg,calcfield,extstat,render,sphavg,rendersphavg

  ### alignment (=session) scan defaults (shared if more than one alignscan)
  set alignscanparms(modelimage) -unset-   ;# mprage.001
  set alignscanparms(imagepatt)  -unset-   ;# AFNI: mprage+orig.BRIK
  set alignscanparms(imtype)     -unset-   ;# maybe pass to orig2cor
  # imtypes: coronal slice directory, noheader, ignoreheader, noheadbrik
  set alignscanparms(slices)     -unset-
  set alignscanparms(xres)       -unset-
  set alignscanparms(yres)       -unset-
  set alignscanparms(inplane)    -unset-
  set alignscanparms(thickness)  -unset-
  set alignscanparms(brightness)   1.0     ;# mprage=1.0, ISIR=0.2
  set alignscanparms(regdat)   register.dat
  set alignscanparms(initroundflag) 1      ;# 0=orig,1=round, INIT+report only
  set alignscanparms(blockcenteroffset)  0.0  ;# shift-mean
  set alignscanparms(tkregtargdir) orig    ;# equals $origir, was $t1dir

  ### defunct non-scandir-indexed funct scan parms (read-only, back compat)
  set functscanparms(slices)     -unset-
  set functscanparms(xres)       -unset-
  set functscanparms(yres)       -unset-
  set functscanparms(inplane)    -unset-
  set functscanparms(thickness)  -unset-

  ### functional scan lists (page/scandir-specific parms)
  ## features a scandir might have
  set functscanlists(def,rawavgflag)  0   ;# aspect=rawavg
  set functscanlists(def,fourflag)    0   ;# aspect=calcfour
  set functscanlists(def,randflag)    0   ;# aspect=calcrand
  set functscanlists(def,sigavgflag)  0   ;# aspect=sigavg
  set functscanlists(def,surfavgflag) 0   ;# aspect=surfavg
  set functscanlists(def,sphavgflag)  0   ;# aspect=sphavg
  set functscanlists(def,renderflag)  0   ;# aspect=render
  #N.B.: no functscanlists(def,sphavgflag): aspect=sphavg %02d- not $page-based
  set functscanlists(def,stattype)   real ;# real,complex,paradigm
  set functscanlists(def,extstatfunctims) 0  ;# for extstat w/manual register
  ## functscan panel
  set functscanlists(def,imtype)       brik  ;# analyze/tkregister readable
  #imtypes: siemens, mgh, analyze, brik, bshort, bfloat
  set functscanlists(def,modelimage) unset_001.bshort  ;#rawdata xyzt: usu BRIK
  set functscanlists(def,imagepatt)  unset_%03d.bshort ;#rawdata xyzt: usu BRIK
  set functscanlists(def,slices)      10
  set functscanlists(def,xres)        64
  set functscanlists(def,yres)        64
  set functscanlists(def,reps)        128
  set functscanlists(def,inplane)     2.5
  set functscanlists(def,thickness)   5.0
  set functscanlists(def,brightness)  0.1        ;# brightness factor
  set functscanlists(def,mbaccel)      1         ;# multiband accel
  set functscanlists(def,taxisoffsets) ""        ;# TAXIS_OFFSETS (AFNI HEAD)
  #sliceorders: simul, odev, evod, odevr, evodr, asc, desc
  set functscanlists(def,sliceorder) evod        ;# Siemens: even # slices
  set functscanlists(def,vregtargTR)    0        ;# TR to use as 3dvolreg targ
  set functscanlists(def,vregdfile) motion.1D    ;# rel motion parms output file
  set functscanlists(def,vregregressflag)  1     ;# add motion regressors
  set functscanlists(def,vreg2passflag) 0        ;# smooth/fine 3dvolreg
  set functscanlists(def,tkregtargdir)    orig   ;# equals $origir, was $t1dir
  set functscanlists(def,regdat)    register.dat
  set functscanlists(def,initroundflag) 1   ;# 0=orig,1=round, INIT+report only
  set functscanlists(def,vregtargdir)  -unset-   ;# functscan
  set functscanlists(def,aligndir)     -unset-   ;# image/mprage
  set functscanlists(def,allverticesflag)  0     ;# used at paint time
  set functscanlists(def,normdsampsearchflag) 0  ;# normsearch (uniq 1vtx)
  set functscanlists(def,samevtxthickflag) 0     ;# search on vec to equiv num
  set functscanlists(def,normdsampuniqvoxflag) 0 ;# uniqvox (1st hit) tcourses
  set functscanlists(def,normdsampuniqvtxflag) 0 ;# tell paint write + uniqvtx
  set functscanlists(def,normdsampallflag) 0     ;# sample every dstep
  #set functscanlists(def,alignfunctcentoffset) 0.0 ;#defunct: cent-cent offset
  set functscanlists(def,blockcenteroffset) 0.0  ;# shift-mean
  set functscanlists(def,paintdmin)    0.0   ;# min search dist/frac norm2vtx
  set functscanlists(def,paintdmax)    0.8   ;# max search dist/frac norm2vtx
  set functscanlists(def,paintdstep)   0.10  ;# search step (mm)
  set functscanlists(def,paintnormop)  max   ;# vtxnorm search op (max,avg,min)
  set functscanlists(def,paintnormtype) frac ;# vtxnorm search type (mm,frac)
  set functscanlists(def,clonesuff)    b     ;# - inserted before suff
  ## rawavg panel
  set functscanlists(def,rawtoavgdirs) { -unset- }  ;# rawavgscan
  set functscanlists(def,rawtoavgrevs) { -unset- }  ;# rawavgscan (on/off/none)
  set functscanlists(def,rawoperation) average      ;# average/concat
  set functscanlists(def,rawavgfilepatt) { -unset- } ;# feedback only
  set functscanlists(def,concatfiles)      1        ;# concat only
  set functscanlists(def,revtTRs)          0        ;# average only
  ## fourier panel 
  set functscanlists(def,stimnotes)    "some stim prog"
  #N.B.: tksurfer varname for "paintext" is "wmgmext"
  #N.B.: 24 Sep 2019: changed next to "white" (was orig): foot S-I bad in orig!
  set functscanlists(def,paintext)      white  ;# sampsurf 3ddata (orig,white)
  set functscanlists(def,rh,wfile)      unset-rh.w            ;# feedback only
  set functscanlists(def,lh,wfile)      unset-lh.w            ;# feedback only
  set functscanlists(def,angle_offset1sec)  0.01562           ;# 1/64=0.015625
  set functscanlists(def,phasetype)     eccen   ;# polar,eccen,2cond,fstat
  set functscanlists(def,phasestattype) sqrt-F  ;# sqrt-F,p-val,p-FA (0,1,2)
  set functscanlists(def,phasestatformat)  afnibrik ;#bfloat,afnibrik TODO:mgz
  set functscanlists(def,fullfourierflag) 0  ;# 6x as big as raw
  set functscanlists(def,fixileaveflag)  0   ;# fix interleave slicetime by spec
  set functscanlists(def,useTAXISflag)   0   ;# fix interleave slicetime w/TAXIS
  set functscanlists(def,inclharm23flag) 0   ;# consider harm2,3 as signal
  set functscanlists(def,TR)             2
  set functscanlists(def,stimcycles)     8   ;# for fourier
  set functscanlists(def,smoothsteps3d)  0   ;# 27 nearest neigh phasecombine
  set functscanlists(def,lofreqwin)      3   ;# hipass:ignore low !noise or sig
  set functscanlists(def,hifreqwin)     -1   ;# -1=Nyuist, else lowpass
  set functscanlists(def,omitfreq)      -1   ;# ignore single freq (-1=don't)
  set functscanlists(def,permtestcnt)    0   ;# num permutation tests (0=off)
  set functscanlists(def,meandelay)     0.0  ;# mean delay for F-stats
  set functscanlists(def,preclustfthr)  5.0  ;# F-thresh input to surfclust
  set functscanlists(def,clustarea)     150  ;# min cluster area sqmm
  set functscanlists(def,filetruncphaseflag)  0 ;# truncphase fourier outfiles
  set functscanlists(def,rh,truncphasemin) 0.25 ;# start0deg, CCW/CW (no hemo)
  set functscanlists(def,rh,truncphasemax) 0.75 ;# start0deg, CCW/CW (no hemo)
  set functscanlists(def,lh,truncphasemin) 0.75 ;# start0deg, CCW/CW (no hemo)
  set functscanlists(def,lh,truncphasemax) 0.25 ;# start0deg, CCW/CW (no hemo)
  set functscanlists(def,nonbinaryfsflag)  0    ;# 1=allow near-zero trunc
  set functscanlists(def,truncslope)    5.0     ;# used by fourier,not tksurfer
  set functscanlists(def,eccendir)     -unset-  ;# fsscan
  set functscanlists(def,polardir)     -unset-  ;# fsscan
  set functscanlists(def,fspatchext)   -unset-  ;# partialpatch.endflatext
  ## randblock panel
  set functscanlists(def,paradigmdir)  -unset-  ;# now req relative
  set functscanlists(def,paradigmfile) -unset-  ;# now resets to *.1D
  set functscanlists(def,smoothfwhm)    0.0     ;# 3dmerge -1blur_fwhm
  set functscanlists(def,maxlag)         4      ;# for 3dDeconvolve, in TRs
  set functscanlists(def,polort)         2      ;# polynom nuisance fit order
  set functscanlists(def,extraoptsrand)  ""     ;# add to 3dDeconvolve cmdline
  set functscanlists(def,stats3ddecon) -unset-  ;# 3dDeconvolve outbucket
  set functscanlists(def,deconvtype)    test    ;# test,fout,tout
  set functscanlists(def,condnames)    -unset-  ;# one-cond 1D file stems
  set functscanlists(def,contrastcnt)    0      ;# num glt contrasts
  set functscanlists(def,condnames2difflist) {} ;# list composite diffcondnames
  set functscanlists(def,condnames2addlist) {}  ;# list composite addcondnames
  ## sigavg panel
  set functscanlists(def,sigtoavgdirs) { -unset- }  ;# sigavgscan
  set functscanlists(def,sigtoavgrevs) { -unset- }  ;# sigavgscan (on/off/none)
  #next: phaseaverage, phasecancel, fullphavgsig
  set functscanlists(def,sigoperation) phaseaverage ;# phaseaverage
  set functscanlists(def,sigavgoffset)  0.0  ;# offset before possible rev
  set functscanlists(def,bfloatpatt)    unset_%03d.bfloat ;#fsig: omits infixes
  set functscanlists(def,bfloatpattinf) unset{}_%03d.bfloat ;# feedback only
  ## surfavg panel
  set functscanlists(def,surftoavgbigstems) { -unset- } ;# surfavgscan
  set functscanlists(def,surftoavgrevs) { -unset- }     ;# surfavgscan
  set functscanlists(def,surfoperation) phaseavg-pol ;#realaverage,-pol/ecc/two
  set functscanlists(def,surfavgscriptflag) 0     ;# surfcombine vs. rcxcombine
  set functscanlists(def,mksurfavgscriptflag) 0   ;# make new vs. use existing
  set functscanlists(def,surfavgoffset) 0.0       ;# offset before possible rev
  ## fieldsign panel
  set functscanlists(def,smoothstepsfs)  50       ;# fieldsign ecc/pol on surf
  set functscanlists(def,retinseedlabel) retinseeds.label  ;# not incl $hemi
  set functscanlists(def,smoothstepsbd)  30       ;# works OK
  set functscanlists(def,minretindist)  0.02      ;# working
  set functscanlists(def,maxretinsearch) 5.0      ;# stop each seed at 5mm rad
  set functscanlists(def,retinvtxfrac)   1.0      ;# fraction label vtxs seeded
  set functscanlists(def,retinprogressflag) 0     ;# show
  ## extstat panel (clusterrad/vol also on exposed on fourier panel above)
  set functscanlists(def,extstatfile)    -unset-  ;# scan1+orig.BRIK
  set functscanlists(def,bskip)           0       ;# single brik (nskip=bug!)
  #next: bfloat, briksingle, brikmulti, mgzsingle
  set functscanlists(def,statformat)    brikmulti ;# brikmulti
  set functscanlists(def,realstatformat) afnibrik ;# bfloat,afnibrik
  # N.B.: clusterrad is bad varname: actually dist to be considered same clust!
  # N.B.: default should be 1 (since -dxyz=1) but left 10 for back compat
  set functscanlists(def,clusterrad)         1    ;# -dxyz=1: units=voxwidth
  set functscanlists(def,clustervol)        40    ;# -dxyz=1: units=voxvolume
  set functscanlists(def,multiprefix)       ""    ;# paint output only
  set functscanlists(def,multiinfix)        ""    ;# paint output only
  set functscanlists(def,globalmaskthresh) 0.0    ;#

  ### render scan lists (scandir-specific parms)
  set renderscanlists(def,rgbname)   -unset- ;# bitmap pref
  #bfloatstem now misnomer: stats typically BRIK (N.B.: omits _r,_i etc infix)
  set renderscanlists(def,bfloatstem) -unset- ;# vtxlist pref (omits infixes)
  set renderscanlists(def,polarstem) -unset- ;# vtxlist pref (omits infixes)
  set renderscanlists(def,eccenstem) -unset- ;# vtxlist pref (omits infixes)
  set renderscanlists(def,sbfloatstem) -unset- ;# stats mask vtxlist pref
  set renderscanlists(def,samestem)     0    ;# force rgb same stem
  set renderscanlists(def,renderlisttype) one ;# render one/last/all *.w files
  set renderscanlists(def,rendertype)  real  ;# eccen,polar,2cond,fstat,real,fs
  set renderscanlists(def,colscale)     1    ;#0=wh,1=ht,6=BR,7=GR,8=w2,9=fs,11
  set renderscanlists(def,fthresh)     0.3   ;# (0.5) hard thresh
  set renderscanlists(def,fslope)      1.5   ;# (0.2) sigmoid steepness
  set renderscanlists(def,fmid)        1.1   ;# (3.0) sigmoid midpoint
  set renderscanlists(def,sfthresh)     0.3   ;# hard cmp-to-stat thresh
  set renderscanlists(def,sfslope)      1.5   ;# sigmoid steepness cmp-to-stat
  set renderscanlists(def,sfmid)        3.0   ;# sigmoid midpoint cmp-to-stat
  set renderscanlists(def,rh,angle_offset) 0.15
  set renderscanlists(def,lh,angle_offset) 0.15
  set renderscanlists(def,angle_cycles)   1.0
  set renderscanlists(def,fadef)          0.7
  set renderscanlists(def,ipsiyellowfact) 0.0
  set renderscanlists(def,offset)    0.30    ;# default lighting offset
  set renderscanlists(def,cvfact)    1.30    ;# bg light/dark curv gray contr
  set renderscanlists(def,avgflag)    1      ;# 50:50 convex/concave (lt/dark)
  set renderscanlists(def,smoothstepsrend) 5 ;# along surface, real/(imag)
  set renderscanlists(def,smoothstepsstat) 5 ;# along surface, stat
  set renderscanlists(def,cpxangrealampflag) 0 ;# smooth ignoring dispersion
  set renderscanlists(def,kcnt)   5          ;# kernel cells (int pix)
  set renderscanlists(def,kfwhm) 1.5         ;# kernel FWHM (floating pnt pix)
  set renderscanlists(def,smoothoverlaymaskflag) 1 ;#smooth loaded mask (3Donly)
  set renderscanlists(def,complexvalflag)  0
  set renderscanlists(def,fourierampflag)  0 ;# show ampl+phase vs. F+phase
  set renderscanlists(def,colscaletype) cplx ;#cplx,r/tstat,fs,real->flgs@render
  set renderscanlists(def,rh,revphaseflag) 0
  set renderscanlists(def,lh,revphaseflag) 0
  set renderscanlists(def,truncphaseflag)  0
  set renderscanlists(def,softtruncphaseflag)  0
  set renderscanlists(def,invphaseflag)  0   ;# not yet used
  set renderscanlists(def,rh,truncphasemin) 0.25 ;# all 4: after rev,inv,offset
  set renderscanlists(def,rh,truncphasemax) 0.75 ;# same var in functscanlists
  set renderscanlists(def,lh,truncphasemin) 0.25 ;# but diff convention there
  set renderscanlists(def,lh,truncphasemax) 0.75 ;# before rev there
  set renderscanlists(def,complexampmodtype) off ;# off,repl,mask,mult
  # next: sig(nostatmask), famp, fsig, raang(Rayleigh), tsig(t), tpow(power)
  set renderscanlists(def,complexstatsource) sig  ;# also: singsub: fclu
  set renderscanlists(def,scalebarflag)     1
  set renderscanlists(def,colscalebarflag)  1
  set renderscanlists(def,interpolatelutflag) 1
  set renderscanlists(def,botedgelutflag)   0
  set renderscanlists(def,zerosymmfadeflag) 0
  #set renderscanlists(def,brightphase)  1   ;# rm'd: now default 
  set renderscanlists(def,bwslope) 4.0       ;# tkmedit underlay contr (def=12)
  set renderscanlists(def,bwmid) 0.50        ;# tkmedit underlay mid (def=0.35)
  set renderscanlists(def,surfcolor) 1       ;# 0=none,1=curv (2=area,3=shear)
  set renderscanlists(def,lat)  1
  set renderscanlists(def,med)  0
  set renderscanlists(def,ven)  0
  set renderscanlists(def,pos)  0
  set renderscanlists(def,dor)  0
  set renderscanlists(def,cust) 0
  set renderscanlists(def,rh,customxrot)   0
  set renderscanlists(def,rh,customyrot)   0
  set renderscanlists(def,rh,customzrot)   0
  set renderscanlists(def,rh,customxtrans) 0
  set renderscanlists(def,rh,customytrans) 0
  set renderscanlists(def,rh,customscalepercent) 100
  set renderscanlists(def,lh,customxrot)   0
  set renderscanlists(def,lh,customyrot)   0
  set renderscanlists(def,lh,customzrot)   0
  set renderscanlists(def,lh,customxtrans) 0
  set renderscanlists(def,lh,customytrans) 0
  set renderscanlists(def,lh,customscalepercent) 100
  set renderscanlists(def,flat)     1
  set renderscanlists(def,viewstcl) twocond-views.tcl
  set renderscanlists(def,flattcl)  twocond-flat.tcl
  set renderscanlists(def,overlay_frame)  0  ;# tkmedit data overlay
  set renderscanlists(def,do_overlay)     1  ;# tkmedit data overlay
  set renderscanlists(def,do_interpolate) 0  ;# tkmedit data overlay
  set renderscanlists(def,patchflag)      0  ;# not used now (fs2000 smpanel)

  ### position.tcl single parms
  set postclparms(rh_occip_zrot)    90
  set postclparms(rh_occip_scale)   1.3      ;# 1.4, 1.1
  set postclparms(rh_occip_xtrans)  0.0
  set postclparms(rh_occip_ytrans)  0.0
  set postclparms(lh_occip_zrot)    90
  set postclparms(lh_occip_scale)   1.3      ;# 1.4, 1.1
  set postclparms(lh_occip_xtrans)  0.0
  set postclparms(lh_occip_ytrans)  0.0
  set postclparms(rh_full_zrot)    90
  set postclparms(rh_full_scale)   0.7       ;# 1.1
  set postclparms(rh_full_xtrans)  0.0
  set postclparms(rh_full_ytrans)  0.0
  set postclparms(lh_full_zrot)    90
  set postclparms(lh_full_scale)   0.7       ;# 1.1
  set postclparms(lh_full_xtrans)  0.0
  set postclparms(lh_full_ytrans)  0.0
  set postclparms(fullpolrectflag)  0        ;# put here, sort of belongs
  set postclparms(fontfile)   luxisb.ttf     ;# put here, doesn't really belong

  ### cross session scan lists (1st index is 00,01,02,.. not page/scandir)
  set sphavglists(def,hemi)         rh     ;# (only 00) 
  set sphavglists(def,sphavgdir) image/polavg;# (only 00)
  set sphavglists(def,smoothsteps2ico) 1   ;# (only 00) adj in interface
  set sphavglists(def,smoothsteps2sub) 0   ;# (only 00) now just internal
  set sphavglists(def,phasetype)   polar   ;# (only 00) polar,eccen,2cond,real
  set sphavglists(def,mapmethod)   nnfr    ;# (only 00) select: nnfr nnf
  set sphavglists(def,ttestcompval) 0.0    ;# (only 00) adj in interface
  set sphavglists(def,permtestcnt)    0    ;# (only 00) adj in interface
  set sphavglists(def,clustsurf) smoothwm  ;# (only 00) surfclust for est. area
  set sphavglists(def,session)      110628MS
  set sphavglists(def,subject)      nobody
  set sphavglists(def,scandir)      scan1    ;# N.B.: usu. iscandir (w/"image")
  set sphavglists(def,vtxlistpref)  scan+orig_r-rh.w ;# wfile inherits brikstem
  set sphavglists(def,morphsurf)    sphere.reg
  set sphavglists(def,statbrikpref) scan_r+orig.BRIK ;# BRIK infix before orig
}

### popup ASCII editor window near main csurf window (NOTES, scomfile)
proc editfile { file {offset 1} } {
  global editor
  if {"$editor" == ""} { return }
  if ![canwriteormakefile $file] {
    confirmalert "Edit File: $file not writable"
    if ![file exists $file] { return }
  }
  set gopts \
    "+[expr [winfo rootx .]+($offset*25)]-[expr [winfo rooty .]+($offset*25)]"
  if {$editor == "vixterm"} {
    exec xterm -geometry $gopts -e vi "$file" >& /dev/null &  ;# null else huptk
  } elseif {$editor == "vigterm"} {
    exec gnome-terminal --geometry $gopts --execute vi "$file" >& /dev/null &
  } elseif {$editor == "gedit"} {
    exec $editor "$file" >& /dev/null &
  } elseif { [exec uname] == "Darwin" && [string match *TextEdit $editor] } {
    exec open -e "$file"    ;# don't start/leave multiple TextEdit's in bg
  } elseif {$editor == "jot"} {  ;# SGI: the first...
    exec $editor "$file" >& /dev/null &
  } else {
    exec $editor -geometry $gopts "$file" >& /dev/null &  ;# xedit (ugh)
  }
}

### main panel SURFACE button command
proc tksurfercmd { } {
  global surflog surfbu
  global viewtype stmptcl etmptcl t1dir doublebufferflag
  global surfparms postclparms flattenparms
  global env name hemi surfext surfdir patchext bindir iscandir
  global origext foldedext inflatedext inflatedext2 sphereext regext qsphereext
  global smallscreenflag doublebufferflag minglxdepthflag
  global tiffoutflag black2transparentflag tksurferlogflag mac_appnap_hack
  global volumedir mritype loadMRIflag loadMRIauxflag appnapstateforced
  global session functscanlists

  if {$name == "__nobody__"} {
    confirmalert "Select a subject (besides __nobody__)"
    return
  }

  # maybe sequentially open hemi's
  checkbothhemi

  # pre-append hemi if not already there
  if ![string match "\[rl\]h.*" $surfext] {  ;# std freesurfer
    set surf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$surfext
  } else {
    set surf $env(SUBJECTS_DIR)/$name/$surfdir/$surfext
  }
  # same for patch
  if ![string match "\[rl\]h.*" $patchext] {
    set patch $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$patchext
  } else {
    set patch $env(SUBJECTS_DIR)/$name/$surfdir/$patchext
  }

#xxxxxxxxxxxx
  # special case for non-freesurfer-style *.obj,*.srf names
  # w/no surfext prefix, can't tell if intended file is ?h.*.obj or *.obj
  # parallel to tksurfer:make_filenames() -> not found, try no pre-append
  if { [string match *.obj $surfext] || [string match *.srf $surfext] } {
    if ![string match "\[rl\]h.*" $surfext] {
      if ![file exists $surf] {
        set surf $env(SUBJECTS_DIR)/$name/$surfdir/$surfext
        if ![file exists $surf] {
          confirmalert "*OBJ/SRF Surface:\
                   \n\nGiven extension:\
                   \n\n    $surfext\
                   \n\nLooked for surface files:\
                   \n\n    (1) $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$surfext\
                     \n    (2) $env(SUBJECTS_DIR)/$name/$surfdir/$surfext\
                   \n\n...neither found"
          return
        }
      }
    }
  }

#xxxxxxxxxxxx
  # no hemi pre-append if *.surf.gii (includes flat b/c flat*gii not a patch)
  # N.B.: tksurfer make_filenames *.gii special case to not pre-append $hemi
  if { [string match *.surf.gii $surfext] &&
       ![string match "\[rl\]h.*" $surfext] } {
    set surf $env(SUBJECTS_DIR)/$name/$surfdir/$surfext
  }

#xxxxxxxxxxxx
  # check if *.vtk $surfext in "surface:" missing surf-type prefix, catch/help
  # catch here vs. in fixsurfaces: 1st see it, avoid multiple callbacks there
  if { [string match *.vtk $surfext] } {
    set preappendedvtk 0
    foreach ext "$origext $foldedext $inflatedext $sphereext $regext" {
      if [string match $ext.* $surfext] { set preappendedvtk 1 }
    }
    if {!$preappendedvtk} {
      confirmalert "VTK Surface:\n\n    $surfext\
                \n\nmissing standard freesurfer prefix, e.g.:\
                \n\n    $hemi.orig\
                  \n    $hemi.smoothwm\
                  \n    etc...\
                 \n\nTo make this surface loadable, rename it to\
                   \nsomething like:\
                  \n\n  $hemi.orig.$surfext"
      return
    }
  }

  # change hemi if other hemi surfs found
  if ![file exists $surf] {
    set otherhemi none
    if {$hemi == "lh"} { set otherhemi rh }
    if {$hemi == "rh"} { set otherhemi lh }
    set foundextlist {}
    foreach ext "$origext $foldedext $inflatedext $sphereext $regext" {
      set surfotherhemi $env(SUBJECTS_DIR)/$name/$surfdir/$otherhemi.$ext
      if [file exists $surfotherhemi] { lappend foundextlist $ext }
    }
    if { $surfext == "" && [llength $foundextlist] } { ;# empty entry only
      set fmtlist ""
      foreach ext $foundextlist { set fmtlist "$fmtlist\n    $ext" }
      confirmalert "Surface:\
                 \n\n    $surf\
                 \n\nnot found\
                 \n\nN.B.: these opposite-hemi ($otherhemi) surfs exist:\
                 \n$fmtlist\
               \n\n(changing hemi to $otherhemi)"
      set hemi $otherhemi
    } else {
      confirmalert "Surface:\n\n    $surf\n\nnot found\n\n(wrong hemi?)"
    }
    return
  }

  # check writable, patch found, very old COR-.info
  if ![file writable $surf] {
    confirmalert \
     "Surface: $surf\nnot writable  ...starting view-only (edits not saveable)"
    set editflag -
  }
  if { $viewtype == "viewcuts" || $viewtype == "flattened" } {
    if ![file exists $patch] {
      confirmalert "Patch:\n\n    $patch\n\nnot found"
      return
    }
  }
  if { [checkcorinfoFOV $t1dir] == "zerofovT1" } { return }

  # make startup script
  if {$viewtype == "folded"}    { mk3dscript }
  if {$viewtype == "inflated"}  { mk3dscript }
  if {$viewtype == "viewcuts"}  { mkviewcutscript }
  if {$viewtype == "flattened"} { mkflatscript }
  set pref ""
  set loadmri1opt ""
  if {$loadMRIflag} {
    set pref "+"
    set loadmri1opt "-loadmri1 $mritype"
    if { [file extension $mritype] != ".mgz" &&
         [file extension $mritype] != ".mgh" &&
        ![file exists $env(SUBJECTS_DIR)/$name/$volumedir/$mritype/COR-001] } {
      set loadmri1opt "-loadmri1 $mritype.mgz"
      if ![file exists $env(SUBJECTS_DIR)/$name/$volumedir/$mritype.mgz] {
        confirmalert "Surface: mri to load not found... tried:\
                  \n\n    (1) COR dir: $mritype\
                    \n    (2) $mritype.mgz\
                  \n\nin $env(SUBJECTS_DIR)/$name/$volumedir"
        set loadMRIflag 0
        set loadMRIauxflag 0
        return
      }
    }
    if {$surfext == "$inflatedext" || $surfext == "$inflatedext2" ||
        $surfext == "$sphereext" || $surfext == "$sphereext.$regext" ||
        $surfext == "$qsphereext" } {
      if ![okreplace "" "Load 3D MRI data w/unfolded surface?" "Load Anyway"] {
        set loadMRIflag 0
        set loadMRIauxflag 0
        return
      }
    }
  }
  set loadmri2opt ""
  set loadmri3opt ""
  if {$loadMRIauxflag} {
    if {!$loadMRIflag} {
      confirmalert " Surface: can't load 2nd,3rd image sets before 1st"
      set loadMRIauxflag 0
      return
    }
    set loadmri2opt "-loadmri2 filled"
    if { ![file exists $env(SUBJECTS_DIR)/$name/$volumedir/filled/COR-001] } {
      set loadmri2opt "-loadmri2 filled.mgz"
      if ![file exists $env(SUBJECTS_DIR)/$name/$volumedir/filled.mgz] {
        confirmalert "Surface: mri to load not found... tried:\
                  \n\n    (1) COR dir: filled\
                    \n    (2) filled.mgz\
                  \n\nin $env(SUBJECTS_DIR)/$name/$volumedir\
                  \n\n...load second volume ignored"
        set loadmri2opt ""
      }
    }
    set loadmri3opt "-loadmri3 T2"
    if { ![file exists $env(SUBJECTS_DIR)/$name/$volumedir/filled/COR-001] } {
      set loadmri3opt "-loadmri3 T2.mgz"
      if ![file exists $env(SUBJECTS_DIR)/$name/$volumedir/filled.mgz] {
        #confirmalert "Surface: mri to load not found... tried:\
        #          \n\n    (1) COR dir: filled\
        #            \n    (2) filled.mgz\
        #          \n\nin $env(SUBJECTS_DIR)/$name/$volumedir"
        set loadmri3opt ""  ;# silent fail
      }
    }
  }

  # guess first funct (for init annot2roi.tcl, req's open SessionTools once)
  set scandiropt ""
  set rawopt ""
  set regopt ""
  if {$session != "__nosession__" && $session != ""} {
    if {"$iscandir" != ""} {
      set scandiropt "-scandir [file tail $iscandir]"  ;# init val ""
    }
    set rawlist {}
    set reglist {}
    foreach ind [array names functscanlists] {  ;# empty functscanlists OK
      if [string match def,* $ind] { continue }
      if [string match image/functscan*,imagepatt $ind] { lappend rawlist $ind }
      if [string match image/1-*,imagepatt $ind]        { lappend rawlist $ind }
      if [string match image/functscan*,regdat $ind]  { lappend reglist $ind }
      if [string match image/1-*,regdat $ind]         { lappend reglist $ind }
    }
    # sort put functscan* before 1-*
    if {"$rawlist" != ""} {  ;# N.B.: req's open SessionTools once
      set rawopt "-rawdata $functscanlists([lindex [lsort $rawlist] 0])"
    }
    if {"$reglist" != ""} {  ;# N.B.: tksurfer correctly sets regdata w/o this
      set regopt "-regdat $functscanlists([lindex [lsort $reglist] 0])"
    }
  }
  if {!$appnapstateforced} {
    set appnaparg -1  ;# let tksurfer decide
  } else {
    set appnaparg $mac_appnap_hack
  }

  ### use opts, not env b/c read-env-file-by-readenv.tcl can be after openwin
  set opts " \
    -tksurferinterface mini \
    -smallscreenflag $smallscreenflag \
    -doublebufferflag $doublebufferflag \
    -dividequadsflag $surfparms(dividequadsflag) \
    -undividequadsflag $surfparms(undividequadsflag) \
    -newquadoutputflag $surfparms(newquadoutputflag) \
    -newcurvareaoutputflag $surfparms(newcurvareaoutputflag) \
    -writefloatpatchflag $flattenparms(writefloatpatchflag) \
    -tiffoutflag $tiffoutflag \
    -tksurferlogflag $tksurferlogflag \
    -macappnaphackflag $appnaparg \
    -black2transparentflag $black2transparentflag \
    -fontfile $postclparms(fontfile) \
    $loadmri1opt \
    $loadmri2opt \
    $loadmri3opt \
    $scandiropt \
    $rawopt \
    $regopt \
    "
  if {$minglxdepthflag}  { set opts "$opts -glxdepth 12" }
  if {$smallscreenflag}  { set opts "$opts -followglwinflag 0" }
  # N.B.: tclenv now read later, by readenv.tcl: pre Mac10.11 was "env $tclenv"
  set tclenv "patchname=$patchext"  ;# passed to tcl script setdefpatchview
#xxx -- next MacOSX 10.11 fail: can't use env: PATH/DYLD not passed to subshell
#  set command \
#    "env $tclenv $bindir/tksurfer ${pref}${name} $hemi $surfext -tcl $stmptcl"
  set id [open $etmptcl w 0666]
  foreach line $tclenv { puts $id $line }  ;# bypass Mac 10.11+ env block
  close $id
  # next: bindir may contain backslashed spaces
  set command "$bindir/tksurfer ${pref}${name} $hemi $surfext \
    -tcl $stmptcl -csurftclenv $etmptcl $opts"
  runacmd "$command" $surfbu "SURFACE  " surfinput $surflog surfpid
  #tkwait variable surfpid  ;# don't wait
  #after 2000 { rmlog $stmptcl }  ;# min 700 but longer can remove 2nd created
  set loadMRIflag 0
  set loadMRIauxflag 0
  chklefthandedsurf $surfext
}

proc chklefthandedsurf { surfext } {
  global chkleftcnt lastleftname name

  if ![info exists lastleftname] { set lastleftname $name }
  if [string match *.srf $surfext] {  ;# currently just by suffix!
    if ![info exists chkleftcnt] { set chkleftcnt 0 }
    if {"$name" != "$lastleftname"} { set chkleftcnt 0 }
    incr chkleftcnt
    if {$chkleftcnt <= 2} {  ;# complain just twice per subject
      if {$chkleftcnt == 2} { after 12000 { set userok 1 } } ;# kill after 12s
      confirmalert "Read Surface: native coordinate system for\
             \n\n    $surfext\
             \n\nmay be left-handed (FreeSurfer uses right-handed/RAS coords)\
             \n\nIf this is actually a right hemisphere but looks like a left\
               \nhemisphere (or vice versa), you have two choices:\
              \n\n    (1) use as is (clicked vertex coords will be unchanged)\
                \n    (2) click \"FlipHemi\" upper-right large F3 interface\
                \n        to flip x-coord sign, then save as native freesurfer\
                \n        surface with \"W\" button on \"outsurf:\" line\
              \n\n(only complains twice :-\} )"
    }
  }
  set lastleftname $name
}

### main panel VOLUME button command
proc tkmeditcmd { } {
  global medlog medbu
  global env name hemi otherhemi bindir
  global mritype medsurfflag mtmptcl cmdsonlyid
  global volumedir origext tiffoutflag vollooklist
  global smallscreenflag doublebufferflag minglxdepthflag tkmeditlogflag
  global wmfillparms mac_appnap_hack appnapstateforced

  if {$name == "__nobody__"} {
    confirmalert "Select a subject (besides __nobody__)"
    return
  }

  # maybe sequentially open hemi's
  checkbothhemi

  set editflag ""
  # find (first)image (N.B.: COR dir used if both COR dir and .mgz present)
  set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype/COR-001
  set newmritype $mritype
  set try1 $newmritype/COR-001
  if ![file exists $firstim] {
    if [string match *.mgz $mritype] {
      set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype
    } else {
      set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype.mgz
    }
    set newmritype [file tail $firstim]
    set try2 $newmritype 
    if ![file exists $firstim] {
      if [string match *.mgh $mritype] {
        set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype
      } else {
        set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype.mgh
      }
      set newmritype [file tail $firstim]
      set try3 $newmritype 
     set allmgzlist [glob -nocomplain $env(SUBJECTS_DIR)/$name/$volumedir/*.mgz]
      set lookmgzlist ""
      foreach mgz $allmgzlist {
        set found 0 
        foreach vol $vollooklist {
          if [string match "*/$vol.mgz" $mgz] { set found 1; break }
        }
        if {$found} { set lookmgzlist "$lookmgzlist [file tail $mgz]\n" }
      }
      if ![file exists $firstim] {
        confirmalert " VOLUME $mritype not found in:\n\n\
                       $env(SUBJECTS_DIR)/$name/$volumedir\n\n\
                       Looked for:\n\n\
                       (1) $try1  (COR dir)\n\
                       (2) $try2\n\
                       (3) $try3"
        if {"$lookmgzlist" != ""} {
          confirmalert "N.B.: found these *.mgz files:\n\n$lookmgzlist"
        }
        return
      }
    }
  }
  if ![file writable $firstim] {
    confirmalert "Images ($mritype): $firstim\nnot writable\
      ...starting view-only (edits not saveable)"
    set editflag -noedit  ;# old tkmedit: was -
  }

  if { [checkcorinfoFOV $mritype] == "zerofovT1" } { return }
 
  # make startup script
  set id [open $mtmptcl w 0644]
  puts $id "open_window"
  puts $id "set plane \$cor"               ;# delayed subst tksurfer.tcl enum
  puts $id "set prad 1"                    ;# thicker default brush
  puts $id "set tiffoutflag $tiffoutflag"  ;# from csurf preferences
  puts $id "setfile insurf $hemi.orig"     ;# respect curr hemi 
  puts $id "redraw"
  close $id
  set surf ""
  if {$medsurfflag} {
    set surf $hemi.$origext
    if {!$otherhemi} { set medsurfflag 0 }
  }
  set opts "-tkmeditinterface mini -all3flag 0"
  # next transfer csurf Preferences
  if {$smallscreenflag}   { set opts "$opts -followglwinflag 0" }
  if {!$doublebufferflag} { set opts "$opts -doublebufferflag 0" }
  if {$minglxdepthflag}   { set opts "$opts -glxdepth 12" }
  if {$tkmeditlogflag}    { set opts "$opts -tkmeditlogflag 1" }
  if {$wmfillparms(wmfillthresh) != 2.0} {
    set opts "$opts -wmfillthresh [expr int($wmfillparms(wmfillthresh))]"
  }
  if {!$appnapstateforced} {
    set appnaparg -1  ;# let tksurfer decide
    set opts "$opts -macappnaphackflag -1"
  } else {
    set opts "$opts -macappnaphackflag $mac_appnap_hack"
  }
  if {$cmdsonlyid != "fileNONE"} {
    puts $cmdsonlyid "### made tmp tkmedit tcl script: ${mtmptcl}"
    set id [open $mtmptcl r]
    foreach line [split [read $id] "\n"] { puts $cmdsonlyid "# $line" }
#xxx -- or output script-maker (OK tcsh/bash)
#puts $cmdsonlyid "touch $mtmptcl"
#foreach line [split [read $id] "\n"] {puts $cmdsonlyid "cat << ZZZZ >> $line"}
#puts $cmdsonlyid "ZZZZ"
    close $id
  }
  set command \
    "$bindir/tkmedit $name $newmritype $surf $editflag -tcl $mtmptcl $opts"
  set mritype $newmritype
### occasional undebugged problem (not showstopper)
# csurf wish8.5 sometimes goes min or two at 100% CPU here, then back to <1%
# stays 100% after QuitVOLUME, must kill csurf to kill the 100% CPU wish8.5 proc
# reproduced on 10.15 so not rel to no-discrete-vid kernel hack w/long uptime
# N.B.: couldn't get this to occur w/tksurfer, yet somehow csurf-dep (?)
  runacmd "$command" $medbu "VOLUME  " medinput $medlog medpid
  #tkwait variable medpid  ;# don't wait
  after 500 {   ;# so radio button can stay lit
    if { [string match *.mgz $mritype] || [string match *.mgh $mritype] } {
      set mritype [file rootname $mritype]
    }
  }
  #after 2000 { rmlog $mtmptcl }  ;# min 700 but longer can remove 2nd created
}

### main panel VOLUME button command overload (shift-middle-click)
proc tkstripcmd { } {
  global medlog medbu
  global env name hemi otherhemi bindir
  global mritype medsurfflag mtmptcl
  global volumedir origext tiffoutflag
  global smallscreenflag doublebufferflag minglxdepthflag tkmeditlogflag
  global wmfillparms

  if {$name == "__nobody__"} {
    confirmalert "Select a subject (besides __nobody__)"
    return
  }
  checkbothhemi
  set editflag ""
  # N.B.: COR dir used if both COR dir and .mgz present
  set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype/COR-001
  set newmritype $mritype
  set try1 $newmritype/COR-001
  if ![file exists $firstim] {
    if [string match *.mgz $mritype] {
      set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype
    } else {
      set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype.mgz
    }
    set newmritype [file tail $firstim]
    set try2 $newmritype 
    if ![file exists $firstim] {
      if [string match *.mgh $mritype] {
        set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype
      } else {
        set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$mritype.mgh
      }
      set newmritype [file tail $firstim]
      set try3 $newmritype 
      if ![file exists $firstim] {
        confirmalert "VOLUME $mritype not found in:\
                  \n\n$env(SUBJECTS_DIR)/$name/$volumedir\
                  \n\nLooked for:\
                  \n\n  (1) $try1  (COR dir)\
                    \n  (2) $try2\
                    \n  (3) $try3"
        return
      }
    }
  }

  if { [checkcorinfoFOV $mritype] == "zerofovT1" } { return }
  set opts ""
  # next transfer csurf Preferences
  if {$smallscreenflag}   { set opts "$opts -followglwinflag 0" }
  if {!$doublebufferflag} { set opts "$opts -doublebufferflag 0" }
  if {$minglxdepthflag}   { set opts "$opts -glxdepth 12" }
  set command "$bindir/tkstrip $name $newmritype"
  set mritype $newmritype
  runacmd "$command" $medbu "VOLUME  " medinput $medlog medpid
  after 500 {   ;# so radio button can stay lit
    if { [string match *.mgz $mritype] || [string match *.mgh $mritype] } {
      set mritype [file rootname $mritype]
    }
  }
}

### Make Full/Occip Surface Cuts menu command
proc editsurfacecmd { } {
  global surfbu viewtype docutsflag editingsurface surfext inflatedext

  if {[$surfbu cget -text] == "QuitSURFA"} { $surfbu invoke }
  set viewtype inflated
  set surfext $inflatedext
  set docutsflag 1
  $surfbu invoke
  set editingsurface 0
}

### Edit Segmentation menu command
proc editsegmentationcmd { } {
  global medbu surfbu
  global mritype wmdir viewtype medsurfflag surfext inflatedext

  set mritype $wmdir
  set medsurfflag 1
  $medbu invoke
  set viewtype inflated
  set surfext $inflatedext
  $surfbu invoke
}

### make folded/inflated tksurfer tcl script for SURFACE button command
proc mk3dscript { } {
  global stmptcl surfdir hemi surfext patchext docutsflag otherhemi
  global env session iscandir cmdsonlyid name

  set patt $env(FUNCTIONALS_DIR)/$session/$iscandir/*.w
  set wfile [file tail [lindex [lsort [glob -nocomplain $patt]] 0]]
  set id [open $stmptcl w 0644]
  if {"$wfile" != ""} { puts $id "setfile val */[file tail $iscandir]/$wfile" }
  puts $id "open_window"
  puts $id "source \"$env(CSURF_DIR)/lib/tcl/readenv.tcl\"" ;#env:Oct15,spJul19
  puts $id "read_binary_curv"
  ### tmp omit: patchabbrev callback loads patch (3d) over folded/inflated!
  puts $id "setfile patch ~/$surfdir/$hemi.$patchext"
  puts $id "make_lateral_view"
  puts $id "set cslope 3.0"
  if {$docutsflag} {
    puts $id "rotate_brain_y 180"
    if {!$otherhemi} { set docutsflag 0 }
  }
  if [string match "*cereb*" $name] {  ;# somewhat dangerous cerebellum hack
    puts $id "rotate_brain_y -90"
  }
  puts $id "set offset 0.30"
  puts $id "set cvfact 1.30"
  puts $id "set light2 0.8"
  puts $id "setfile rgb ~/rgb/curv-$hemi-$surfext-lat.tiff"
  puts $id "redraw"
  close $id
  if {$cmdsonlyid != "fileNONE"} {
    puts $cmdsonlyid "### made tmp tksurfer tcl script: ${stmptcl}"
    set id [open $stmptcl r]
    foreach line [split [read $id] "\n"] { puts $cmdsonlyid "# $line" }
    close $id
  }
}

### make flattened tksurfer tcl script for SURFACE button command
proc mkflatscript { } {
  global stmptcl env name hemi surfdir patchext session iscandir cmdsonlyid

  set pos $env(SUBJECTS_DIR)/$name/scripts/position.tcl
  if ![file exists $pos] { mkpositiontcl }
  set patt $env(FUNCTIONALS_DIR)/$session/$iscandir/*.w
  set wfile [file tail [lindex [lsort [glob -nocomplain $patt]] 0]]
  set id [open $stmptcl w 0644]
  puts $id "source \"$env(CSURF_DIR)/lib/tcl/readenv.tcl\"" ;#env:Oct15,spJul19
  puts $id "source \"$env(CSURF_DIR)/lib/tcl/setdefpatchview.tcl\""
  puts $id "setfile val */[file tail $iscandir]/$wfile"
  puts $id "read_binary_curv"
  puts $id "setfile patch ~/$surfdir/$hemi.$patchext"
  puts $id "read_binary_patch"
  puts $id "open_window"
  puts $id "restore_zero_position; rotate_brain_x -90"
  # these are tcl vars set when position.tcl runs ($ in script)
  puts $id {rotate_brain_z $flatzrot}
  puts $id {translate_brain_x $flatxtrans}
  puts $id {translate_brain_y $flatytrans}
  puts $id {scale_brain $flatscale}
  puts $id "set cslope 3.0"
  puts $id "set offset 0.30"
  puts $id "set cvfact 1.30"
  puts $id "set light2 0.8"
  puts $id "setfile rgb ~/rgb/curv-$hemi-$patchext.tiff"
  puts $id "redraw"
  close $id
  if {$cmdsonlyid != "fileNONE"} {
    puts $cmdsonlyid "### made tmp tksurfer tcl script: ${stmptcl}"
    set id [open $stmptcl r]
    foreach line [split [read $id] "\n"] { puts $cmdsonlyid "# $line" }
    close $id
  }
}

### make viewcuts tksurfer tcl script for SURFACE button command
proc mkviewcutscript { } {
  global env stmptcl hemi surfdir patchext fullpref occippref cmdsonlyid

  set id [open $stmptcl w 0644]
  puts $id "open_window"
  puts $id "source \"$env(CSURF_DIR)/lib/tcl/readenv.tcl\"" ;#env:Oct15,spJul19
  puts $id "read_binary_curv"
  puts $id "setfile patch ~/$surfdir/$hemi.$patchext"
  ### select_patch already does (setfile patch callback touches patchabbrev)
  puts $id "read_binary_patch"
  puts $id "set flag2d 0; restore"   ;# back to 3d
  if { [string match $occippref.* $patchext] ||
       [string match $fullpref.* $patchext] } {
    puts $id "rotate_brain_y 180"
  }
  puts $id "set cslope 3.0"
  puts $id "set offset 0.30"
  puts $id "set cvfact 1.30"
  puts $id "set light2 0.8"
  puts $id "redraw"
  puts $id "setfile rgb ~/rgb/curv-$hemi-$patchext.tiff"
  close $id
  if {$cmdsonlyid != "fileNONE"} {
    puts $cmdsonlyid "### made tmp tksurfer tcl script: ${stmptcl}"
    set id [open $stmptcl r]
    foreach line [split [read $id] "\n"] { puts $cmdsonlyid "# $line" }
    close $id
  }
}

### make subject dir patchview parmfile: position.tcl (for setdefpatchview.tcl)
proc mkpositiontcl { } {
  global env name program
  global ${program}_vers ${program}_oldvers postclparms 

  # force valid parms, file
  if ![isnum $postclparms(rh_occip_zrot)] {set postclparms(rh_occip_zrot) 90}
  if ![isnum $postclparms(rh_occip_scale)] {set postclparms(rh_occip_scale) 1.3}
  if ![isnum $postclparms(rh_occip_xtrans)] {set postclparms(rh_occip_xtrans) 0}
  if ![isnum $postclparms(rh_occip_ytrans)] {set postclparms(rh_occip_ytrans) 0}
  if ![isnum $postclparms(lh_occip_zrot)] {set postclparms(lh_occip_zrot) 90}
  if ![isnum $postclparms(lh_occip_scale)] {set postclparms(lh_occip_scale) 1.3}
  if ![isnum $postclparms(lh_occip_xtrans)] {set postclparms(lh_occip_xtrans) 0}
  if ![isnum $postclparms(lh_occip_ytrans)] {set postclparms(lh_occip_ytrans) 0}
  if ![isnum $postclparms(rh_full_zrot)] {set postclparms(rh_full_zrot) 90}
  if ![isnum $postclparms(rh_full_scale)] {set postclparms(rh_full_scale) 0.7}
  if ![isnum $postclparms(rh_full_xtrans)] {set postclparms(rh_full_xtrans) 0}
  if ![isnum $postclparms(rh_full_ytrans)] {set postclparms(rh_full_ytrans) 0}
  if ![isnum $postclparms(lh_full_zrot)] {set postclparms(lh_full_zrot) 90}
  if ![isnum $postclparms(lh_full_scale)] {set postclparms(lh_full_scale) 0.7}
  if ![isnum $postclparms(lh_full_xtrans)] {set postclparms(lh_full_xtrans) 0}
  if ![isnum $postclparms(lh_full_ytrans)] {set postclparms(lh_full_ytrans) 0}

  set pos $env(SUBJECTS_DIR)/$name/scripts/position.tcl
  if ![canwriteormakefile $pos] { return }
  if [file exists $pos] { mvlog $pos $pos~ }
  set id [open $pos w 0644]
  puts $id "#!${program}[set ${program}_oldvers]posfile"  ;# go back: Sep2013
  puts $id "##############################################################"
  puts $id "# Used by rendering scripts from functional scan scripts dir"
  puts $id "# (adjust using Expert Preferences--edits here overwritten)"
  puts $id "##############################################################"
  puts $id "set rh.occip.patch.flat.flatzrot $postclparms(rh_occip_zrot)"
  puts $id "set rh.occip.patch.flat.flatscale $postclparms(rh_occip_scale)"
  puts $id "set rh.occip.patch.flat.flatxtrans $postclparms(rh_occip_xtrans)"
  puts $id "set rh.occip.patch.flat.flatytrans $postclparms(rh_occip_ytrans)"
  puts $id "set lh.occip.patch.flat.flatzrot $postclparms(lh_occip_zrot)"
  puts $id "set lh.occip.patch.flat.flatscale $postclparms(lh_occip_scale)"
  puts $id "set lh.occip.patch.flat.flatxtrans $postclparms(lh_occip_xtrans)"
  puts $id "set lh.occip.patch.flat.flatytrans $postclparms(lh_occip_ytrans)"
  puts $id ""
  puts $id "set rh.full.patch.flat.flatzrot $postclparms(rh_full_zrot)"
  puts $id "set rh.full.patch.flat.flatscale $postclparms(rh_full_scale)"
  puts $id "set rh.full.patch.flat.flatxtrans $postclparms(rh_full_xtrans)"
  puts $id "set rh.full.patch.flat.flatytrans $postclparms(rh_full_ytrans)"
  puts $id "set lh.full.patch.flat.flatzrot $postclparms(lh_full_zrot)"
  puts $id "set lh.full.patch.flat.flatscale $postclparms(lh_full_scale)"
  puts $id "set lh.full.patch.flat.flatxtrans $postclparms(lh_full_xtrans)"
  puts $id "set lh.full.patch.flat.flatytrans $postclparms(lh_full_ytrans)"
  close $id
  putlog "$pos written"
}

### MGH/UCSD backward compat, requires mv/ln oldstyle surf names
proc readoldpositiontcl { } {
  global env name program
  global ${program}_vers ${program}_oldvers postclparms 
  set vers "#!${program}[set ${program}_vers]datfile"
  set oldvers "#!${program}[set ${program}_oldvers]datfile"
  set pos $env(SUBJECTS_DIR)/$name/scripts/position.tcl
  if ![file exists $pos] { return 0 }
  set id [open $pos r]
  set lines [split [read $id] "\n"]
  set firstline [lindex $lines 0]
  if {$firstline != $vers && $firstline != $oldvers} {
    close $id
    return 0
  }
  foreach line $lines {
    set first [string trim [lindex $line 0]]
    set parm [string trim [lindex $line 1]]
    set value [string trim [lindex $line 2]]
    if {$first == "set"} {
      set hemi unknown
      set patch unknown
      set type unknown
      if [string match rh.* $parm] { set hemi rh }
      if [string match lh.* $parm] { set hemi lh }
      if [string match *.patch.* $parm] { set patch occip }
      if [string match *.patch-nomid.* $parm] { set patch full }
      if [string match *zrot $parm] { set type zrot }
      if [string match *scale $parm] { set type scale }
      if [string match *xtrans $parm] { set type xtrans }
      if [string match *ytrans $parm] { set type ytrans }
      set postclparms(${hemi}_${patch}_${type}) $value
    }
  }
  close $id
  mvlog $pos ${pos}OLD
  return 1
}

### trace env(SUBJECTS_DIR) to update subject combobox list
#proc fixsubjects { varName index op } { }  ;# saved example of old syntax
proc fixsubjects { name1 name2 op } {
  global env subjectscombo sessionscombo

  $subjectscombo subwidget listbox delete 0 end
  set subjectslist {}
  foreach dir [lsort [glob -nocomplain $env(SUBJECTS_DIR)/*]] {
    if ![file exists $dir/scripts] { continue }
    set na [file tail $dir]
    $subjectscombo insert end $na
    lappend subjectslist $na
  }
  set firstsubj [lindex $subjectslist 0]
  if {$firstsubj != "" && ![file isdirectory $env(SUBJECTS_DIR)/$firstsubj]} {
    set firstsubj ""
  }
  $subjectscombo config -value $firstsubj
  $sessionscombo invoke  ;# if funct, subject agrees with it
}

### trace subject name to update surface combobox list
proc fixsurfaces { name1 name2 op } {
  global env name hemi surfdir surfext surfextlist surfextrmlist inflatedext
  global surfacescombo surfacescombo2 inflatedext2

  # clear combo
  $surfacescombo subwidget listbox delete 0 end
  set uniqlist {}
  if {$hemi == "both"} { set shemi rh } else { set shemi $hemi }
  set lastext $surfext

### old
#  global origext inflatedext sphereext regext
#
#  # to appear in dropdown, surface must start with: $hemi.*
#  foreach surf \
#      [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$name/$surfdir/$shemi.*]] {
#    set cext [string range [file tail $surf] 3 end]
#    if { [lsearch -glob $surfextlist $cext] >= 0 &&
#         [lsearch -exact $uniqlist $cext] == -1 } {       ;# $surfextlist exact
#      lappend uniqlist $cext
#    } elseif { [string match ${inflatedext}???? $cext] &&
#               [lsearch -exact $uniqlist $cext] == -1 } { ;# num'd inflated
#      lappend uniqlist $cext
#    } elseif { [string match ${sphereext}???? $cext] &&
#               [lsearch -exact $uniqlist $cext] == -1 } { ;# num'd sphere
#      lappend uniqlist $cext
#    } elseif { [string match ${sphereext}.${regext}???? $cext] &&
#               [lsearch -exact $uniqlist $cext] == -1 } { ;# num'd spherereg
#      lappend uniqlist $cext
#    } elseif { [string match ${origext}* $cext] &&
#               [lsearch -exact $uniqlist $cext] == -1 } { ;# any hemi.orig*
#      lappend uniqlist $cext
#    } elseif { [string match ${inflatedext}* $cext] &&
#               [lsearch -exact $uniqlist $cext] == -1 } { ;# any hemi.inflated*
#      lappend uniqlist $cext
#    } else { ; }
#  }
### end

  # std surfs start with: $hemi.* ($surfextlist sorted by csurf-name-likeness)
  # full pathnames
  set surflist \
    [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$name/$surfdir/$shemi.*]]

#xxxxxxxxxxxx
  # add in all *.obj and *.srf files (full pathnames)
  lappend surflist \
    [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$name/$surfdir/*.obj]]
  lappend surflist \
    [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$name/$surfdir/*.srf]]

  # rm dups and those not in surfextlist patterns (e.g., curv/sulc/area)
  foreach extpatt $surfextlist {
    foreach surf $surflist {
      set cext [file tail $surf]
      if { [string match rh.* $cext] || [string match lh.* $cext] } {
        set cext [string range $cext 3 end]
      }
      if { [string match $extpatt $cext] &&
           [lsearch -exact $uniqlist $cext] == -1 } { lappend uniqlist $cext }
    }
  }

  # rm some that still match good patterns (e.g., inflated.H matches inflated*)
  set uniqlistclean {}
  foreach ext $uniqlist {
    set keep 1
    foreach rmpatt $surfextrmlist {
      if { [string match $rmpatt $ext] } { set keep 0 }
    }
    #if {!$keep} { confirmalert "omit: $ext" }  ;# debug
    if {$keep} { lappend uniqlistclean $ext }
  }
  set uniqlist $uniqlistclean

#xxxxxxxxxxxx
  # append hemi-spec HCP-like GIFTI's (N.B.: these don't start with $hemi.*)
  # N.B.: if *.gii, tksurfer make_filenames never pre-appends hemi
  set giftilist {}
  if {$shemi == "rh"} { set giftilist \
    [glob -nocomplain $env(SUBJECTS_DIR)/$name/$surfdir/*.R.*.surf.gii] }
  if {$shemi == "lh"} { set giftilist \
    [glob -nocomplain $env(SUBJECTS_DIR)/$name/$surfdir/*.L.*.surf.gii] }
  foreach gifti $giftilist { lappend uniqlist [file tail $gifti] }

#xxxxxxxxxxxx
  # load *.vtk's only if empty std ?h.* list and surfext not pre-appended
  # N.B.: tksurfer make_filenames treats *.vtk like reg FS surf names (vs gii)
  # N.B.: could catch/warn here, but two callbacks -> tksurfercmd catches
  # N.B.: tksurfercmd catches/explains how to pre-append ?h.orig.<curr_name>
  if ![llength $uniqlist] {
    set vtklist [glob -nocomplain $env(SUBJECTS_DIR)/$name/$surfdir/*.vtk]
    foreach vtk $vtklist {  ;# don't load otherhemi pre-appended
      if { $shemi == "rh" && 
           ![string match $env(SUBJECTS_DIR)/$name/$surfdir/lh.* $vtk] } {
        lappend uniqlist [file tail $vtk]
      }
      if {$shemi == "lh" &&
           ![string match $env(SUBJECTS_DIR)/$name/$surfdir/rh.* $vtk] } {
        lappend uniqlist [file tail $vtk]
      }
    }
  }

  # default surface on select new subject: inflated (if there)
  if ![llength $uniqlist] { set uniqlist {} }
  foreach uniqext $uniqlist { $surfacescombo insert end $uniqext }
  if {$lastext != "" && [lsearch -exact $uniqlist $lastext] != -1} {
    set curr $lastext
  } else {
    set curr [lindex $uniqlist end]
    if {[lsearch -exact $uniqlist $inflatedext] != -1} {set curr $inflatedext}
  }
  if {$name == "fsaverage"} {  ;# special case: if inflated_avg there, use it
    if {[lsearch -exact $uniqlist $inflatedext2] != -1} {set curr $inflatedext2}
  }
  $surfacescombo config -value $curr

  # load copy of combo on View Functional Data panel
  if { [info exists surfacescombo2] && [winfo exists $surfacescombo2] } {
    $surfacescombo2 subwidget listbox delete 0 end
    set surflist [$surfacescombo subwidget listbox get 0 end]
    foreach surf $surflist { $surfacescombo2 insert end $surf }
    $surfacescombo2 config -value $curr
  }
}

### trace subject name to update patch combobox list
proc fixpatches { name1 name2 op } {
  global env name hemi surfdir patchext patchlist patchextlist patchinfix
  global patchescombo patchescombo2

  $patchescombo subwidget listbox delete 0 end
  set uniqlist {}
  if {$hemi == "both"} { set shemi rh } else { set shemi $hemi }
  set lastpatchext $patchext
  foreach pa \
   [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$name/$surfdir/$shemi.*]] {
    set patch [string range [file tail $pa] 3 end]
    set patchroot [file root $patch]
    set cpatchext [string range [file extension $patch] 1 end]
    if { [lsearch -exact $patchlist $patchroot]   >= 0 &&
         [lsearch -exact $patchextlist $cpatchext] >= 0 &&
         [lsearch -exact $uniqlist $patch] == -1 } {
      lappend uniqlist $patch
    } elseif { [string match *$patchinfix* $pa] &&
               [lsearch -exact $uniqlist $patch] == -1 } {
      lappend uniqlist $patch
    } else { ; }
  }
  if ![llength $uniqlist] { set uniqlist {} }
  foreach uniqpatch [lsort $uniqlist] { $patchescombo insert end $uniqpatch }
  if {$lastpatchext != "" && [lsearch -exact $uniqlist $lastpatchext] != -1} {
    set curr $lastpatchext
  } else {
    set curr [lindex $uniqlist 0]
  }
  $patchescombo config -value $curr

  if { [info exists patchescombo2] && [winfo exists $patchescombo2] } {
    $patchescombo2 subwidget listbox delete 0 end
    set patchlist [$patchescombo subwidget listbox get 0 end]
    foreach patch [lsort $patchlist] { $patchescombo2 insert end $patch }
    $patchescombo2 config -value $curr
  }
}

### trace subject name to update mritype combobox list
proc fixmritypes { name1 name2 op } {
  global env name volumedir vollooklist mritypescombo

  set mritypeslist {}
  foreach vol $vollooklist {
    if [file exists $env(SUBJECTS_DIR)/$name/$volumedir/$vol] {
      lappend mritypeslist $vol
    }
    if [file exists $env(SUBJECTS_DIR)/$name/$volumedir/$vol.mgz] {
      lappend mritypeslist $vol.mgz
    }
  }
  set allmgz [glob -nocomplain $env(SUBJECTS_DIR)/$name/$volumedir/*.mgz]
  foreach mgz $allmgz {
    # N.B.: combo-loaded ctrl_pts.mgz has 6 frames, tkmedit rejects
    set found 0
    set mgztail [file tail $mgz]
    foreach vol $mritypeslist { if [string match $vol $mgztail] {set found 1} }
    if {!$found} { lappend mritypeslist $mgztail }
  }
  $mritypescombo subwidget listbox delete 0 end
  foreach vol $mritypeslist { $mritypescombo insert end $vol }
}

### trace env(FUNCTIONALS_DIR) to update session combobox list
proc fixsessions { name1 name2 op } {
  global env sessionscombo matchsubject name fnewtopflag

  $sessionscombo subwidget listbox delete 0 end
  set sessiondirslist {}
  if {$matchsubject} {
    foreach namefile [lsort [glob -nocomplain $env(FUNCTIONALS_DIR)/*/name]] {
      set id [open $namefile r]
      set thisname [string trim [read $id]]
      close $id
      if {$thisname == $name} {
        set sessiondir [file tail [file dirname $namefile]]
        $sessionscombo insert end $sessiondir
        lappend sessiondirslist $sessiondir
      }
    }
  } else {
    if {$fnewtopflag} {set order -decreasing} else {set order -increasing}
    foreach dir [lsort $order [glob -nocomplain $env(FUNCTIONALS_DIR)/*]] {
      set sessiondir [file tail $dir]
      $sessionscombo insert end $sessiondir
      lappend sessiondirslist $sessiondir
    }
  }
  set firstsess [lindex $sessiondirslist 0]
  if {$firstsess != "" && ![file isdir $env(FUNCTIONALS_DIR)/$firstsess]} {
    set firstsess ""
  }
  $sessionscombo config -value $firstsess
}

### trace session to update iscandir combobox list
proc fixscandirs { name1 name2 op } {
  global session scandirscombo

  $scandirscombo subwidget listbox delete 0 end
  if {$session == ""} { return }
  set scandirslist [getfunctiscandirslist]
  foreach trimmeddir $scandirslist { $scandirscombo insert end $trimmeddir }
  if ![llength $scandirslist] { set scandirslist {} }
  $scandirscombo config -value [lindex $scandirslist 0]
}

proc cbx:listcmd_mri { } {
  global mritypescombo

  # before select: for new additions
  $mritypescombo config -disablecallback true
  fixmritypes 0 0 0
  $mritypescombo config -disablecallback false
}

### find list funct scandirs: (1) sess/image/* (2) sess/05456/003/* (3) sess/*
proc getfunctiscandirslist { } {
  global env session skipfunctlist

  set scandirslist {}
  foreach sess [glob -nocomplain $env(FUNCTIONALS_DIR)/$session] {
    if ![file readable $sess] {
      confirmalert "Get Funct Scan Dirs: session $sess not readable"
      return $scandirslist   ;# maybe empty
    }
  }
  set dirlist [lsort [glob -nocomplain $env(FUNCTIONALS_DIR)/$session/image/*]]
  if ![llength $dirlist] {  ;# APD1
    set dirlist \
     [lsort [glob -nocomplain $env(FUNCTIONALS_DIR)/$session/?????/00*/image*]]
    if [llength $dirlist] {  ;# add generated dirs (no 00? subdir)
      set nosubdirlist \
        [lsort [glob -nocomplain $env(FUNCTIONALS_DIR)/$session/?????/*]]
      foreach dir $nosubdirlist {
        if ![string match */?????/00* $dir] { lappend dirlist $dir }
      }
    }
  }
  if ![llength $dirlist] {  ;# flat
    set dirlist [lsort [glob -nocomplain $env(FUNCTIONALS_DIR)/$session/*]]
  }
  foreach dir $dirlist {
    # N.B.: too dup popups to check bad scandir name here
    if ![file isdirectory $dir] { continue }
    set trimmed \
      [string range $dir [string length $env(FUNCTIONALS_DIR)/$session/] end]
    set tail [file tail $trimmed]
    if { [lsearch -exact $skipfunctlist $tail] >= 0 } { continue }
    lappend scandirslist $trimmed
  }
  return $scandirslist   ;# maybe empty
}

### expand new rawavg/sigavg/surfavg/fs bare dir to $page (APD1:rm image2)
proc expandnewsessdir { tail } {
  set newdir $tail
  set firstfunct [lindex [getfunctiscandirslist] 0]
  if [string match */* $firstfunct] {
    set sessroot $firstfunct
    while { $sessroot != "." } {
      set newdir $sessroot/$tail
      set sessroot [file dirname $sessroot]
    }
  }
  return $newdir
}

### find mri/orig subdirs for Setup Struct Scans
proc getstructscandirslist { } {
  global env name volumedir origdir

  set scandirslist {}
  set fullorigdir $env(SUBJECTS_DIR)/$name/$volumedir/$origdir
  set dirlist [lsort [glob -nocomplain $fullorigdir/*]]
  foreach dir $dirlist {
    if ![file isdirectory $dir] { continue }
    lappend scandirslist [file tail $dir]
  }
  return $scandirslist   ;# maybe empty
}

### trace session, update subject to match curr sess (skip if matchsubject set)
proc fixonesubject { name1 name2 op } {
  global env session subjectscombo matchsubject viewtype

  if {$matchsubject} { return } 
  set saveviewtype $viewtype
  set namefile $env(FUNCTIONALS_DIR)/$session/name
  if [file exists $namefile] {
    set id [open $namefile r]
    set name [string trim [read $id]]
    close $id
    if [file exists $env(SUBJECTS_DIR)/$name] {
      $subjectscombo config -value $name
    } else {
      # ignore namefile subject not found
    }
  } else {
    # ignore missing namefile
  }
  # restore after: newsession=>fixonesubject=>newsubject=>fixsurfaces=>ldcombos
  set viewtype $saveviewtype
}

### load Image File combobox list (Struct/Align/Funct panel create)
proc fiximages { page type } {
  global structscanlists alignscanparms functscanlists iscandir imagescombo

  if {$type == "alignscan" || $type == "functscan"} { set iscandir $page }
  set currimage none
  if {$type == "structscan"} {
    if [info exists structscanlists($page,modelimage)] {
      set currimage $structscanlists($page,modelimage)
    }
  }
  if {$type == "alignscan"} {
    if [info exists alignscanparms(modelimage)] {
      set currimage $alignscanparms(modelimage)
    }
  }
  if {$type == "functscan"} {
    if [info exists functscanlists($page,modelimage)] {
      set currimage $functscanlists($page,modelimage)
    }
  }
  if ![info exists imagescombo($page)] { return }
  $imagescombo($page) subwidget listbox delete 0 end
  if {$type == "structscan"} { set imageslist [getstructimageslist] }
  if {$type == "alignscan"}  { set imageslist [getfunctimageslist] }
  if {$type == "functscan"}  { set imageslist [getfunctimageslist] }
  foreach imagetail $imageslist { $imagescombo($page) insert end $imagetail }
  if ![llength $imageslist] {return}
  if {$currimage == "none" || $currimage == "" || $currimage == "-unset-"} {
    set currimage [lindex $imageslist 0]
  }
  $imagescombo($page) config -value $currimage
}

### load/update Paradigm File combo (Rand Block panel create, new paradigm dir)
proc fixparadigms { page } {
  global paradigmscombo env session iscandir functscanlists parasuff

  set currpara none
  set iscandir $page
  if [info exists functscanlists($page,paradigmfile)] {
    set currpara $functscanlists($page,paradigmfile)
  }
  if ![info exists paradigmscombo($page)] { return }
  $paradigmscombo($page) subwidget listbox delete 0 end
  set paradir $functscanlists($page,paradigmdir)
  #if ![string match /* $paradir] { ;#if rel dir saved, live glob it (moveable)
  #  set paradir $env(FUNCTIONALS_DIR)/$session/$iscandir/$paradir
  #}
  set paradir $env(FUNCTIONALS_DIR)/$session/$iscandir/$paradir ;# now req rel
  set paradigmslist [lsort [glob -nocomplain $paradir/*.$parasuff]]
  foreach para $paradigmslist {
    $paradigmscombo($page) insert end [file tail $para]
  }
  if {$currpara == "none" || $currpara == ""} {
    set currpara [lindex $paradigmslist 0]
  }
  # TODO: allow user set pattern/suffix?
  $paradigmscombo($page) config -value *.$parasuff
}

### load External Statistics Images Set combo (Ext Stats panel create)
proc fixstats { page } {
  global statscombo functscanlists

  set currstat none
  if [info exists functscanlists($page,extstatfile)] {
    set currstat $functscanlists($page,extstatfile)
  }
  if ![info exists statscombo($page)] { return }
  $statscombo($page) subwidget listbox delete 0 end
  set statsbriklist ""
  set statsheadlist ""
  set briklist ""
  set headlist ""
  set otherlist ""
  foreach image [getfunctimageslist] {
    if [string match *-stats+orig.BRIK $image] {
      lappend statsbriklist $image
    } elseif { [string match *.BRIK $image] &&
              ![string match *-stats+orig.BRIK $image] } {
      lappend briklist $image
    } elseif [string match *-stats+orig.HEAD $image] {
      lappend statsheadlist $image
    } elseif { [string match *.HEAD $image] &&
              ![string match *-stats+orig.HEAD $image] } {
      lappend headlist $image
    } else { lappend otherlist $image }
  }
  set imageslist \
    [concat $statsbriklist $briklist $statsheadlist $headlist $otherlist]
  foreach imagetail $imageslist { $statscombo($page) insert end $imagetail }
  if ![llength $imageslist] { return }
  if {$currstat == "none" || $currstat == ""} {
    set currstat [lindex $imageslist 0]
  }
  $statscombo($page) config -value $currstat
}

### load Condition Name combos (READ 1Ds on Calculate RandBlock Stats panel)
proc fixcondnames { page } {
  global functscanlists condnamescombo1 condnamescombo2
  global condnames2difforaddhlist

  set currname1 none
  set currname2 none
  if ![info exists functscanlists($page,condnames)] { return }
  if ![info exists condnamescombo1($page)] { return }
  if ![info exists condnamescombo2($page)] { return }
  set condnames $functscanlists($page,condnames)
  $condnamescombo1($page) config -disablecallback true
  $condnamescombo2($page) config -disablecallback true
  $condnamescombo1($page) subwidget listbox delete 0 end
  $condnamescombo2($page) subwidget listbox delete 0 end
  if [llength $condnames] {
    foreach condname $condnames {
      $condnamescombo1($page) insert end [file tail $condname]
      $condnamescombo2($page) insert end [file tail $condname]
    }
    if {$currname1 == "none" || $currname1 == ""} {
      set currname1 [lindex $condnames 0]
    }
    if {$currname2 == "none" || $currname2 == ""} {
      set currname2 [lindex $condnames 0]
    }
    $condnamescombo1($page) config -value $currname1
    $condnamescombo2($page) config -value $currname2
  } else {  ;# clear if condnames empty on re-read
    $condnamescombo1($page) config -value ""
    $condnamescombo2($page) config -value ""
    if { [info exists functscanlists($page,condnames2difflist)] } {
      set functscanlists($page,condnames2difflist) {}
    }
    if { [info exists functscanlists($page,condnames2addlist)] } {
      set functscanlists($page,condnames2addlist) {}
    }
    if { [info exists condnames2difforaddhlist($page)] &&
         [winfo exists $condnames2difforaddhlist($page)] } {
      $condnames2difforaddhlist($page) delete all
    }
  }
  $condnamescombo1($page) config -disablecallback false
  $condnamescombo2($page) config -disablecallback false
}

### load *-{views/flat}.tcl into 3D,Flat tclscript combos (Render panel create)
proc fixtclscripts { page } {
  global viewstclcombo flattclcombo
  global env session tcldir renderscanlists

  set currviews none
  set currflat none
  if [info exists renderscanlists($page,viewstcl)] { 
    set currviews $renderscanlists($page,viewstcl)
  }
  if [info exists renderscanlists($page,flattcl)] { 
    set currflat $renderscanlists($page,flattcl)
  }
  if ![info exists viewstclcombo($page)] { return }
  if ![info exists flattclcombo($page)] { return }
  $viewstclcombo($page) subwidget listbox delete 0 end
  $flattclcombo($page) subwidget listbox delete 0 end
  set loclist \
   [lsort [glob -nocomplain $env(FUNCTIONALS_DIR)/$session/image/scripts/*.tcl]]
  set viewslist [lsort [glob -nocomplain $tcldir/*-views.tcl]]
  set flatlist  [lsort [glob -nocomplain $tcldir/*-flat.tcl]]
  if [llength $loclist] {
    foreach loc $loclist {$viewstclcombo($page) insert end [file tail $loc]}
    $viewstclcombo($page) insert end "--------" ;#divdr:select_tclscript resets
    foreach loc $loclist {$flattclcombo($page) insert end [file tail $loc] }
    $flattclcombo($page) insert end "--------"
  }
  foreach views $viewslist {$viewstclcombo($page) insert end [file tail $views]}
  foreach flat $flatlist {$flattclcombo($page) insert end [file tail $flat] }
  if {$currviews == "none" || $currviews == ""} {
    set currview [file tail [lindex $viewslist 0]]
  }
  if {$currflat == "none" || $currviews == ""} {
    set currflat [file tail [lindex $flatlist 0]]
  }
  $viewstclcombo($page) config -value $currviews
  $flattclcombo($page)  config -value $currflat
}

### load Paintfile (Painted VertexList Prefix) (Render panel create, 1 update)
proc fixwfileprefs { page } {
  global wfileprefscombo renderscanlists
  global realname complexname amprealname ampcomplexname

  set preflist [lsort [getuniqwfilelist $page]]
  # sort any AFNI contrasts after cond-versus-OFF
  set contrasts ""; set other ""
  foreach pref $preflist {
    if [string match *-VS-* $pref] {
      lappend contrasts $pref
    } else {
      lappend other $pref
    }
  }
  set preflist "$other $contrasts" 
  # sort real/imag phase data before stats (_i at top -> default init load sig)
  set phases ""; set other ""
  foreach pref $preflist {
    if { [string match *$realname $pref] ||
         [string match *$complexname $pref] ||
         [string match *$amprealname $pref] ||
         [string match *$ampcomplexname $pref] } {
      lappend phases $pref
    } else {
      lappend other $pref
    }
  }
  set preflist "$phases $other" 
#xxxxxxxxxxx -- could load (sam) *labels* in Paintfile, diff funct/abbrev conv
  set currpref none
  if [info exists renderscanlists($page,bfloatstem)] { 
    set currpref $renderscanlists($page,bfloatstem)
  }
  if ![info exists wfileprefscombo($page)] { return }
  $wfileprefscombo($page) subwidget listbox delete 0 end
  foreach pref $preflist {$wfileprefscombo($page) insert end [file tail $pref]}
  if {$currpref == "none" || $currpref == ""} {
    set currpref [file tail [lindex $preflist 0]]
  }
  $wfileprefscombo($page) config -value $currpref
}

### load Statfile combo (Render panel create, called by 3 other live updates)
proc fixswfileprefs { page } {
  global env session iscandir hemi wasbrak wasbrakold
  global swfileprefscombo renderscanlists sessionscanlists
  global cplxstatname1 cplxstatname2 cplxstatname3 cplxstatname4 cplxstatname5
  global cplxstatname6 cplxstatname7
  global realfname realfclustname realpname realpclustname realbordcntname
  global mac_appnap_hack

  set iscandir $page
  ## (re)load stat combo with all wfiles (same as Paintfile) for user override
  set preflist [lsort [getuniqwfilelist $page]]
  set currpref "-no_mask-"
  if [info exists renderscanlists($page,sbfloatstem)] {
    set currpref $renderscanlists($page,sbfloatstem)
  } else {
    set renderscanlists($page,sbfloatstem) $currpref
  }
  $swfileprefscombo($page) subwidget listbox delete 0 end
  foreach pref $preflist {
    $swfileprefscombo($page) insert end [file tail $pref]
  }
  if {$currpref == "-no_mask-" || $currpref == ""} {
    set currpref [file tail [lindex $preflist 0]]  ;# def to first in list
  }
  $swfileprefscombo($page) config -value $currpref

  ## distinguish single-subj vs. cross-subj (4 combos)
  set type other
  if [info exists sessionscanlists($page,type)] {
    if {$sessionscanlists($page,type) == "sphavgscan"} { set type sphavgscan }
    if {$sessionscanlists($page,type) == "functscan"} { set type functscan }
    if {$sessionscanlists($page,type) == "extstatscan"} { set type extstatscan}
  }

  #### update statcombo if matching stat found (cf. tclscripts, surftestrender)
  ## singlesubj complex (no -mean- in bfloatstem: just append)
  if {$type == "functscan" && $renderscanlists($page,complexvalflag)} {
    if ![info exists renderscanlists($page,complexstatsource)] {
      set renderscanlists($page,complexstatsource) \
        $renderscanlists(def,complexstatsource) ;#for call before addrender defs
    }
    set complexstatsource $renderscanlists($page,complexstatsource)
    set tmpcplxstatname _none
    if {$complexstatsource == "sig"} { set tmpcplxstatname _none } ;#amp=sqrtF
    if {$complexstatsource == "fclu"} { ;# try order: _f, _h, _p, _q (last wins)
      foreach infix "$realfname $realfclustname $realpname $realpclustname" {
        set sbfloatstem $renderscanlists($page,bfloatstem)${infix}
        foreach pref $preflist {
          set preftail [file tail $pref]
          if { $preftail == $sbfloatstem } {
            $swfileprefscombo($page) config -value $preftail
            set tmpcplxstatname $infix
          }
          set renderscanlists($page,complexampmodtype) "mask"
        }
      }
    }
    if {$complexstatsource == "fcoh"} {
      set infix $cplxstatname7
      set sbfloatstem $renderscanlists($page,bfloatstem)${infix}
      foreach pref $preflist {
        set preftail [file tail $pref]
        if { $preftail == $sbfloatstem } {
          $swfileprefscombo($page) config -value $preftail
          set tmpcplxstatname $infix
        }
        set renderscanlists($page,complexampmodtype) "mask"
      }
    }
    if { $tmpcplxstatname == "_none" } {  ;# no mask, or nothing matched
      set renderscanlists($page,sbfloatstem) "-no_mask-"
      set renderscanlists($page,complexampmodtype) "off"
    }
    # set nomask also if infix unstripped (i.e. paintfile *not* _r,_i or _x,_y)
    if { [string match *${realfname} $renderscanlists($page,bfloatstem)] ||
     [string match *${realfclustname} $renderscanlists($page,bfloatstem)] ||
     [string match *${realpname} $renderscanlists($page,bfloatstem)] ||
     [string match *${realpclustname} $renderscanlists($page,bfloatstem)] ||
     [string match *${realbordcntname} $renderscanlists($page,bfloatstem)] } {
      set renderscanlists($page,sbfloatstem) "-no_mask-"
      set renderscanlists($page,complexampmodtype) "off"
    }
  }
  ## xsubj complex (find -mean-, subst -stat-, add infix)
  if {$type == "sphavgscan" && $renderscanlists($page,complexvalflag)} {
    if ![info exists renderscanlists($page,complexstatsource)] {
      set renderscanlists($page,complexstatsource) \
        $renderscanlists(def,complexstatsource) ;#for call before addrender defs
    }
    set complexstatsource $renderscanlists($page,complexstatsource)
    set tmpcplxstatname _none
    if {$complexstatsource == "sig"}   {set tmpcplxstatname _none}      ;#sqrtF
    if {$complexstatsource == "famp"}  {set tmpcplxstatname $cplxstatname6};#_h
    if {$complexstatsource == "fsig"}  {set tmpcplxstatname $cplxstatname2};#_g
    if {$complexstatsource == "raang"} {set tmpcplxstatname $cplxstatname4};#_e
    if {$complexstatsource == "tsig"}  {set tmpcplxstatname $cplxstatname3};#_a
    if {$complexstatsource == "tpow"}  {set tmpcplxstatname $cplxstatname5};#_b
    set i [string first -mean- $renderscanlists($page,bfloatstem)]
    if {$i != -1} {  ;# found -mean-
      set str1 [string range $renderscanlists($page,bfloatstem) 0 $i]
      set str2 \
        [string range $renderscanlists($page,bfloatstem) [expr $i + 5] end]
      ## N.B.: cf. eccen/polar/twocond tclscripts infix substitution
      # infix is _f or _g: "mean" => "stat", infix is _a: "mean" => "tstat"
      set newinfix stat
      if {$tmpcplxstatname == $cplxstatname3} { set newinfix tstat } ;# sqrtF
      if {$tmpcplxstatname == $cplxstatname5} { set newinfix tstat } ;# pow
      set sbfloatstem ${str1}${newinfix}${str2}${tmpcplxstatname}
      set found 0
      foreach pref $preflist {
        set preftail [file tail $pref]
        if { $preftail == $sbfloatstem } {
          $swfileprefscombo($page) config -value $preftail
          set found 1
        }
      }
      if {!$found && $complexstatsource == "famp"} {  ;# also try _f
        set tmpcplxstatname $cplxstatname1
        set sbfloatstem ${str1}${newinfix}${str2}${tmpcplxstatname}
        foreach pref $preflist {
          set preftail [file tail $pref]
          if { $preftail == $sbfloatstem } {
            $swfileprefscombo($page) config -value $preftail
          }
        }
      }
      set renderscanlists($page,complexampmodtype) "mask"
    }
    if { $tmpcplxstatname == "_none" } {
      set renderscanlists($page,sbfloatstem) "-no_mask-"
      set renderscanlists($page,complexampmodtype) "off"
    }
  }
  ## singlesubj real (live mask: permissive thresh vs. another set of files)
  if {$type == "functscan" || $type == "extstatscan"} {
    if {!$renderscanlists($page,complexvalflag)} {
      set bfloatstem $renderscanlists($page,bfloatstem)
      set sbfloatstem REPLACE_COEF_SUFF_FAIL
      set colscaletype $renderscanlists($page,colscaletype)
      # 3dDeconvolve: t label retains _LC@0@/_GLT@0, F omits (cf. medtestrender)
      if {$colscaletype == "fstat" || $colscaletype == "tstat"} {
        #set flistver0 { _LC#0#_coef-thresh+orig _F-stat-clust+orig } ;# omit
        #set tlistver0 { _coef-thresh+orig _t-st-clust+orig }
        set tlistver1 { _coef-thresh+orig _t-st-clust+orig } ;# use wasbrak?
        set flistver1 { _LC@0@_coef-thresh+orig _F-stat-clust+orig }
        set tlistver2 { _GLT@0_Coef-clust+orig _GLT@0_Tstat-clust+orig }
        set flistver2 { _GLT@0_Coef-clust+orig _GLT_Fstat-clust+orig }
        if {$colscaletype == "tstat"} {set verlist [list $tlistver1 $tlistver2]}
        if {$colscaletype == "fstat"} {set verlist [list $flistver1 $flistver2]}
        foreach pair $verlist {
          set coefsuff [lindex $pair 0]
          set clustsuff [lindex $pair 1]
          if [string match *$coefsuff $bfloatstem] {
            set sbfloatstem [string range $bfloatstem 0 \
                              [expr [string length $bfloatstem] - 1 - \
                              [string length $coefsuff]]]${clustsuff}
          }
        }
        if {$sbfloatstem == "REPLACE_COEF_SUFF_FAIL" &&
            $bfloatstem != "-multiple-" } {
          #xxx -- was crashing on 10.10.5, so just write to csurf log for now
          putlog "StatMask: ### auto-setting of maskfile failed because\
                \n  AFNI coef suffix not recognized on: $bfloatstem\
                \n  (1) manually pick correct StatMask Paintfile, or\
                \n  (2) change Data Type to \"real\" (no mask)"
          ####################### -- caused a few csurf crashes on 10.10
          #confirmalert "StatMask: auto-setting of maskfile failed because\
          #            \nAFNI coef suff not recognized on:\
          #          \n\n    $bfloatstem\
          #          \n\n(1) manually pick correct StatMask Paintfile, or\
          #            \n(2) change Data Type to \"real\" (no mask)"
          ##xxx: above covered up by yosemite hack xterm, hangs kill xterm
          #if {$mac_appnap_hack} { after 100 "set userok 1" }
          #######################
          set renderscanlists($page,sbfloatstem) "-no_mask-"
          #set renderscanlists($page,colscaletype) real  ;# irritating
          return
        }
        set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
        set statfile $fullscandir/${sbfloatstem}-$hemi.w
        if { ![file exists $statfile] &&
             $renderscanlists($page,renderlisttype) == "one" } {
          #xxx -- might also crash on 10.10.5, so just write to csurf log now
          putlog "StatMask: ### missing mask file:\
                \n  $statfile\
                \n  for real coef file  ...turn mask OFF"
          #######################
          #confirmalert "StatMask: missing mask file:\n\n\    $statfile\
          #          \n\nfor real coef file\n\n...turn mask OFF"
          ##xxx -- above covered up by yosemite hack xterm, hangs kill xterm
          #if {$mac_appnap_hack} { after 100 "set userok 1" }
          #######################
          set renderscanlists($page,sbfloatstem) "-no_mask-"
          set renderscanlists($page,colscaletype) real
          return
        }
        set renderscanlists($page,sbfloatstem) $sbfloatstem
      }  ;# tmsk or Fmsk
    }
  }
  ## xsubj real
  if {$type == "sphavgscan" && !$renderscanlists($page,complexvalflag)} {
#xxx -- TODO: for when/if xsubj block design panel written
  }
}

### find images in current struct mri/orig subdir
proc getstructimageslist { } {
  global env name volumedir origdir origsubdir
  set imageslist {}
  set fullorigsubdir $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$origsubdir
  set fulllist [lsort [glob -nocomplain $fullorigsubdir/*]]
  foreach im $fulllist {
    set imtail [file tail $im]
    #set imsuff [file extension $im]
    lappend imageslist $imtail
  }
  return $imageslist   ;# maybe empty
}

### find images in current funct dir
proc getfunctimageslist { } {
  global env session iscandir skipimsufflist
  set imageslist {}
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir ;# caller updates
  set fulllist [lsort [glob -nocomplain $fullscandir/*]]
  set briklist [lsort [glob -nocomplain $fullscandir/*.BRIK]]
  set headlist [lsort [glob -nocomplain $fullscandir/*.HEAD]]
  set otherlist {}
  foreach im $fulllist {
    if [string match *.BRIK $im] { continue }
    if [string match *.HEAD $im] { continue }
    lappend otherlist $im
  }
  #foreach im $fulllist { }  ;# orig
  foreach im "$briklist $headlist $otherlist" {  ;# sort BRIKs to top
    set imtail [file tail $im]
    set imsuff [file extension $im]
    # next: skip intermed 3d/surf analysis files
    if { [lsearch -exact $skipimsufflist $imsuff] >= 0 } { continue }
    if [string match *TmpClustMask+orig* $im] { continue }  ;# now saved
    if [string match *MY_AREA* $im] { continue }  ;# 3D ROI's
    lappend imageslist $imtail
  }
  return $imageslist   ;# maybe empty
}

### load/update one functscan Same-Plane combo w/align scans in current session
proc findaligns { page } {
  global env session sessionscanlists functscanlists alignscombo
  if ![info exists alignscombo($page)] { return }
  if ![winfo exists $alignscombo($page)] { return } 
  $alignscombo($page) subwidget listbox delete 0 end
  set alignslist ""
  foreach index [array names sessionscanlists] {
    set ipage [string range $index 0 [expr [string last , $index] - 1]]
    if {$ipage != "def" && $sessionscanlists($index) == "alignscan"} {
      if [file exists $env(FUNCTIONALS_DIR)/$session/$ipage] {
        lappend alignslist $ipage
      }
    }
  }
  if ![llength $alignslist] {return}
  set alignslist [lsort $alignslist]
  foreach dir $alignslist { $alignscombo($page) insert end $dir }
  set aligndir [lindex $alignslist 0]
  if [info exists functscanlists($page,aligndir)] {
    set aligndir $functscanlists($page,aligndir)
  }
  $alignscombo($page) config -value $aligndir
  if { $functscanlists($page,aligndir) == "" && [llength $alignslist] == 1 } {
    set functscanlists($page,aligndir) [lindex $alignslist 0]
  }
}

### load/update one volreg targets combo w/volreg-able scans in current session
proc findvregtargs { page } {
  global env session sessionscanlists functscanlists vregtargscombo
  if ![info exists vregtargscombo($page)] { return }
  if ![winfo exists $vregtargscombo($page)] { return }
  $vregtargscombo($page) subwidget listbox delete 0 end
  set vregtargslist ""
  foreach index [array names sessionscanlists] {
    set ipage [string range $index 0 [expr [string last , $index] - 1]]
    if {$ipage != "def" && $sessionscanlists($index) == "functscan"} {
      if [file exists $env(FUNCTIONALS_DIR)/$session/$ipage] {
        lappend vregtargslist $ipage
      }
    }
  }
  if ![llength $vregtargslist] {return}
  set vregtargslist [lsort $vregtargslist]
  foreach dir $vregtargslist { $vregtargscombo($page) insert end $dir }
  set vregtargdir [lindex $vregtargslist 0]
  if [info exists functscanlists($page,vregtargdir)] {
    set vregtargdir $functscanlists($page,vregtargdir)
  }
  $vregtargscombo($page) config -value $vregtargdir
}

### load/update 1 Select to Add combo w/rawaverageable scans curr sess (3D Raw)
proc findrawavgfuncts { page } {
  global env session sessionscanlists rawtoavgcombo rawavgdir newrawavgdir
  if { [string match ${rawavgdir}* $page] ||
       [string match */${rawavgdir}* $page] } {
    set newrawavgdir $page
  }
  if ![info exists rawtoavgcombo($page)] { return }
  if ![winfo exists $rawtoavgcombo($page)] { return } 
  $rawtoavgcombo($page) config -disablecallback true
  $rawtoavgcombo($page) subwidget listbox delete 0 end
  set rawtoavglist ""
  foreach index [array names sessionscanlists] {
    set ipage [string range $index 0 [expr [string last , $index] - 1]]
    if {$ipage != "def"} {
      if {$sessionscanlists($index) == "functscan" ||
          $sessionscanlists($index) == "extstatscan"} {
        if [file exists $env(FUNCTIONALS_DIR)/$session/$ipage] {
          lappend rawtoavglist $ipage  ;# (incl existing rawavg dirs)
        }
      }
    }
  }
  if [llength $rawtoavglist] {
    set rawtoavglist [lsort $rawtoavglist]
    foreach dir $rawtoavglist { $rawtoavgcombo($page) insert end $dir }
    set rawtoavgdir [lindex $rawtoavglist 0]
    $rawtoavgcombo($page) config -value $rawtoavgdir
  }
  $rawtoavgcombo($page) config -disablecallback false
}

### update one Select to Add combo w/sigaverage-able scans curr sess (3D Four)
proc findsigavgfuncts { page } {
  global env session sessionscanlists sigtoavgcombo sigavgdir newsigavgdir
  if { [string match ${sigavgdir}* $page] ||
       [string match */${sigavgdir}* $page] } {
    set newsigavgdir $page
  }
  if ![info exists sigtoavgcombo($page)] { return }
  if ![winfo exists $sigtoavgcombo($page)] { return }
  $sigtoavgcombo($page) config -disablecallback true
  $sigtoavgcombo($page) subwidget listbox delete 0 end
  set sigtoavglist ""
  foreach index [array names sessionscanlists] {
    set ipage [string range $index 0 [expr [string last , $index] - 1]]
    if {$ipage != "def" && $sessionscanlists($index) == "functscan"} {
      if [file exists $env(FUNCTIONALS_DIR)/$session/$ipage] {
        lappend sigtoavglist $ipage
      }
    }
  }
  if [llength $sigtoavglist] {
    set sigtoavglist [lsort $sigtoavglist]
    foreach dir $sigtoavglist { $sigtoavgcombo($page) insert end $dir }
    set sigtoavgdir [lindex $sigtoavglist 0]
    $sigtoavgcombo($page) config -value $sigtoavgdir
  }
  $sigtoavgcombo($page) config -disablecallback false
}

### no-op called on make surfavgpage
proc findsurfavgfuncts { page } {  
}

### load/update 1pair Eccen(Polar) combos w/fourier scans curr sess (Fieldsign)
proc findretins { page } {
  global env session functscanlists eccenscombo polarscombo fsdir newfsdir

  if { [string match ${fsdir}* $page] || [string match */${fsdir}* $page] } {
    set newfsdir $page    ;# reset entry for existing unconfig'd
  }
  if ![info exists eccenscombo($page)] { return }
  if ![info exists polarscombo($page)] { return }
  if ![winfo exists $eccenscombo($page)] { return } 
  if ![winfo exists $polarscombo($page)] { return } 

  $eccenscombo($page) subwidget listbox delete 0 end
  $polarscombo($page) subwidget listbox delete 0 end
  set eccenslist ""
  set polarslist ""
  foreach index [array names functscanlists] {
    set ipage [string range $index 0 [expr [string last , $index] - 1]]
    set isuff [string range $index [string last , $index] end]
    if {$ipage != "def" && $isuff == ",phasetype"} {
      if [file exists $env(FUNCTIONALS_DIR)/$session/$ipage] {
        if {$functscanlists($index) == "eccen"} { lappend eccenslist $ipage }
        if {$functscanlists($index) == "polar"} { lappend polarslist $ipage }
      }
    }
  }
  foreach dir $eccenslist { $eccenscombo($page) insert end $dir }
  foreach dir $polarslist { $polarscombo($page) insert end $dir }
  if [llength $eccenslist] {
    set eccendir [lindex $eccenslist 0]
    if [info exists functscanlists($page,eccendir)] {
      set eccendir $functscanlists($page,eccendir)
    }
    $eccenscombo($page) config -value $eccendir
  }
  if [llength $polarslist] {
    set polardir [lindex $polarslist 0]
    if [info exists functscanlists($page,polardir)] {
      set polardir $functscanlists($page,polardir)
    }
    $polarscombo($page) config -value $polardir
  }
}

### find unique wfile stems (from list of <stem>-?h.w)
proc getuniqwfilelist { anyscandir } {
  global env session
  set patt $env(FUNCTIONALS_DIR)/$session/$anyscandir/*-?h.w  ;# safer: was *.w
  set patt2 $env(FUNCTIONALS_DIR)/$session/$anyscandir/*.mgh  ;# no $hemi!
#xxx --- TODO: in contrast to .mgh, this would be read by diff funct
  #set patt3 $env(FUNCTIONALS_DIR)/$session/$anyscandir/?h_*.label  ;# TODO
  set filelist [glob -nocomplain $patt $patt2]
  set uniqstemlist {}
  foreach file $filelist {
    set stem $file
    if [string match "*-\[rl\]h.w" $file] {
      set stemend [expr [string length $file] - 6]  ;# rm -?h.w
      set stem [string range $file 0 $stemend]
    }
    if { [lsearch -exact $uniqstemlist $stem] == -1 } {
      lappend uniqstemlist $stem
    }
  }
  return $uniqstemlist   ;# maybe empty
}

### find all BRIKs (infixes not stripped till select time)
proc getbriklist { anyscandir } {
  global env session
  set patt $env(FUNCTIONALS_DIR)/$session/$anyscandir/*+orig.BRIK
  set filelist [glob -nocomplain $patt]
  return $filelist   ;# maybe empty
}

### rm pairs of stems ending with real/complex infixes (given list of stems)
proc rmcomplexstems { wfilelist } {
  global realname complexname
  set reallen [string length $realname]
  set complexlen [string length $complexname]
  if {$reallen == 0 || $complexlen == 0} { return $wfilelist }
  set noncomplexwfilelist {}
  foreach stem $wfilelist {
    set ok2add 1
    if [string match *$realname $stem] {
      set realstem \
        [string range $stem 0 [expr [string length $stem] - $reallen - 1]]
      foreach teststem $wfilelist {
        if {"$teststem" == "${realstem}${complexname}" } { set ok2add 0 }
      }
    } elseif [string match *$complexname $stem] {
      set complexstem \
        [string range $stem 0 [expr [string length $stem] - $complexlen - 1]]
      foreach teststem $wfilelist {
        if {"$teststem" == "${complexstem}${realname}" } { set ok2add 0 }
      }
    }
    if {$ok2add} { lappend noncomplexwfilelist $stem }
  }
  return $noncomplexwfilelist   ;# maybe empty
}

### find unique bfloat/BRIK stems (expects uniq list of <stem><infix>'s)
proc getuniqcomplexstemlist { uniqwfilelist } {
  global realname complexname amprealname ampcomplexname statname
  global cplxstatname1 cplxstatname2 cplxstatname3 cplxstatname4 cplxstatname5
  global cplxstatname6 realpname
  global dispername realfclustname realpclustname realbordcntname
  set uniqstemlist {}
  set reallen [string length $realname]
  set complexlen [string length $complexname]
  set ampreallen [string length $amprealname]
  set ampcomplexlen [string length $ampcomplexname]
  set statlen [string length $statname]
  foreach file $uniqwfilelist {
    if       [string match *${realname} $file] {         ;# trim _r
      set stemend [expr [string length $file] - $reallen - 1]
    } elseif [string match *${complexname} $file] {      ;# trim _i
      set stemend [expr [string length $file] - $complexlen - 1]
    } elseif [string match *${amprealname} $file] {      ;# trim _x
      set stemend [expr [string length $file] - $ampreallen - 1]
    } elseif [string match *${ampcomplexname} $file] {   ;# trim _y
      set stemend [expr [string length $file] - $ampcomplexlen - 1]
    } elseif [string match *${cplxstatname1} $file] {    ;# no trim _f
      set stemend [expr [string length $file] -1]
    } elseif [string match *${cplxstatname6} $file] {    ;# no trim _h (xsub)
      set stemend [expr [string length $file] -1]
    } elseif [string match *${realfclustname} $file] {   ;# no trim _h (single)
      set stemend [expr [string length $file] -1]
    } elseif [string match *${cplxstatname2} $file] {    ;# no trim _g
      set stemend [expr [string length $file] -1]
    } elseif [string match *${cplxstatname3} $file] {    ;# no trim _a
      set stemend [expr [string length $file] -1]
    } elseif [string match *${cplxstatname4} $file] {    ;# no trim _e
      set stemend [expr [string length $file] -1]
    } elseif [string match *${cplxstatname5} $file] {    ;# no trim _b
      set stemend [expr [string length $file] -1]
    } elseif [string match *${dispername} $file] {       ;# no trim _d
      set stemend [expr [string length $file] -1]
    } elseif [string match *${realbordcntname} $file] {  ;# no trim _k
      set stemend [expr [string length $file] -1]
    } elseif [string match *${realpname} $file] {        ;# no trim _p
      set stemend [expr [string length $file] -1]
    } elseif [string match *${realpclustname} $file] {   ;# no trim _q
      set stemend [expr [string length $file] -1]
    } elseif [string match *${statname} $file] {         ;# trim f (N.B. no '_')
      set stemend [expr [string length $file] - $statlen - 1]
    } else { continue }                                  ;# ignore unrecog
    set stem [string range $file 0 $stemend]
    if { [lsearch -exact $uniqstemlist $stem] == -1 } {
      lappend uniqstemlist $stem
    }
  }
  return $uniqstemlist   ;# maybe empty
}

### read csurf.dat into arrays (random order of lists OK, unrecognized ignored)
proc readarrayparms { datfile aspect } {
  global program
  global ${program}_vers ${program}_oldvers
  global convparms stripskullparms normalizeparms wmfilterparms wmfillparms
  global surfparms inflateparms finalparms flattenparms sphereparms lightparms
  global structscanlists sessionscanlists alignscanparms functscanlists
  global renderscanlists sphavglists postclparms
  global functscanparms  ;# oldstyle, read-only

  if {$aspect == "struct"} {
    set scriptsdir [cdsubjectscripts]
    set arraynamelist { \
      convparms stripskullparms normalizeparms wmfilterparms \
      wmfillparms surfparms inflateparms finalparms flattenparms sphereparms \
      structscanlists postclparms lightparms }
  } elseif {$aspect == "alignfunct" || $aspect == "rawavg" ||
            $aspect == "calcfour" || $aspect == "calcrand" ||
            $aspect == "sigavg" || $aspect == "surfavg" ||
            $aspect == "calcfield" || $aspect == "extstat" ||
            $aspect == "render" || $aspect == "sphavg" ||
            $aspect == "rendersphavg"} {
    set scriptsdir [cdfunctscripts]
    set arraynamelist { \
      sessionscanlists alignscanparms functscanlists renderscanlists \
      sphavglists functscanparms }
  } else { return }
  if ![file exists $datfile] { return }

  cleararrays $aspect

  set id [open $datfile r]
  set i -1
  set currarray none
  set foundprev 0
  set vers "#!${program}[set ${program}_vers]datfile"
  set oldvers "#!${program}[set ${program}_oldvers]datfile"
  foreach line [split [read $id] "\n"] {   ;# randorder/extras OK (fwdcompat)
    incr i
    if {$i == 0} {
      if {$line != $vers && $line != $oldvers} {
        confirmalert "Datfile: $datfile in\n$scriptsdir\n\has unrecognized\
                      first line:\n\n=> $line <=\n\nvalid: \t$vers\n\t$oldvers"
        setdefaultarrays
        writearrayparms $datfile $aspect
        return
      } else { continue }
    }
    if {$foundprev} {
      array set $currarray $line
      set currarray none
      set foundprev 0
      continue
    }
    foreach arrayname $arraynamelist {
      if {$line == "$program arrayname: $arrayname"} {
        set currarray $arrayname
        set foundprev 1
        break
      } 
    }
  }
  close $id
  convertsingleparms
}

### backward compat w/same-pix-for-all-functscans in orig release csurf.dat
proc convertsingleparms { } {
  global sessionscanlists functscanlists functscanparms
  set convertlist {}
  foreach parm { slices xres yres inplane thickness } {
    if {$functscanparms($parm) != "-unset-"} { lappend convertlist $parm }
  }
  if ![llength $convertlist] { return }
  set formatlist ""
  foreach parm $convertlist {
    set formatlist "$formatlist \n$parm = $functscanparms($parm)"
  }
  confirmalert "Datfile: converting old-style global functscan parms\
                to scandir-specific:\n$formatlist"
  foreach index [array names sessionscanlists] {
    set ipage [string range $index 0 [expr [string last , $index] - 1]]
    if {$ipage != "def" && $sessionscanlists($index) == "functscan"} {
      foreach parm $convertlist {
        set functscanlists($ipage,$parm) $functscanparms($parm)
      }
    }
  }
  foreach parm $convertlist { set functscanparms($parm) -unset- }
}

### clear live arrays
proc cleararrays { aspect } {
  global structscanlists sessionscanlists functscanlists renderscanlists
  global mkdscandirnames mkdrawscanfiles mkdstripinitTRs mkdnewscannames
  global sphavglists

  if {$aspect == "struct"} {
    foreach index [array names structscanlists] {
      if ![string match def,* $index] { unset structscanlists($index) }
    }
  } elseif {$aspect == "alignfunct" || $aspect == "rawavg" ||
            $aspect == "calcfour" || $aspect == "calcrand" ||
            $aspect == "sigavg" || $aspect == "surfavg" ||
            $aspect == "calcfield" || $aspect == "extstat" ||
            $aspect == "render" || $aspect == "sphavg" ||
            $aspect == "rendersphavg"} {
    foreach index [array names sessionscanlists] {
      if ![string match def,* $index] { unset sessionscanlists($index) }
    }
    foreach index [array names functscanlists] {
      if ![string match def,* $index] { unset functscanlists($index) }
    }
    foreach index [array names renderscanlists] {
      if ![string match def,* $index] { unset renderscanlists($index) }
    }
    foreach index [array names sphavglists] {
      if ![string match def,* $index] { unset sphavglists($index) }
    }
  }
  if {$aspect == "mkorigdirs" || $aspect == "mkscandirs"} { ;# no reinstate
    foreach mkdarray \
        "mkdscandirnames mkdrawscanfiles mkdstripinitTRs mkdnewscannames" {
      if [info exists $mkdarray] { unset $mkdarray }
    }
  }
}

### write live arrays into csurf.dat (Save, Save/Close, action any Setup panel)
proc writearrayparms { datfile aspect } {
  global name program
  global ${program}_vers ${program}_oldvers debugarrayparms
  global convparms stripskullparms normalizeparms wmfilterparms wmfillparms
  global surfparms inflateparms finalparms flattenparms sphereparms lightparms
  global structscanlists sessionscanlists alignscanparms functscanlists
  global renderscanlists sphavglists postclparms

  if {$aspect == "struct"} {
    set scriptsdir [cdsubjectscripts]
  } elseif {$aspect == "alignfunct" || $aspect == "rawavg" ||
            $aspect == "calcfour" || $aspect == "calcrand" ||
            $aspect == "sigavg" || $aspect == "surfavg" ||
            $aspect == "calcfield" || $aspect == "extstat" ||
            $aspect == "render" || $aspect == "sphavg" ||
            $aspect == "rendersphavg"} {
    set scriptsdir [cdfunctscripts]
  } else {
    confirmalert "writearrayparms: bad aspect ($aspect)  ...config not saved"
    return
  }
  update idletasks

  if [file exists $datfile] {
    if ![file writable $datfile] {
      confirmalert \
        "Datfile: $scriptsdir/$datfile not writable  ...config not saved"
      return
    }
    mvlog $datfile $datfile~   ;# always backup
  } else {
    if ![file writable . ] {
      confirmalert \
        "Scripts Dir: $scriptsdir not writable  ...config not saved"
      return
    }
  }
  set id [open $datfile w 0644]
  puts $id "#!${program}[set ${program}_oldvers]datfile" ;# go back: Sep2013
  foreach arrayname { \
      convparms stripskullparms normalizeparms wmfilterparms wmfillparms \
      surfparms inflateparms finalparms flattenparms sphereparms lightparms \
      structscanlists sessionscanlists alignscanparms functscanlists \
      renderscanlists sphavglists postclparms } {
    puts $id "$program arrayname: $arrayname"
    puts $id [array get $arrayname]
    if {$debugarrayparms} {
      puts "$program arrayname: $arrayname"
      foreach index [lsort [array names $arrayname]] {
        puts "  $arrayname ($index) = [set ${arrayname}($index)]"
      }
    }
  }
  close $id
  putlog "$datfile written"
}

### make sequence-of-background-processes window
proc bgsequencewin { wilabel bulabel cmdlablist commandlist { title "" } } {
  global processbu proccancelbu sequencedone
  global processkill
  global ffontbb pfont bgcol entbgcol

  set bgcmdcnt [llength $commandlist]
  set bglabcnt [llength $cmdlablist]
  if {$bgcmdcnt != $bglabcnt} { return }
  for {set i 0} {$i < $bgcmdcnt} {incr i} { global processlab$i }

  set nm .progress
  if [winfo exists $nm] {  ;# one bgsequence per interpreter
    raise $nm
    confirmalert "Finish current operation first"
    return
  }
  set f [toplevel $nm -borderwidth 10]
  if { "$title" != "" } { wm title $nm "$title" }
  positionpopup $f
  wm protocol $f WM_DELETE_WINDOW killboxOK
  label $f.la -text "$wilabel" -font $ffontbb -borderwidth 2 \
                                           -relief groove -padx 7 -pady 7
  pack $f.la -side top -anchor w
  frame $f.me -borderwidth 5
  frame $f.bu
  pack $f.me $f.bu -side top
  frame $f.me.sta -borderwidth 5 
  frame $f.me.tex -borderwidth 5
  pack $f.me.sta $f.me.tex -side left

  for {set i 0} {$i < [llength $commandlist]} {incr i} {
    if {$i == 0} {set progtext "\[process idle\]"} else {set progtext ""}
    set processlab$i [label $f.me.sta.m$i -text "$progtext" -font $pfont]
    pack $f.me.sta.m$i -side top -anchor e
    label $f.me.tex.m$i -text "--[lindex $cmdlablist $i]" -font $pfont
    pack $f.me.tex.m$i -side top -anchor w
  } 
  set processbu $f.bu.pr
  set proccancelbu $f.bu.ca
  button $processbu -text $bulabel -font $pfont -highlightbackground $bgcol \
    -command "bgsequencecmd \{$commandlist\}"
  button $proccancelbu -text "Cancel" -font $pfont \
    -highlightbackground $bgcol \
    -command "destroy $f; wm protocol . WM_DELETE_WINDOW testclose"
  pack $processbu $proccancelbu -side right -padx 5 -anchor e

  bind $nm <Return> "pack forget $proccancelbu; $processbu invoke"
  bind $processbu <ButtonRelease-1> \
     "set processkill 1; pack forget $proccancelbu"
  foreach win [info commands $f*] {$win config -background $bgcol}
  foreach win [info commands $f.me.sta*] {$win config -background $entbgcol}
  foreach win "$processbu $proccancelbu $f.la" {$win config -bg $entbgcol}

  wm protocol . WM_DELETE_WINDOW killboxOK   ;# disarm main killbox
  if { [exec uname] != "Linux" } { raise $f }
  focus $f
  update idletasks
  wm geometry $f 400x[winfo height $f]  ;# just set width
  #grab $f      ;# grab disallows simul medit/surfer
  tkwait variable sequencedone
  #grab release $f
  if [winfo exists $f] {destroy $f}
  wm protocol . WM_DELETE_WINDOW testclose  ;# re-arm
}

### do bgsequence runcmd/interrupt/progr (cmds called w/entering subjdir,name)
proc bgsequencecmd { commandlist } {
  global env name force
  global processbu sequencedone
  global processkill subprocessredo

  set bgcmdcnt [llength $commandlist]
  for {set i 0} {$i < $bgcmdcnt} {incr i} { global processlab$i }

  set currsubjectsdir $env(SUBJECTS_DIR)
  set currname $name
  wm title .progress "progress -- $currname"
  set processkill 0
  set subprocessredo 0
  for {set i 0} {$i < $bgcmdcnt} {incr i} {
    if {$processkill} { break }
    set prev [expr $i - 1]
    if {$prev >= 0}     { [set processlab$prev] config -text "done" }
    if {$i < $bgcmdcnt} { [set processlab$i]    config -text "in progress" }
    set cmd [lindex $commandlist $i]
    $cmd $currsubjectsdir $currname
  }
  if {!$processkill} {
    $processbu config -text DONE -command { }
    confirmalert "Processing sequence finished ($currname)"
  } else {
    confirmalert "Processing sequence interrupted ($currname)"
  }
  set sequencedone 1
}

### CONVERT/AVERAGE button command (Setup Structural panel)
proc averagestructscmd { } {
  global cmdlog convertstructbu
  global env name bindir afnibindir force
  global volumedir origdir structscanlists convparms csurfconvalignflag
  global vregname

  cdsubjectscripts    ;# maybe interrupted after change to struct subdir
  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name

  ### check inputs
  set invollist {}
  set involsubdirlist {}
  set formatlist ""
  foreach index [array names structscanlists] {
    if [string match def,* $index] { continue }
    if [string match *,type $index] {
      if {$structscanlists($index) == "structscan"} {
        set rawstructsubdir \
          [string range $index 0 [expr [string last ,type $index] - 1]]
        set rawhome $env(SUBJECTS_DIR)/$name/$volumedir/$origdir
        if ![file exists $rawhome/$rawstructsubdir] { continue }
        lappend involsubdirlist $rawstructsubdir
        #set imagepatt $structscanlists($rawstructsubdir,imagepatt)
        #lappend invollist $rawhome/$rawstructsubdir/$imagepatt
        set modelimage $structscanlists($rawstructsubdir,modelimage)
        lappend invollist $rawhome/$rawstructsubdir/$modelimage  ;# usu. brik
      }
    }
  }
  if ![llength $invollist] {
    confirmalert "Convert/Average: no scans to convert/average"
    return
  }
  foreach involl $invollist {
    if ![file exists $involl] {
      confirmalert "Convert/Average:\n\n    $involl ...\n\nnot found"
      return
    }
    if ![canwriteormakefile $involl] {
      confirmalert "Convert/Average: permissions\ndon't allow write to:\
                \n\n    [file dirname [lindex $invollist 0]]"
      return
    }
  }

  # warn tkmedit/freeview bug
  set rawstructsubdir [lindex $involsubdirlist 0]
  set extraopts $structscanlists($rawstructsubdir,extraopts)
  if { $structscanlists($rawstructsubdir,mgzout) &&
       ![string match *-zeropixwidth* $extraopts] &&
       ![string match "* -w*" $extraopts] } {
    set resp [okreplace "" "N.B.: lack of \"-zeropixwidth\" or \"-w\" in\
                     \n\"Other Options\" means actual voxel size\
                     \nwill be written to .mgz header (as spacingX,Y,Z)\
                   \n\nN.B.: but .mgz files with spacingX,Y,Z != 0.0\
                     \ncurrently not acceptable to MGH tkmedit\
                     \nor freeview!! (fine for csurf tkmedit)\
                   \n\nN.B.: spacing parameters in .mgz header can be\
                     \nviewed or changed later.  For example:\
                   \n\n    calcimg  -spacing  orig.mgz    => prints spacing\
                     \n    calcimg  -setspacing  0.0  0.0  0.0  orig.mgz\
                     \n    calcimg  -setspacing  1.0  1.0  1.0  orig.mgz" \
         "Skip -zeropixwith" "Use -zeropixwidth"]
    if {$resp == 0} { return }
    if {$resp == 1} { ; }  ;# default: write actual spacing into mgz header
    if {$resp == 2} { 
      set structscanlists($rawstructsubdir,extraopts) \
        "-zeropixwidth $structscanlists($rawstructsubdir,extraopts)"
    }
  }

  ### check output
  set outvol $env(SUBJECTS_DIR)/$name/$volumedir/$origdir
  if {!$force} {
    if {$structscanlists([lindex $involsubdirlist 0],mgzout)} { ;# 1st sets all
      set firstout $outvol.mgz
    } else {
      set firstout $outvol/COR-001
    }
    if [file exists $firstout] {
      if ![okreplace $firstout \
           "Images ($origdir): $firstout exists--Overwrite?" "Overwrite"] {
        confirmalert "Images: $firstout not altered"
        return
      }
    }
  }

  ### allow spaces
  set outvol [backslashspaces $outvol]  ;# backslashes OK: file exists, cdlog
  # conservative (in case it breaks something)
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog \
      "avgstructcmd: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  ### (1) no align
  if {$convparms(aligntype) == "noalign"} {
    set command \
      "$bindir/mri_average [lbackslashspaces [lsort $invollist]] $outvol"
    runacmd \
      "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    foreach rawstructsubdir $involsubdirlist {
      set formatlist "$formatlist \
      $origdir/$rawstructsubdir/$structscanlists($rawstructsubdir,imagepatt)\n"
    }
    if ![file exists $outvol/COR-256] {
      cdsubjectscripts
      confirmalert "Convert/Average ($name) failed--working on:\n\n$formatlist"
      return
    }
  }

  ### (2) mri_average -align (not yet working, expertprefs checkbutton hidden)
  if {$convparms(aligntype) == "intalign"} {
   set command \
     "$bindir/mri_average -align [lbackslashspaces [lsort $invollist]] $outvol"
    runacmd \
      "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    foreach rawstructsubdir $involsubdirlist {
      set formatlist "$formatlist \
      $origdir/$rawstructsubdir/$structscanlists($rawstructsubdir,imagepatt)\n"
    }
    if ![file exists $outvol/COR-256] {
      confirmalert "Convert/Average ($name) failed--working on:\n\n$formatlist"
      return
    }
  }

  ### (3) MNI (not implemented, expert prefs checkbutton hidden)
  if {$convparms(aligntype) == "mnialign"} {
    # TODO: run MNI script followed by mri_average w/o align (multiple cmds)
    confirmalert "MNI align not yet implemented"
    return
  }

  ### (4) manual alignment with tkregister (now rarely used)
  if {$convparms(aligntype) == "manualalign"} {  ;# registeravg
    confirmalert "manual reg w/nearest neighbor regcor avg now defunct"
    return
    ### N.B.: regcor doesn't accept mgz, regcor is nearest neigh (no interpol)
    ### N.B.: csurf code below not fixed to be space-safe
    if { [llength $involsubdirlist] > 1 } {
      confirmalert "Register/Average:\n\n\
(1) optionally adjust first scan\n\       (if badly offcenter)\n\n\
(2) register subsequent scans to first\n\       (SAVEREG, quit-tkregister)\n\n\
(3) registered average\n\       (started by last quit-tkregister)"
    }
    ## convert/(flip) each
    set involsubdirlist [lsort $involsubdirlist]
    foreach rawstructsubdir $involsubdirlist {
      foreach parm { imagepatt imtype slices inplane thickness } {
        if { ![info exists structscanlists($rawstructsubdir,$parm)] ||
             $structscanlists($rawstructsubdir,$parm) == ""} {
          confirmalert "Convert/Average: missing parm ($parm)"
          return
        }
      }
      set imagepatt $structscanlists($rawstructsubdir,imagepatt)
      set modelimage $structscanlists($rawstructsubdir,modelimage)
      set imtype $structscanlists($rawstructsubdir,imtype)
      set slices $structscanlists($rawstructsubdir,slices)
      set xres $structscanlists($rawstructsubdir,xres)
      set yres $structscanlists($rawstructsubdir,yres)
      set fov [expr 256.0 * $structscanlists($rawstructsubdir,inplane)]
      set thickness $structscanlists($rawstructsubdir,thickness)
      set extraopts $structscanlists($rawstructsubdir,extraopts)
      set fullscandir \
        $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$rawstructsubdir
      cdlog $fullscandir
      if {$imtype == "brik"} {
        forcebrikMSBfirst  \
         [file rootname $imagepatt] nowarn $convertstructbu "CONVERT/AVERAGE  "
      }
      set firstnum [findfirstnum $imtype $imagepatt]
      set opts ""
      if {$imtype == "noheader" || $imtype == "ignoreheader"} {
        set opts "-t $thickness -f $fov"
      }
      if {$xres != 256 || $yres != 256} {set opts "$opts -xysize $xres $yres"}
      set thickness $structscanlists($rawstructsubdir,thickness)
      if {$extraopts != ""} { set opts "$opts $extraopts" }
      if {$imtype == "coronal slice directory"} {
        confirmalert \
          "Convert/Average: $rawstructsubdir already converted to COR"
        continue
      }
      set flipx $structscanlists($rawstructsubdir,flipx)
      set flipy $structscanlists($rawstructsubdir,flipy)
      set flipz $structscanlists($rawstructsubdir,flipz)
      # TODO: convert/flip w/mri_convert (but still no ignorehdr)
      if {$csurfconvalignflag} { ;# ignoreheader (manalign: brik2cor here too?)
        set command \
          "$bindir/orig2cor $opts $imtype local $imagepatt $firstnum $slices"
      } else {
        set command "$bindir/mri_convert $modelimage $fullscandir"
      }
      runacmd \
        "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
      if ![file exists COR-256] {
        cdsubjectscripts
        confirmalert "Convert/Average ($name) failed: working on:\n\n\
    $origdir/$rawstructsubdir/$structscanlists($rawstructsubdir,imagepatt))"
        return
      }
      confirmalert "Convert/Average: ### flip not done (TODO)"
      #flipstruct $flipx $flipy $flipz  ;# change funct args to req cordirormgz
    }
    ## adjust target (TODO: regcor should trilinear-interpolate)
    if {$convparms(adjusttargflag)} {
      set targstruct [lindex $involsubdirlist 0]
      confirmalert " Adjust Target: $name/mri/$origdir subdir:\n\n\
                     $targstruct => $targstruct\n\n\
                     When done, SAVEREG and quit-tkregister\n\
                     to start cross-scan alignment"
      cdlog $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$targstruct
      if [file exists register.datPREADJUST] { ;# start w/existing if re-do
        mvlog register.dat register.dat~
        mvlog register.datPREADJUST register.dat
      } else { eval exec $bindir/tkregister -readinfo }
      set command \
        "$bindir/tkregister $name $origdir/$targstruct $origdir/$targstruct"
      runacmd \
        "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
      set command \
        "$bindir/regcor $name $origdir/$targstruct $origdir/$targstruct"
      runacmd \
        "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
      mvlog register.dat register.datPREADJUST
      set command "$bindir/tkregister -readinfo"  ;# TODO: won't work mgz!
      runacmd \
        "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
    }
    ## skip out if only one
    if { [llength $involsubdirlist] == 1 } {
      cdlog $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$rawstructsubdir
      foreach corfile [glob COR-*] {
        mvlog $corfile $env(SUBJECTS_DIR)/$name/$volumedir/$origdir
      }
      cdsubjectscripts
      writearrayparmscmd $origsubjectsdir $origname
      confirmalert "Convert/Average ($name) done"
      return
    }
    ## manual reg each to target
    set targstruct [lindex $involsubdirlist 0]
    foreach rawstructsubdir $involsubdirlist {
      cdlog $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$rawstructsubdir
      if {$rawstructsubdir == $targstruct} {
        set command "$bindir/tkregister -readinfo"
      } else {
        confirmalert "Manual Register/Average: $name/mri/$origdir subdirs:\
                  \n\n    $rawstructsubdir => $targstruct\
                  \n\nWhen done, SAVEREG and quit-tkregister\
                  \n\nAverage is done after last\
                    \nSAVEREG/quit-tkregister"
        set command "$bindir/tkregister \
          $name $origdir/$rawstructsubdir $origdir/$targstruct"
      }
      runacmd \
        "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
    }
    cdsubjectscripts
    ## average (TODO: regcor should trilinear-interpolate)
    set preflist ""
    foreach rawstructsubdir $involsubdirlist {
      set preflist "$preflist $origdir/$rawstructsubdir"
    }
    set command "$bindir/regcor $name $preflist $origdir"
    runacmd \
      "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    cplog \
      $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$rawstructsubdir/COR-.info \
      $env(SUBJECTS_DIR)/$name/$volumedir/$origdir

    foreach rawstructsubdir $involsubdirlist {
      rmlog [glob -nocomplain \
        $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$rawstructsubdir/COR-*]
      set imagepatt $structscanlists($rawstructsubdir,imagepatt)
      set formatlist "$formatlist $origdir/$rawstructsubdir/$imagepatt\n"
    }
  } ;# end manualalign

  ### (5) AFNI 3dvolreg (default)
  if {$convparms(aligntype) == "afnialign" ||
      $convparms(aligntype) == "afnihalign"} {
    set formatlist ""
    foreach fullinbrik $invollist {
      if { [file extension $fullinbrik] != ".BRIK"} {
        confirmalert " Convert/Average: AFNI align requires BRIK inputs\n\
                       Suffix not .BRIK on input file:\n\n    $fullinbrik"
        return
      }
      set formatlist "$formatlist $fullinbrik\n"
    }
    if { [llength $invollist] > 1 } {
      confirmalert "AFNI Register/Average:\
                \n\n(1) register each BRIK to first (3dvolreg)\
                \n\n(2) average registered BRIKs (3dcalc)\
                \n\n(3) convert avg BRIK to COR\
                  \n       (N.B.: parms/flip from 1st scan only!)\
                  \n       (N.B.: ignores \"Adjust target before align\")"
    }
    ## align each additional brik to first one using 3dvolreg within subdirs
    set fulltargbrik [lindex [lsort $invollist] 0]  ;# fullpath sorts by subdir
    set fullregbriklist ""
    foreach fullinbrik [lsort $invollist] {
      if {"$fullinbrik" == "$fulltargbrik"} { continue }
      set rawstructsubdir [file dirname $fullinbrik] 
      set inbrik [file tail $fullinbrik]
      set stemend [expr [string length $inbrik] - 11] ;# strip +orig.BRIK
      set regstem [string range $inbrik 0 $stemend]-${vregname}  ;# add -vreg
      set regbrik ${regstem}+orig.BRIK
      set reghead ${regstem}+orig.HEAD
      cdlog $rawstructsubdir    ;# 3dvolreg reads anywhere, writes locally
      if [file exists $regbrik] { rmlog $regbrik }  ;# else AFNI interface
      if [file exists $reghead] { rmlog $reghead }
      set opts "-twodup -twopass -verbose"
      if {$convparms(aligntype) == "afnihalign"} { set opts "$opts -heptic" }
      set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dvolreg \
        $opts -prefix $regstem \
        -base [backslashspaces $fulltargbrik] [backslashspaces $fullinbrik]"
      runacmd \
        "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
      set fullregbriklist \
        "$fullregbriklist $rawstructsubdir/$regstem+orig.BRIK"
    }
    ## avg with 3dcalc
    set opts "-verbose"
    set taglist "a b c d e f g h i j k l m n o p q r s t u v w x y z"
    set fullavgbriklist \
      "[backslashspaces $fulltargbrik] [backslashspaces $fullregbriklist]"
    set fullavgarglist ""
    set i 0
    set formatlist "$formatlist\n\nregistered inputs:\n"
    foreach fullavgbrik $fullavgbriklist {
      if {$i == 0} {
        set afniexpr [lindex $taglist $i]
      } else {
        set afniexpr "$afniexpr+[lindex $taglist $i]"
      }
      set fullavgarglist \
        "$fullavgarglist -[lindex $taglist $i] [backslashspaces $fullavgbrik]"
      set formatlist "$formatlist $fullavgbrik\n"
      incr i
    }
    if {$i > 26} {
      confirmalert "Convert/Average: too many BRIKS to avg w/3dcalc (max=26)"
      cdsubjectscripts
      return
    }
    set afniexpr ($afniexpr)/$i.0
    set avgbrikstem origavg${i}  ;# no spaces
    set avgbrik $avgbrikstem+orig.BRIK
    if [file exists $avgbrik] { rmlog $avgbrik }
    cdlog $outvol  ;# orig dir (outvol already-backslashed)
    if { [llength $fullavgbriklist] > 1 } {   ;# backslashed spaces OK
      set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
        $opts $fullavgarglist -expr $afniexpr -prefix $avgbrikstem"
      runacmd \
        "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
    } else {  ;# copy single scan
      cplog $fulltargbrik                      $avgbrikstem+orig.BRIK
      cplog [file rootname $fulltargbrik].HEAD $avgbrikstem+orig.HEAD
    }
    forcebrikMSBfirst \
      $avgbrikstem+orig nowarn $convertstructbu "CONVERT/AVERAGE  "
    ## convert to mgz COR-, possible flip (N.B.: use parms/flips from 1st scan!)
    set rawstructsubdir [lindex $involsubdirlist 0]
    set imagepatt  $avgbrikstem+orig.BRIK
    set modelimage $avgbrikstem+orig.BRIK
    set imtype $structscanlists($rawstructsubdir,imtype)
    set slices $structscanlists($rawstructsubdir,slices)
    set xres $structscanlists($rawstructsubdir,xres)
    set yres $structscanlists($rawstructsubdir,yres)
    set fov [expr 256.0 * $structscanlists($rawstructsubdir,inplane)]
    set thickness $structscanlists($rawstructsubdir,thickness)
    set extraopts $structscanlists($rawstructsubdir,extraopts)
    set fullscandir $env(SUBJECTS_DIR)/$name/$volumedir/$origdir ;# =outvol
    cdlog $fullscandir
    set firstnum [findfirstnum $imtype $imagepatt]
    set opts ""
    if {$imtype == "noheader" || $imtype == "ignoreheader"} {
      set opts "-t $thickness -f $fov"
    }
    if {$xres != 256 || $yres != 256} {set opts "$opts -xysize $xres $yres"}
    if {$extraopts != ""} { set opts "$opts $extraopts" }
    # undo AFNI floatfac
    set prescale 1.0
    set found 0
    foreach arg $extraopts {
      if {$arg == "-p" || $arg == "-prescale" } { set found 1; continue }
      if {$found} { set prescale $arg; break }
    }
    set afnifloatfac [getafnifloatfac $avgbrikstem+orig.HEAD 0]
    if {$afnifloatfac == "" || $afnifloatfac == 0} { set afnifloatfac 1.0 }
    set opts "$opts -p [expr $prescale * 1.0/$afnifloatfac]"
    set cordirormgzfile ""  ;# empty cancels flip
    set flipx $structscanlists($rawstructsubdir,flipx)
    set flipy $structscanlists($rawstructsubdir,flipy)
    set flipz $structscanlists($rawstructsubdir,flipz)
    if {$csurfconvalignflag} {
      if {$imtype == "brik"} {  ;# translates ORIENT_SPECIFIC (flip) from HEAD
        if {$structscanlists([lindex $involsubdirlist 0],mgzout)} { ;#cf. above
          set cordirormgzfile ../[file tail [pwd]].mgz     ;# ../orig.mgz
        } else {
          set cordirormgzfile [pwd]  ;# /usr0/subjects/marty/mri/orig
        }
        set command "$bindir/brik2cor \
          $imagepatt [backslashspaces $cordirormgzfile] $extraopts"
      } else {  ;# not a BRIK, ignores ORIENT_SPECIFIC (need flip, now ignores)
        #set cordirormgzfile [pwd]  ;# TODO: don't cancel flip w/empty
        set command \
          "$bindir/orig2cor $opts $imtype local $imagepatt $firstnum $slices"
      }
    } else {
      #set cordirormgzfile [pwd]  ;# TODO: don't cancel flip w/empty
      set command \
        "$bindir/mri_convert $modelimage [backslashspaces $fullscandir]"
    }
    runacmd \
      "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    cdlog $env(SUBJECTS_DIR)/$name/$volumedir  ;# back out 1 for flipstruct
    flipstruct [file tail cordirormgzfile] $flipx $flipy $flipz ;#brackets spOK
    #TODO: allow adj avg COR (see above, extra button, warn translate only)
    cdsubjectscripts
  } ;# end afnialign

  ### feedback
  writearrayparmscmd $origsubjectsdir $origname
  if  { [info exists opts] && [string match *-hires* $opts] } {
    if {$structscanlists([lindex $involsubdirlist 0],mgzout)} { ;# cf. above
      set outmsg "$origdir.mgz (512^3, 0.5mm^3)"
    } else { 
      set outmsg "$origdir/COR-001 -> $origdir/COR-512"
    }
  } else {
    if {$structscanlists($rawstructsubdir,mgzout)} {
      set outmsg "$origdir.mgz (256^3, 1.0mm^3)"
    } else { 
      set outmsg "$origdir/COR-001 -> $origdir/COR-256"
    }
  }
  confirmalert \
   "Average ($origname) done:\n\n\nraw inputs:\n\n$formatlist\n\naverage:\n\n\
      $outmsg"
}

### flip CORdir or mgz struct in pwd during CONVERT/AVERAGE
proc flipstruct { cordirormgzfile flipx flipy flipz } {
  global mtmptcl bindir cmdlog convertstructbu

  if ![file exists $cordirormgzfile] { return }
  if {$flipx == "x" && $flipy == "y" && $flipz == "z"} { return }
  foreach var "$flipx $flipy $flipz" {
    if {$var !=  "x" && $var !=  "y" && $var !=  "z" &&
        $var != "-x" && $var != "-y" && $var != "-z"} { return }
  }
  set id [open $mtmptcl w 0644]
  puts $id "flip_corview_xyz $flipx $flipy $flipz"
  puts $id "write_images"
  puts $id "exit"
  close $id
  set command "$bindir/tkmedit $cordirormgzfile -tcl $mtmptcl"
  runacmd \
    "$command" $convertstructbu "CONVERT/AVERAGE  " cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
  rmlog $mtmptcl
}

### guess number possibly embedded in first imgname (incomplete, for orig2cor)
proc findfirstnum { imtype imagepatt } {
  set firstnum 1
  if {$imtype == "siemens"} {
    set ext [file extension $imagepatt]
    set patt \
      [string range $imagepatt 0 [expr [string last % $imagepatt] - 1]]*${ext}
    set nlist {}
    set files [glob -nocomplain $patt]
    foreach file $files {
      lappend nlist \
       [string range [file rootname $file] [expr [string last - $file] +1] end]
    }
    set firstnum [lindex [lsort -integer $nlist] 0]
  }
  if {$imtype == "bshort"} { set firstnum 0 }
  # TODO: only works for Siemens, bshort => else default is 1
  return $firstnum
}

### Process Volume menu command
proc processvolume { } {
  global env name talairachflag datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  set cmdlablist { "normalize intensities" "compute Talairach"\
                   "strip skull" "segment white matter" }
  set commandlist { normalizecmd talairachcmd stripskullcmd wmfiltercmd }
  if {!$talairachflag} {
    set cmdlablist [ldelete $cmdlablist "compute Talairach"]
    set commandlist [ldelete $commandlist talairachcmd]
  }
  set wilabel "PROCESS VOLUME"
  set bulabel ProcessVolume
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

### Process Volume step 1 (of 4) command
proc normalizecmd { subjectsdir name } {
  global cmdlog processbu processkill subprocessredo
  global normalizeparms
  global volumedir origdir t1dir braindir wmdir filleddir
  global force bindir

  set invol $subjectsdir/$name/$volumedir/$origdir
  set outvol $subjectsdir/$name/$volumedir/$t1dir

  set opts ""
  if {$normalizeparms(intensgradlim) != "default"} { 
    set opts "$opts -g $normalizeparms(intensgradlim)"
  }
  if {$normalizeparms(normsteps) != "default"} { 
    set opts "$opts -n $normalizeparms(normsteps)"
  }
  if {$normalizeparms(manualcontrol)} {
    set controldat $subjectsdir/$name/tmp/control.dat 
    set opts "$opts -f $controldat"
  }
  set command "$bindir/mri_normalize $opts \
    [backslashspaces $invol] [backslashspaces $outvol]"

  set infofile $invol/COR-.info
  if ![file exists $infofile] {
    confirmalert "Parameter File: $infofile\nnot found  ...convert first"
    set processkill 1
    return
  }
  set firstin $invol/COR-001
  if ![file exists $firstin] {
    confirmalert "Images ($origdir): $firstin...\nnot found  ...convert first"
    set processkill 1
    return
  }

  set firstinfo $subjectsdir/$name/$volumedir/$t1dir/COR-.info
  if ![canwriteormakefile $firstinfo] {
    confirmalert \
      "Images ($t1dir): can't copy COR-.info to $firstinfo\n...fix permissions"
    set processkill 1
    return
  }
  foreach subdir "$t1dir $braindir $wmdir $filleddir" {
    cplog $subjectsdir/$name/$volumedir/$origdir/COR-.info \
          $subjectsdir/$name/$volumedir/$subdir
  }
  if {!$force} {
    set firstout $outvol/COR-001
    if [file exists $firstout] {
      if {$subprocessredo} {
        set action [okreplace $firstout \
          "Normalize: Images ($t1dir): $firstout...\
          exist (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $firstout \
          "Normalize: Images ($t1dir): $firstout...\
          exist--use them or redo/overwrite?" "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu NORMALIZEintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Process Volume (optional) step 2 (of 4) command
proc talairachcmd { subjectsdir name } {
  global cmdlog processbu processkill subprocessredo
  global volumedir avgdir 
  global origdir t1dir braindir wmdir filleddir
  global env force bindir
  global mincbindir talairachmeth mniproto

  set invol $subjectsdir/$name/$volumedir/$t1dir  ;# was origdir

  if {$talairachmeth == "mni"} {  ;# portable-ized MNI
    # requires: (1) hacked mritotal, (2) csh setenv MNI_CONFIG_PATH, PERL5LIB
    #set mnimodeldir $env(CSURF_DIR)/local/lib/mni_autoreg/model ;# old dirs
    set mnimodeldir $env(CSURF_DIR)/mni_autoreg/model
    set refvol $mnimodeldir/average_305.mnc
    set mincfile $invol/fromcor.mnc
    set xform $subjectsdir/$name/$volumedir/transforms/talairach.xfm
    set command "$mincbindir/mritotal -clobber -modeldir $mnimodeldir \
       -protocol $mniproto $mincfile $xform"
  }

  set firstin $invol/COR-001
  if ![file exists $firstin] {
    confirmalert "Images ($t1dir): $firstin...\nnot found  ...normalize first"
    set processkill 1
    return
  }
  if ![file exists $refvol] {
    confirmalert "Images (lib): Talairach reference volume: $refvol\nnot found"
    set processkill 1
    return
  }
  if {!$force} {
    if [file exists $xform] {
      if {$subprocessredo} {
        set action [okreplace $xform \
          "Make Transform: $xform exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $xform \
          "Make Transform: $xform exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      #if {$action == 2} { set command "sleep 0" }     ;# standard use existing
      if {$action == 2} { exec sleep 0; return }       ;# also skip convert
    }
  }

  # TODO: allow interrupt convert, fix printfs w/backslash-n + fflush(stdout)
  if {$talairachmeth == "mni"} {  ;# after ask interrupt, before runacmd
    if {!$force} {
      confirmalert \
       "Csurf interface will be unresponsive during Talairaching (OK starts)"
    }
    putlog "$bindir/mri_convert2001 $invol $mincfile"
    exec $bindir/mri_convert2001 $invol $mincfile
  }

  runacmd "$command" $processbu TALAIRACHintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid

  if {$talairachmeth == "mni"} {  ;# insert xform file name into each COR-.info
    if [file exists $mincfile] { rmlog $mincfile }
    foreach subdir "$origdir $t1dir $braindir $wmdir $filleddir" {
      set headerfile $subjectsdir/$name/$volumedir/$subdir/COR-.info
      if [file exists $headerfile] {
        mvlog $headerfile $headerfile~
        set idout [open $headerfile w 0644]
        set idin [open $headerfile~ r]
        foreach line [split [read $idin] "\n"] {
          if { [lindex $line 0] != "xform" } {
            puts $idout $line
          }
          if { [lindex $line 0] == "ti" } {
            puts $idout "xform [file tail $xform]"
          }
        }
        close $idin
        close $idout
      }
    }
  }

}

### Process Volume step 3 (of 4) command
proc stripskullcmd { subjectsdir name } {
  global cmdlog processbu processkill subprocessredo
  global stripskullparms
  global volumedir t1dir braindir
  global force bindir csurfstripskullflag

  set invol  $subjectsdir/$name/$volumedir/$t1dir
  set outvol $subjectsdir/$name/$volumedir/$braindir

  # viewing, but no Linux port
  #set tclenv "fzero=$stripskullparms(fzero) fmax=$stripskullparms(fmax) \
               dfrac=$stripskullparms(dfrac) istilt=$stripskullparms(istilt)"
  #set command "env $tclenv tktrishrink $name 0 -tcl stripskull.tcl"

  if {$csurfstripskullflag} {
    set usedat 1
    if {$stripskullparms(fzero) == "default" ||
        $stripskullparms(fmax) == "default" ||
        $stripskullparms(dfrac) == "default" ||
        $stripskullparms(istilt) == "default"} {
      set usedat 1
      set stripskullparms(fzero) default
      set stripskullparms(fmax) default
      set stripskullparms(dfrac) default
      set stripskullparms(istilt) default
    }
    set command "$bindir/mri_strip_skull $name 1"
  } else {
    set command "$bindir/mri_watershed \
      [backslashspaces $invol] [backslashspaces $outvol"
  }

  set firstin $invol/COR-001
  if ![file exists $firstin] {
    confirmalert "Images ($t1dir): $firstin...\nnot found  ...normalize first"
    set processkill 1
    return
  }
  if {!$force} {
    set firstout $outvol/COR-001
    if [file exists $firstout] {
      if {$subprocessredo} {
        set action [okreplace $firstout \
          "Stripskull: Images ($braindir): $firstout...\
          exist (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $firstout \
          "Stripskull: Images ($braindir): $firstout...\
          exist--use them or redo/overwrite?" "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  if {$csurfstripskullflag} {
    if { $usedat && [canwriteormakefile brain.dat] } {
      set id [open brain.dat w 0644]
      puts $id "fzero $stripskullparms(fzero)"
      puts $id "fmax $stripskullparms(fmax)"
      puts $id "dfrac $stripskullparms(dfrac)"
      puts $id "istilt $stripskullparms(istilt)"
      close $id
    }
  }
  runacmd "$command" $processbu STRIPSKULLintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
  if [file exists brain.dat] { rmlog brain.dat }
}

### Process Volume step 4 (of 4) command
proc wmfiltercmd { subjectsdir name } {
  global cmdlog processbu processkill subprocessredo
  global wmfilterparms
  global volumedir braindir wmdir
  global force bindir

  set invol $subjectsdir/$name/$volumedir/$braindir  ;# TODO: wmfilter parms
  set outvol $subjectsdir/$name/$volumedir/$wmdir

  ## TODO: needs abs talairach xform file name (../transforms/talairach.xfm OK)
  #set command "wmfilter $name 1"             ;# old one
  #set command "$bindir/mri_wmfilter $name"   ;# defaults if no wmfilter.dat

  set opts ""
  if {$wmfilterparms(keepedits)} {
    set opts "$opts -keep"
  }
  if {$wmfilterparms(wm_hi) != "default"} { 
    set opts "$opts -wm_hi $wmfilterparms(wm_hi)"
  }
  if {$wmfilterparms(wm_low) != "default"} { 
    set opts "$opts -wm_low $wmfilterparms(wm_low)"
  }
  if {$wmfilterparms(gray_hi) != "default"} { 
    set opts "$opts -gray_hi $wmfilterparms(gray_hi)"
  }
  set command "$bindir/mri_segment $opts \
    [backslashspaces $invol] [backslashspaces $outvol]"
  ## TODO: more parms
  # -wsize $wmfilterparms(wsize)
  # -pct $wmfilterparms(pct)
  # -nslope $wmfilterparms(nslope)
  # -pslope $wmfilterparms(pslope)
  # -nseg $wmfilterparms(nseg)       
  # $wmfilterparms(thicken) => -thicken
  # $wmfilterparms(fillbg) => -fillbg
  # $wmfilterparms(fillv) => -fillv

  set firstin $invol/COR-001
  if ![file exists $firstin] {
    confirmalert \
      "Images ($braindir): $firstin...\nnot found  ...stripskull first"
    set processkill 1
    return
  }
  if {!$force} {
    set firstout $outvol/COR-001
    if [file exists $firstout] {
      if {$subprocessredo} {
        set action [okreplace $firstout \
          "Segment WM: Images ($wmdir): $firstout...\nexist\
          (stale, but may be edited!)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $firstout \
          "Segment WM: Images ($wmdir): $firstout...\nexist\
          (may be edited!)--use them or redo/overwrite?" "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu FILTERWMintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Create Surface menu command
proc createsurface { } {
  global env name hemi t1dir datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  #selecthemi "Process both hemispheres?" ;# re-fill may make other surf stale
  set hemi both
  if { [checkcorinfoFOV $t1dir] == "zerofovT1" } { return }
  if {$hemi == "both"} {
    set cmdlablist { "fill white matter" "tessellate white matter"\
      "smooth RH white matter" "smooth LH white matter"\
      "inflate RH surface" "inflate LH surface" }
    set commandlist { wmfillcmd tessellcmd \
      smoothcmdrh smoothcmdlh inflatecmdrh inflatecmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "fill white matter" "tessellate white matter"\
      "smooth RH white matter" "inflate RH surface" }
    set commandlist { wmfillcmd tessellcmd smoothcmdrh inflatecmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "fill white matter" "tessellate white matter"\
      "smooth LH white matter" "inflate LH surface" }
    set commandlist { wmfillcmd tessellcmd smoothcmdlh inflatecmdlh }
  }
  set wilabel "CREATE SURFACE"
  set bulabel CreateSurface
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

### Create Surface (no fill) menu command
proc createsurfacenofill { } {
  global env name hemi t1dir

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  #selecthemi "Process both hemispheres?" ;# re-fill may make other surf stale
  set hemi both
  if { [checkcorinfoFOV $t1dir] == "zerofovT1" } { return }
  if {$hemi == "both"} {
    set cmdlablist { "tessellate white matter"\
      "smooth RH white matter" "smooth LH white matter"\
      "inflate RH surface" "inflate LH surface" }
    set commandlist { tessellcmd \
      smoothcmdrh smoothcmdlh inflatecmdrh inflatecmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "tessellate white matter"\
      "smooth RH white matter" "inflate RH surface" }
    set commandlist { tessellcmd smoothcmdrh inflatecmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "tessellate white matter"\
      "smooth LH white matter" "inflate LH surface" }
    set commandlist { tessellcmd smoothcmdlh inflatecmdlh }
  }
  set wilabel "CREATE SURFACE NO FILL"
  set bulabel CreateSurfaceNoFill
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

### Create Surface step 1 command (old FreeSurfer0.8 + hi-res, TODO:MGH)
proc wmfillcmd { subjectsdir name } {
  global cmdlog processbu processkill subprocessredo
  global wmfillparms
  global volumedir wmdir filleddir
  global force bindir

  set invol $subjectsdir/$name/$volumedir/$wmdir
  set outvol $subjectsdir/$name/$volumedir/$filleddir

  if {$wmfillparms(usehiresfillflag)} {  ;# reconditioned old w/hi-res
#xxx -- TODO: put next outside when upgrade to MGH mri_fill that can read mgz
    set firstim $invol/COR-001
    if ![file exists $firstim] {
      set invol $invol.mgz   ;# TODO: .mgh
      set outvol $outvol.mgz
      if ![file exists $invol] {
        confirmalert " Input to \"flll\"not found in:\n\n\
                       $subjectsdir/$name/$volumedir\n\n\
                       Looked for:\n\n\
                         (1) [file tail [file rootname $invol]]  (COR dir)\n\
                         (2) [file tail $invol]"
        set processkill 1
        return
      }
    } else {  ;# CORdir exists
      if [file exists $invol.mgz] {  ;# warn CORdir precedence
        confirmalert "${wmdir}/COR-001 (CORdir) and $wmdir.mgz both present:\
                       \n\nUsing CORdir (move CORdir aside to use mgz)"
      }
    }
    set opts "-nseed 2 \
      -seed1val $wmfillparms(seed1valRH) -seed2val $wmfillparms(seed2valLH)"
    set opts "$opts \
      -seed1ASL $wmfillparms(seed1A) $wmfillparms(seed1S) $wmfillparms(seed1L)"
    set opts "$opts \
      -seed2ASL $wmfillparms(seed2A) $wmfillparms(seed2S) $wmfillparms(seed2L)"
    set opts "$opts -callosumPA $wmfillparms(callP) $wmfillparms(callA)"
    set opts "$opts -callosumIS $wmfillparms(callI) $wmfillparms(callS)"
    set opts "$opts -callosumRL $wmfillparms(callR) $wmfillparms(callL)"
    set opts "$opts -midbrainPA $wmfillparms(midbP) $wmfillparms(midbA)"
    set opts "$opts -midbrainIS $wmfillparms(midbI) $wmfillparms(midbS)"
    set opts "$opts -midbrainRL $wmfillparms(midbR) $wmfillparms(midbL)"
    set opts "$opts -max_fill_iter $wmfillparms(max_fill_iter)"
    set opts "$opts -min_filled_per_cyc $wmfillparms(min_filled_per_cyc)"
    set opts "$opts -max_same_neigh $wmfillparms(max_same_neigh)"
    set opts "$opts -cutsfeedback $wmfillparms(clipfeedback)"
    set opts "$opts -wmfillthresh $wmfillparms(wmfillthresh)"
    set command "$bindir/fill \
      [backslashspaces $invol] [backslashspaces $outvol] $opts"
  } else {  ;# mri_fill
    set firstin $invol/COR-001
    if ![file exists $firstin] {
      confirmalert \
        "Images ($wmdir): $firstin...\nnot found  ...wmfilter,edit first"
      set processkill 1
      return
    }
    set ponscall $subjectsdir/$name/$volumedir/tmp/ponscall.dat
    set opts ""
    if {$wmfillparms(ponspnt)} {
      set opts "$opts \
        -P $wmfillparms(ponsx) $wmfillparms(ponsy) $wmfillparms(ponsz)"
    }
    if {$wmfillparms(callpnt)} {
      set opts "$opts \
        -C $wmfillparms(callx) $wmfillparms(cally) $wmfillparms(callz)"
    }
    if {$wmfillparms(ccmask)} {
      set opts "$opts -ccmask"
    }
    if {$wmfillparms(max_same_neigh) != "default"} {
      set opts "$opts -T $wmfillparms(max_same_neigh)"
    }
    if [canwriteormakefile $ponscall] {
      set opts "$opts -L $ponscall"
    }
    set opts \
      "-lval $wmfillparms(seed2valLH) -rval $wmfillparms(seed1valRH) $opts
    set command "$bindir/mri_fill $opts \
      [backslashspaces $invol] [backslashspaces $outvol]"
  }

  if {!$force} {
    if { [file extension $outvol] == ".mgz" } {
      set firstout $outvol
    } else {
      set firstout $outvol/COR-001
    }
    if [file exists $firstout] {
      if {$subprocessredo} {
        set action [okreplace $firstout \
          "Fill WM: Images ($filleddir): $firstout...\n\
          exist (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $firstout \
          "Fill WM: Images ($filleddir): $firstout...\n\
          exist--use them or redo/overwrite?" "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu FILLWMintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Create Surface step 2 command
proc tessellcmd { subjectsdir name } {
  global cmdlog processbu processkill subprocessredo
  global volumedir filleddir
  global wmfillparms
  global surfdir origext
  global force bindir hemi

  set invol $subjectsdir/$name/$volumedir/$filleddir
  foreach hemi { rh lh } {
    if {$hemi == "rh"} { set fillcolor $wmfillparms(seed1valRH) }
    if {$hemi == "lh"} { set fillcolor $wmfillparms(seed2valLH) }
    set origsurf $subjectsdir/$name/$surfdir/$hemi.$origext
    set command "$bindir/mri_tessellate [backslashspaces $invol] \
      $fillcolor [backslashspaces $origsurf]"
    set firstin $invol/COR-001
    if ![file exists $firstin] {
      confirmalert \
        "Images ($filleddir): $firstin...\nnot found  ...wmfill first"
      set processkill 1
      return
    }
    if {!$force} {
      if [file exists $origsurf] {
        if {$subprocessredo} {
          set action [okreplace $origsurf \
            "Tessellate: Surface: $origsurf exists (stale)--redo/overwrite?" \
            "Redo"]
        } else {
          set action [okreplace $origsurf \
           "Tessellate: Surface: $origsurf exists--use it or redo/overwrite?" \
            "Redo" "Use Existing"]
        }
        if {$action == 0} { set processkill 1; return }  ;# cancel
        if {$action == 1} { set subprocessredo 1 }       ;# overwrite
        if {$action == 2} { set command "sleep 0" }      ;# use existing
      }
    }
    runacmd "$command" $processbu TESSELLATEintr cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
  }
}

### Fix Topology menu command
proc fixtopology { } {
  global env name hemi datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "quick sphere RH surface" "quick sphere LH surface"\
      "fix topology RH surface" "fix topology LH surface"\
      "resmooth RH white matter" "resmooth LH white matter"\
      "reinflate RH surface" "reinflate LH surface" }
    set commandlist { qspherecmdrh qspherecmdlh \
      fixtopologycmdrh fixtopologycmdlh \
      smoothcmdrh smoothcmdlh inflatecmdrh inflatecmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "quick sphere RH surface" "fix topology RH surface"\
      "resmooth RH white matter" "reinflate RH surface" }
    set commandlist { qspherecmdrh fixtopologycmdrh smoothcmdrh inflatecmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "quick sphere LH surface" "fix topology LH surface"\
      "resmooth LH white matter" "reinflate LH surface" }
    set commandlist { qspherecmdlh fixtopologycmdlh smoothcmdlh inflatecmdlh }
  }
  set wilabel "FIX TOPOLOGY"
  set bulabel FixTopology
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc qspherecmdrh { subjectsdir name } {
  qspherecmd $subjectsdir $name rh
}

proc qspherecmdlh { subjectsdir name } {
  qspherecmd $subjectsdir $name lh
}

### Fix Topology step 1 (of 4) command
proc qspherecmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global sphereparms
  global force bindir
  global surfdir inflatedext qsphereext

  #set iter 200  ;# default iters, -inflate => inflate before project
  set inflatedsurf $subjectsdir/$name/$surfdir/$hemi.$inflatedext
  set qspheresurf $subjectsdir/$name/$surfdir/$hemi.$qsphereext
  set command "$bindir/mris_sphere -q -inflate \
    [backslashspaces $inflatedsurf] [backslashspaces $qspheresurf]"
  ###next failed to fix quick sphere occip failure w/0.75mm brain faking 1.0mm
  ## major failure (quits w/o write): huge polygons underlaying much of surf
  #set command "$bindir/mris_sphere -inflate $inflatedsurf $qspheresurf"
  ## 1000's small holes uniform distr, 2nd redraw wave even smaller holes (?!)
  #set command "$bindir/mris_sphere $inflatedsurf $qspheresurf"
  if ![file exists $inflatedsurf] {
    confirmalert "Surface: $inflatedsurf\nnot found  ...smooth first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $qspheresurf] } {
      if {$subprocessredo} {
        set action [okreplace $qspheresurf \
        "QSphere Surface: $qspheresurf exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $qspheresurf \
          "QSphere Surface: $qspheresurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu QSPHEREintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

proc fixtopologycmdrh { subjectsdir name } {
  fixtopologycmd $subjectsdir $name rh
}

proc fixtopologycmdlh { subjectsdir name } {
  fixtopologycmd $subjectsdir $name lh
}

### Fix Topology step 2 (of 4) command
proc fixtopologycmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global force bindir
  global surfdir
  global origext qsphereext fixext

  set origsurf    $subjectsdir/$name/$surfdir/$hemi.$origext
  set qsphere     $subjectsdir/$name/$surfdir/$hemi.$qsphereext
  set origsurffix $subjectsdir/$name/$surfdir/$hemi.${origext}${fixext}

  if {$fixext == ""} {
    set command "$bindir/mris_fix_topology -name $qsphereext \
      -orig $origext -add $name $hemi"
  } else {
    set command "$bindir/mris_fix_topology -name $qsphereext \
      -orig ${origext}${fixext} -suffix $fixext -add $name $hemi"
  }
  if ![file exists $origsurf] {
    confirmalert "Surface: $origsurf\nnot found  ...tessellate first"
    set processkill 1
    return
  }
  if ![file exists $qsphere] {
    confirmalert "Surface: $qsphere\nnot found  ...qsphere first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $origsurffix] } {
      if {$subprocessredo} {
        set action [okreplace $origsurffix \
  "Fix Topology: Surface: $origsurffix exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $origsurffix \
  "Fix Topology: Surface: $origsurffix exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu FIXTOPOLOGYintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

proc smoothcmdrh { subjectsdir name } {
  smoothcmd $subjectsdir $name rh
}

proc smoothcmdlh { subjectsdir name } {
  smoothcmd $subjectsdir $name lh
}

### CreateSurface step 3 (of 4) command, FixTopology step 3 (of 4) command
proc smoothcmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global surfdir origext orig1ext orig2ext foldedext
  global inflateparms
  global force bindir

  set origsurf $subjectsdir/$name/$surfdir/$hemi.$origext
  set orig1surf $subjectsdir/$name/$surfdir/$hemi.$orig1ext
  set orig2surf $subjectsdir/$name/$surfdir/$hemi.$orig2ext
  set foldedsurf $subjectsdir/$name/$surfdir/$hemi.$foldedext

  set opts ""
  if {$inflateparms(smoothcycles) != "default"} {
    set opts "$opts -n $inflateparms(smoothcycles)"
  }
  set command1 "$bindir/mris_smooth -n 1 \
    [backslashspaces $origsurf] [backslashspaces $orig1surf]"
  set command2 "$bindir/mris_smooth -n 2 \
    [backslashspaces $origsurf] [backslashspaces $orig2surf]"
  set command "$bindir/mris_smooth $opts \
    [backslashspaces $origsurf] [backslashspaces $foldedsurf]"

  if ![file exists $origsurf] {
    confirmalert "Surface: $origsurf\nnot found  ...tessellate first"
    set processkill 1
    return
  }
  if {!$force} {
    if [file exists $foldedsurf] {
      if {$subprocessredo} {
        set action [okreplace $foldedsurf \
          "Smooth Surface: $foldedsurf exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $foldedsurf \
          "Smooth Surface: $foldedsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command1 "sleep 0"; \
                          set command2 "sleep 0"; \
                          set command  "sleep 0" }     ;# use existing
    }
  }
  runacmd "$command1" $processbu SMOOTHWMintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
  runacmd "$command2" $processbu SMOOTHWMintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
  runacmd "$command" $processbu SMOOTHWMintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

proc inflatecmdrh { subjectsdir name } {
  inflatecmd $subjectsdir $name rh
}

proc inflatecmdlh { subjectsdir name } {
  inflatecmd $subjectsdir $name lh
}

### CreateSurface step 4 (of 4) command, FixTopology step 4 (of 4) command
proc inflatecmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global inflateparms
  global surfdir sulcext origext foldedext inflatedext
  global force bindir

  set sulcfile     $subjectsdir/$name/$surfdir/$hemi.$sulcext
  #set foldedsurf  $subjectsdir/$name/$surfdir/$hemi.$origext
  set foldedsurf   $subjectsdir/$name/$surfdir/$hemi.$foldedext
  set inflatedsurf $subjectsdir/$name/$surfdir/$hemi.$inflatedext

  set opts ""
  if {$inflateparms(inflatecycles) != "default"} {
    set opts "$opts -n $inflateparms(inflatecycles)"
  }
  if {$inflateparms(metric2smooth) != "default"} {
    set opts "$opts -dist $inflateparms(metric2smooth)"
  }
  if {$inflateparms(nbrs) != "default"} {
    set opts "$opts -nbrs $inflateparms(nbrs)"
  }
  set command "$bindir/mris_inflate $opts \
    [backslashspaces $foldedsurf] [backslashspaces $inflatedsurf]"

  if ![file exists $foldedsurf] {
    confirmalert "Surface: $foldedsurf\nnot found  ...smooth first"
    set processkill 1
    return
  }
  if {!$force} {
    if [file exists $inflatedsurf] {
      if {$subprocessredo} {
        set action [okreplace $inflatedsurf \
          "Inflate Surface: $inflatedsurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $inflatedsurf \
          "Inflate Surface: $inflatedsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
    # redo: always overwrite sulc
  }
  runacmd "$command" $processbu INFLATEintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Make Final Surface menu command
proc mkfinalsurf { } {
  global env name hemi datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "make final RH surfaces" "make final LH surfaces" }
    set commandlist { mkfinalsurfcmdrh mkfinalsurfcmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "make final RH surfaces" }
    set commandlist { mkfinalsurfcmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "make final LH surfaces" }
    set commandlist { mkfinalsurfcmdlh }
  }
  set wilabel "MAKE FINAL SURFACE"
  set bulabel MakeFinalSurface 
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc mkfinalsurfcmdrh { subjectsdir name } {
  mkfinalsurfcmd $subjectsdir $name rh
}

proc mkfinalsurfcmdlh { subjectsdir name } {
  mkfinalsurfcmd $subjectsdir $name lh
}

### Make Final Surface step 1 (of 1) command
proc mkfinalsurfcmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global finalparms
  global force bindir
  global surfdir curvext origext whiteext graymidext pialext

  set curvfile    $subjectsdir/$name/$surfdir/$hemi.$curvext
  set origsurf    $subjectsdir/$name/$surfdir/$hemi.$origext
  set whitesurf   $subjectsdir/$name/$surfdir/$hemi.$whiteext
  set graymidsurf $subjectsdir/$name/$surfdir/$hemi.$graymidext
  set pialsurf $subjectsdir/$name/$surfdir/$hemi.$pialext
  ### options: -whiteonly, -q (quick white/pial w/o self-intersect)
  #set args "-q"
  set args ""
  if {$finalparms(selfintersect)} { set args "-graymid" }
  set command "$bindir/mris_make_surfaces $args $name $hemi"

  if ![file exists $origsurf] {
    confirmalert "Surface: $origsurf\nnot found  ...tessellate first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $whitesurf] } {
      if {$subprocessredo} {
        set action [okreplace $whitesurf \
          "Make Final Surfaces: $whitesurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $whitesurf \
          "Make Final Surfaces: $whitesurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      # redo implies overwrite curv, graymidsurf, pialsurf
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu FINALSURFACESintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### BackCompatibleCurv3d menu command
proc backcompatcurv3d { } {
  global env name bindir
  global cmdlog medbu surfbu

  if ![okreplace "" "Generate old format volume files (COR) and\
                   \nsurface curvature files (curv,sulc) for\
                   \ncompatibility with UCSD Retinotopy FreeSurfer\
                   \n(won't affect current freesurfer)\
                 \n\n#######################################\
                   \n  N.B.: No longer needed since csurf/FreeSurfer0.8\
                   \n  now reads current MGH volume and curvature!\
                   \n#######################################" \
       "Make Back Compatible"] { return }

  foreach hemi { rh lh } {
    foreach type { curv sulc } {
    set fullcurv $env(SUBJECTS_DIR)/$name/surf/$hemi.$type
      if ![file exists $fullcurv] {
        confirmalert "BackCompatCurv: $fullcurv\nnot found"
        return 
      }
      if ![canwriteormakefile $fullcurv] {
        confirmalert "BackCompatCurv: $fullcurv not writable"
        return 
      }
    }
  }
  cdlog $env(SUBJECTS_DIR)/$name/surf
  foreach hemi { rh lh } {
    foreach type { curv sulc } {
      set fullcurv $env(SUBJECTS_DIR)/$name/surf/$hemi.$type
      if { [exec $bindir/calcvert -3bytemagic $fullcurv] == 16777215} {
        cplog $hemi.$type $hemi.${type}FLOAT
        set command "$bindir/calcvert \
          -convert -newcurvin -oldcurvout $hemi.$type $hemi.${type}OLD"
        runacmd "$command" $surfbu "SURFACE  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        cplog $hemi.${type}OLD $hemi.$type
      } else {
         confirmalert "BackCompatCurv: $fullcurv\nalready old curv format"
         break  ;# drop through to check 3d
      }
    }
  }
  cdsubjectscripts

  foreach brikpref { orig T1 brain wm filled } {
    set fullmghbrik $env(SUBJECTS_DIR)/$name/mri/$brikpref.mgz
    if ![file exists $fullmghbrik] {
      confirmalert "BackCompat3d: new format\n$fullmghbrik\nnot found"
      return
    }
  }
  foreach dir { orig T1 brain wm filled } {
    set fulldir $env(SUBJECTS_DIR)/$name/mri/$dir
    if [file exists $fulldir/COR-.info] {
      confirmalert "BackCompat3d: $fulldir/COR-.info exists (already old COR)"
      return
    }
    if [file exists $fulldir] {
      confirmalert "BackCompat3d: $fulldir exists but COR.info missing\n\n\"
                    move $fulldir aside and re-run command"
      return
    }
    if { ![canwriteormakefile $fulldir] && $dir != "orig" } {
      confirmalert "BackCompat3d: cannot create $fulldir"
      return
    }
  }
  cdlog $env(SUBJECTS_DIR)/$name/mri
  foreach dir { orig T1 brain wm filled } {
    if ![file exists $dir] { mkdirlog $dir }  ;# orig may exist
    set command "$bindir/mri_convert $dir.mgz $dir"
    runacmd "$command" $medbu "VOLUME  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
  }
  cdsubjectscripts
  confirmalert "BackCompatCurv3d:\n\n\
                   curv, sulc:  convert to old format (new saved aside)\n\
                   3d volume:  generate COR files (new untouched)"
}

### UndoBackCompatibleCurv menu command
proc undobackcompatcurv { } {
  global env name bindir

  if ![okreplace "" " Restore new format surf curv files (curv,sulc)" \
       "Undo Old Curv Compatible"] { return }

  foreach hemi { rh lh } {
    foreach type { curv sulc } {
    set fullcurv $env(SUBJECTS_DIR)/$name/surf/$hemi.${type}FLOAT
      if ![file exists $fullcurv] {
        confirmalert "UndoBackCompatCurv: new format $fullcurv\nnot found"
        return 
      }
      if ![canwriteormakefile $fullcurv] {
        confirmalert "UndoBackCompatCurv: new format $fullcurv\nnot writable"
        return 
      }
    }
  }
  cdlog $env(SUBJECTS_DIR)/$name/surf
  foreach hemi { rh lh } {
    foreach type { curv sulc } {
      set fullcurv $env(SUBJECTS_DIR)/$name/surf/$hemi.$type
      if { [exec $bindir/calcvert -3bytemagic $fullcurv] != 16777215} {
        cplog $hemi.${type}FLOAT $hemi.$type
      } else {
         confirmalert "UndoBackCompatCurv: $fullcurv\nalready new curv format"
         break  ;# drop through to avoid 4 error messages
      }
    }
  }
  cdsubjectscripts
  confirmalert "UndoBackCompatCurv:\n\n\
                   curv, sulc:  restore new format"
}

### ForwardCompat3d menu command
proc forwardcompat3d { } {
  global env name bindir
  global cmdlog medbu

  if ![okreplace "" \
              " (1) Make *.mgz files for curr freesurfer compatibility\n\
                (2) rename CORdirs: curr freesurfer bug workaround" \
    "Make Forward Compatible"] { return }

  set checkoverwrite 1
  foreach dir { orig T1 brain wm filled } {
    set fulldir $env(SUBJECTS_DIR)/$name/mri/$dir
    if ![file exists $fulldir] {
      confirmalert " ForwardCompat3d: old COR format dir:\n\n\
                     $fulldir\n\n\
                     not found"
      return
    }
    if [file exists ${fulldir}COR] {
      confirmalert " ForwardCompat3d: old COR format dir:\n\n\
                     ${fulldir}COR\n\n\
                     already renamed"
      return
    }
    if { ![canwriteormakefile ${fulldir}.mgz] } {
      confirmalert "ForwardCompat3d: no permission to write ${fulldir}.mgz"
      return
    }
    if { [file exists ${fulldir}.mgz] } {
      if {$checkoverwrite} {
        if ![okreplace ${fulldir}.mgz \
            " ForwardCompat3d: new format .mgz file:\n\n\
              ${fulldir}.mgz\n\n\
              already exists\n\n\
              OK to overwrite \{orig/T1/brain/wm/filled\}.mgz?" \
            "Overwrite"] {
          confirmalert "ForwardCompat3d: *.mgz not altered"
          return
        } else { set checkoverwrite 0 }
      }
    }
  }
  cdlog $env(SUBJECTS_DIR)/$name/mri
  foreach dir { orig T1 brain wm filled } {
    set command "$bindir/mri_convert $dir $dir.mgz"
    runacmd "$command" $medbu "VOLUME  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    mvlog $dir ${dir}COR
  }
  cdsubjectscripts
  confirmalert " ForwardCompat3d:\n\n\
                 (1) converted CORdirs (orig,T1,brain,wm,filled)->mgz\n\
                 (2) added \"COR\" suffix (avoid curr freesurfer bug)"
}

### UndoForwardCompat3d menu command
proc undoforwardcompat3d { } {
  global env name

  if ![okreplace "" " Put moved-aside COR dirs back (won't touch *.mgz)" \
       "Un-rename COR dirs"] { return }

  foreach dir { orig T1 brain wm filled } {
    set fulldir $env(SUBJECTS_DIR)/$name/mri/$dir
    if [file exists $fulldir] {
      confirmalert " UndoForwardCompat3d:  COR dir:\n\n\
                     $fulldir\n\n\
                     already moved back"
      return
    }
    if ![file exists ${fulldir}COR] {
      confirmalert "UndoForwardCompat3d:  COR dir to move back\n\n\
                    ${fulldir}COR\n\n\
                    not found"
      return
    }
    if { ![canwriteormakefile $fulldir] } {
      confirmalert "UndoForwardCompat3d: no permission to modify $fulldir"
      return
    }
  }

  cdlog $env(SUBJECTS_DIR)/$name/mri
  foreach dir { orig T1 brain wm filled } { mvlog ${dir}COR $dir }
  cdsubjectscripts
  confirmalert " UndoForwardCompat3d: moved-aside COR dirs:\n\n\
                 origCOR, T1COR, brainCOR, wmCOR, filledCOR\n\n\
                 moved back to:\n\n\
                 orig, T1, brain, wm, filled (*.mgz untouched)"
}

### FixFinal (all-in-one-button) menu command
proc fixfinal { } {
  global env name hemi force datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  set saveforce $force
  set force 1
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { \
      "quick sphere RH surface" "quick sphere LH surface"\
      "fix topology RH surface" "fix topology LH surface"\
      "resmooth RH white matter" "resmooth LH white matter"\
      "reinflate RH surface" "reinflate LH surface"\
      "make final RH surfaces" "make final LH surfaces" }
    set commandlist { \
       qspherecmdrh qspherecmdlh fixtopologycmdrh fixtopologycmdlh \
       smoothcmdrh smoothcmdlh inflatecmdrh inflatecmdlh \
       mkfinalsurfcmdrh mkfinalsurfcmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { \
      "quick sphere RH surface" "fix topology RH surface"\
      "resmooth RH white matter" "reinflate RH surface"\
      "make final RH surfaces" }
    set commandlist { \
       qspherecmdrh fixtopologycmdrh smoothcmdrh inflatecmdrh \
       mkfinalsurfcmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { \
      "quick sphere LH surface" "fix topology LH surface"\
      "resmooth LH white matter" "reinflate LH surface"\
      "make final LH surfaces" }
    set commandlist { \
       qspherecmdlh fixtopologycmdlh smoothcmdlh inflatecmdlh \
       mkfinalsurfcmdlh }
  }
  set wilabel "FIX, FINAL"
  set bulabel FixFinal
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
  set force $saveforce
}

### CreateFixFinal (all-in-one-button) menu command
proc createfixfinal { } {
  global env name hemi force talairachflag datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  set saveforce $force
  set force 1
  set cmdlablist { \
    "fill white matter" "tessellate white matter"\
    "smooth RH white matter" "smooth LH white matter"\
    "inflate RH surface" "inflate LH surface"\
    "quick sphere RH surface" "quick sphere LH surface"\
    "fix topology RH surface" "fix topology LH surface"\
    "resmooth RH white matter" "resmooth LH white matter"\
    "reinflate RH surface" "reinflate LH surface"\
    "make final RH surfaces" "make final LH surfaces" }
  set commandlist { \
     wmfillcmd tessellcmd smoothcmdrh smoothcmdlh inflatecmdrh inflatecmdlh \
     qspherecmdrh qspherecmdlh fixtopologycmdrh fixtopologycmdlh \
     smoothcmdrh smoothcmdlh inflatecmdrh inflatecmdlh \
     mkfinalsurfcmdrh mkfinalsurfcmdlh }
  set wilabel "CREATE, FIX, FINAL"
  set bulabel CreateFixFinal
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
  set force $saveforce
}

### ProcessCreateFixFinal (all-in-one-button) menu command
proc processcreatefixfinal { } {
  global env name force talairachflag datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  set saveforce $force
  set force 1
  set cmdlablist { \
    "normalize intensities" "compute Talairach"\
    "strip skull" "segment white matter"\
    "fill white matter" "tessellate white matter"\
    "smooth RH white matter" "smooth LH white matter"\
    "inflate RH surface" "inflate LH surface"\
    "quick sphere RH surface" "quick sphere LH surface"\
    "fix topology RH surface" "fix topology LH surface"\
    "resmooth RH white matter" "resmooth LH white matter"\
    "reinflate RH surface" "reinflate LH surface"\
    "make final RH surfaces" "make final LH surfaces" }
  set commandlist { normalizecmd talairachcmd stripskullcmd wmfiltercmd \
     wmfillcmd tessellcmd smoothcmdrh smoothcmdlh inflatecmdrh inflatecmdlh \
     qspherecmdrh qspherecmdlh fixtopologycmdrh fixtopologycmdlh \
     smoothcmdrh smoothcmdlh inflatecmdrh inflatecmdlh \
     mkfinalsurfcmdrh mkfinalsurfcmdlh }
  if {!$talairachflag} {
    set cmdlablist [ldelete $cmdlablist "compute Talairach"]
    set commandlist [ldelete $commandlist talairachcmd]
  }
  set wilabel "PROCESS, CREATE, FIX, FINAL"
  set bulabel ProcessCreateFixFinal
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
  set force $saveforce
}

### ProcessCreate (all-in-one-button) menu command
proc processcreate { } {
  global env name force talairachflag datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  set saveforce $force
  set force 1
  set cmdlablist { \
    "normalize intensities" "compute Talairach"\
    "strip skull" "segment white matter"\
    "fill white matter" "tessellate white matter"\
    "smooth RH white matter" "smooth LH white matter"\
    "inflate RH surface" "inflate LH surface" }
  set commandlist { normalizecmd talairachcmd stripskullcmd wmfiltercmd \
     wmfillcmd tessellcmd smoothcmdrh smoothcmdlh inflatecmdrh inflatecmdlh }
  if {!$talairachflag} {
    set cmdlablist [ldelete $cmdlablist "compute Talairach"]
    set commandlist [ldelete $commandlist talairachcmd]
  }
  set wilabel "PROCESS, CREATE"
  set bulabel ProcessCreate
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
  set force $saveforce
}

### Flatten Surface menu command
proc flatten { } {
  global env name hemi datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "flatten RH surface" "flatten LH surface" }
    set commandlist { flattencmdrh flattencmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "flatten RH surface" }
    set commandlist { flattencmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "flatten LH surface" }
    set commandlist { flattencmdlh }
  }
  set wilabel "FLATTEN SURFACE"
  set bulabel FlattenSurface
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc flattencmdrh { subjectsdir name } {
  flattencmd $subjectsdir $name rh
}

proc flattencmdlh { subjectsdir name } {
  flattencmd $subjectsdir $name lh
}

### Flatten Surface step 1 (of 1) command
proc flattencmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global flattenparms
  global force bindir
  global surfdir begin3dext beginflatext endflatext patchext fullpatch

  set pos $subjectsdir/$name/scripts/position.tcl
  if ![file exists $pos] { mkpositiontcl }

  ## inpatch (allow reflatten already flat)
  set inpatch $subjectsdir/$name/$surfdir/$hemi.$patchext
  if ![file exists $inpatch] {
    confirmalert "Flatten Surface: inpatch not found:\n\n    $inpatch"
    set processkill 1
    return
  }
  if {!$force} {
    if [string match *.$endflatext $inpatch] {
      if ![okreplace $inpatch \
          "Flatten Surface: OK to re-flatten already flat?\n\n$inpatch" \
          "Re-Flatten"] {
        set processkill 1
        return
      } else {
        set subprocessredo 1  ;# don't offer "use existing" b/c decided here
      }
    }
  }
  wm title .progress "$name (inp: [file tail $inpatch])"
  set patchroot [file rootname $patchext]
  set outpatch $subjectsdir/$name/$surfdir/$hemi.$patchroot.$endflatext

  ### command
  set opts ""   ;# 6/04: fix arg order
  if {$flattenparms(write_per_iters) != "default"} {
    set opts "$opts -w $flattenparms(write_per_iters)"
  }
  if {$patchroot == $fullpatch} {
    if {$flattenparms(vertices_per_full) != "default" &&
        $flattenparms(sampledist_mm_full) != "default"} {
      set opts "$opts -distances \
         $flattenparms(sampledist_mm_full) $flattenparms(vertices_per_full)"
    }
  } else {
    if {$flattenparms(vertices_per_patch) != "default" &&
        $flattenparms(sampledist_mm_patch) != "default"} {
      set opts "$opts -distances \
         $flattenparms(sampledist_mm_patch) $flattenparms(vertices_per_patch)"
    }
  }
  set command "$bindir/mris_flatten $opts \
    [backslashspaces $inpatch] [backslashspaces $outpatch]"

  ### outpatch
  if {!$force} {
    if { [file exists $outpatch] } {
      if {$subprocessredo} {
        set action [okreplace $outpatch \
          "Flatten Surface: $outpatch exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $outpatch \
          "Flatten Surface: $outpatch exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu FLATTENintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### old/removed Register Surface menu command
proc spherereg { } {
  global env name hemi datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "sphere RH surface" "sphere LH surface"\
             "register RH to target" "register LH to target" }
    set commandlist { spherecmdrh spherecmdlh sphereregcmdrh sphereregcmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "sphere RH surface" "register RH to target" }
    set commandlist { spherecmdrh sphereregcmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "sphere LH surface" "register LH to target" }
    set commandlist { spherecmdlh sphereregcmdlh }
  }
  set wilabel "REGISTER SURFACE"
  set bulabel RegisterSurface
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc spherecmdrh { subjectsdir name } {
  spherecmd $subjectsdir $name rh
}

proc spherecmdlh { subjectsdir name } {
  spherecmd $subjectsdir $name lh
}

### Register Surface step 1 (of 2) command
proc spherecmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global sphereparms
  global force bindir
  global surfdir inflatedext sphereext

  set inflatedsurf $subjectsdir/$name/$surfdir/$hemi.$inflatedext
  set spheresurf $subjectsdir/$name/$surfdir/$hemi.$sphereext

  set opts ""
  if {$sphereparms(write_per_iters) != "default"} {
    set opts "$opts -w $sphereparms(write_per_iters)"
  }
  if {$sphereparms(vertices_per) != "default" &&
      $sphereparms(sampledist_mm) != "default"} {
    set opts "$opts -distances \
      $sphereparms(vertices_per) $sphereparms(sampledist_mm)"
  }
  set command "$bindir/mris_sphere $opts \
    [backslashspaces $inflatedsurf] [backslashspaces $spheresurf]"

  if ![file exists $inflatedsurf] {
    confirmalert "Sphere Surface: $inflatedsurf\nnot found  ...inflate first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $spheresurf] } {
      if {$subprocessredo} {
        set action [okreplace $spheresurf \
          "Sphere Surface: $spheresurf exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $spheresurf \
          "Sphere Surface: $spheresurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu SPHEREintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

proc sphereregcmdrh { subjectsdir name } {
  sphereregcmd $subjectsdir $name rh
}

proc sphereregcmdlh { subjectsdir name } {
  sphereregcmd $subjectsdir $name lh
}

### Register Surface step 2 (of 2) command
proc sphereregcmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global sphereparms
  global surfdir avgdir sphereext regext
  global force bindir
  global env

  set spheresurf $subjectsdir/$name/$surfdir/$hemi.$sphereext
  ### targs: $hemi.average.tif, $hemi.average.curvature.filled.buckner40.tif
  # N.B.: FreeSurfer0.8/$avgdir=average no longer in csurf, menu for this rm'd
  set targsurf $env(CSURF_DIR)/$avgdir/$hemi.$sphereparms(morphtarg).tif
  set sphereregsurf $subjectsdir/$name/$surfdir/$hemi.$sphereext.$regext
  set opts ""
  if {$sphereparms(write_per_iters) != "default"} {
    set opts "$opts -w $sphereparms(write_per_iters)"
  }
  if {$sphereparms(tol) != "default"} {
    set opts "$opts -tol $sphereparms(tol)"
  }
  if {$sphereparms(nav) != "default"} {
    set opts "$opts -nav $sphereparms(nav)"
  }
  if {$sphereparms(sulcfirst) != "default"} {
    set opts "$opts -curv"   ;# curv touch-up after main sulc
  }
  if {$sphereparms(parea) != "default"} {
    set opts "$opts -parea $sphereparms(parea)"
  }
  if {$sphereparms(corr) != "default"} {
    set opts "$opts -corr $sphereparms(corr)"
  }
  if {$sphereparms(dist) != "default"} {
    set opts "$opts -dist $sphereparms(dist)"
  }
  #mris_register [-curv] -corr <def: 1.0> -parea <def: 0.2> -dist <def: 0.1> ...
  # -parea .2/.5/.9 => stiffer, -dist .1/.2/.4/.6/.8/1.0/1.2 => stiffer
  set command "$bindir/mris_register $opts [backslashspaces $spheresurf] \
    [backslashspaces $targsurf] [backslashspaces $sphereregsurf]"

  if ![file exists $spheresurf] {
    confirmalert "Surface: $spheresurf\nnot found  ...sphere first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $sphereregsurf] } {
      if {$subprocessredo} {
        set action [okreplace $sphereregsurf \
  "Sphere-Register Surface: $sphereregsurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $sphereregsurf \
  "Sphere-Register Surface: $sphereregsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu SPHEREREGintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### start choosemghscan from parent dir of last-selected mgh scan
proc choosemghscan { index rawfileentry } {
  global mghinprawscanfiles lastmghscandir

  if {$lastmghscandir != ""} { set mghinprawscanfiles($index) $lastmghscandir }
  choosefile mghinprawscanfiles($index)
  tkwait variable mghinprawscanfiles($index) ;# after cancel, lastmghscandir=./
  set lastmghscandir [file dirname $mghinprawscanfiles($index)]/
  $rawfileentry xview moveto 1   ;# show tail of long path
}

### ADD SCAN, DEL LAST button cmds (Recon-all panel)
proc reconallwline { action enswin } {
  global mghinprawscanfiles
  global bgcol selbgcol entbgcol ffontb hfont
 
  set scandirlinelist [lsort [info commands $enswin.li??]]
  if {$action == "add"} {
    set num [format "%02d" [llength $scandirlinelist]] ;# count: ind already +1
    frame $enswin.li$num -bg $bgcol
    if [info exists mghinprawscanfiles($num)]  {unset mghinprawscanfiles($num)}
    entry $enswin.li$num.e0 -textvariable mghinprawscanfiles($num) -width 55 \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
      -selectforeground black -font $hfont
    set mghinprawscanfiles($num) \
      "-- type in full path NIFTI file, or use FIND --"   ;# def 'help'
    button $enswin.li$num.bu -text FIND -font $ffontb -pady 0 -padx 5 \
     -highlightbackground $bgcol -command "choosemghscan $num $enswin.li$num.e0"
    pack $enswin.li$num -side top
    pack $enswin.li$num.e0 $enswin.li$num.bu -side left
  }
  if {$action == "delete" && "$scandirlinelist" != ""} {
    destroy [lindex $scandirlinelist end]  ;# last widget line
    set num [format "%02d" [expr [llength $scandirlinelist] - 1]] ;#0-based ind
    unset mghinprawscanfiles($num)
  }
}

### Recon-all menu item (parallel to setupscans, not add*scan procs)
proc setupreconall { } {
  global name env hemi session logflag
  global reconallbu subjectscombo
  global pfont ffont ffontb sfont tfont
  global bgcol selcol selbgcol hilcol hilbgcol actbgcol entbgcol
  global reconallparms xcmd

  if [winfo exists .reconalldialog] {
    raise .reconalldialog
    confirmalert "Finish current recon-all first"
    return
  }
  set f [toplevel .reconalldialog -bg $bgcol]
  ::tk::classic::restore  ;# newpkgtix
  configtixbookcbxent $f
  positionpopup $f
  wm protocol $f WM_DELETE_WINDOW killboxOK
  wm title $f "Run MGH recon-all"

  ### catch spaces in paths, continue anyway
  if { [string match "* *" $env(FSURF_DIR)] || 
       [string match "* *" $env(SUBJECTS_DIR)] } {
    confirmalert "Recon-all: space(s) found in directory paths:\
              \n\n    FSURF_DIR=$env(FSURF_DIR)\
                \n    SUBJECTS_DIR=$env(SUBJECTS_DIR)\
              \n\nMGH FreeSurfer 5.3 startup scripts will fail\
              \n\nContinuing anyway..."
  }

  ### main frames
  # action
  set a [frame $f.ac -bg $bgcol -bd 10 -bg $bgcol]
  pack $a -side top
  ### leave scrolled window for now (permanent window var below is $m)
  # main (inside scrolled window: -shrink y breaks, newpkgtix: -scrollbar auto)
  set scr [tixScrolledWindow $f.sw -height 370 -scrollbar auto] ;# 15 lines
  $scr.f1 config -bd 2 -relief sunken ;# -highlightbackground $bgcol ;#thkbord
  $scr subwidget vsb config -highlightbackground $bgcol
  pack $scr -side top -padx 5 -expand yes -fill y ;# for resizable y, min y
  set scrw [$scr subwidget window]
  $scrw config -bg $bgcol
  $scrw config -bg $bgcol
  set m [frame $scrw.f1 -bd 0 -bg $bgcol]
  pack $m -side top -fill both
  # response
  set r [frame $f.re -bd 10 -bg $bgcol]
  pack $r -side top

  ### top action frame
  frame $a.se -bd 2 -relief groove
  # corner label
  label $a.se.t0 -text "run MGH recon-all script" \
     -font $ffontb -pady 7 -padx 20
  pack $a.se -side left -padx 60
  pack $a.se.t0 -side left
  # action buttons
  frame $a.sp -width 10 -bg $bgcol
  pack $a.sp -side left
  button $a.bu1 -text "RECON-ALL" -padx 5 -pady 5 -font $ffontb \
       -command "reconallcmd" -highlightbackground $bgcol
  set reconallbu $a.bu1
  pack $a.bu1 -padx 3 -side left

  ### main panel frame
  ##TODO: RECON-PICKSTEPS (all the reconall flags)
  ##TODO: csurf.dat? date last mod in entry, save in config when panel closes
  # labels
  label $m.la1 -bg $bgcol -font $tfont -bg $bgcol -text \
" (1) Type name of new (or wm-edited) subject and hit <Return>"
  label $m.la1b -bg $bgcol -font $sfont -bg $bgcol -text \
"            (new subject can't overlap name in SUBJECTS_DIR -- check dropdown)"
  label $m.la2 -bg $bgcol -font $tfont -bg $bgcol -text \
" (2a) If New: Add/Delete lines with ADD SCAN (DEL LAST), FIND locates scan(s)"
  label $m.la2b -bg $bgcol -font $sfont -bg $bgcol -text \
"            (FIND panel: double-click selected left-column folder to see its sub-folders)"
  label $m.la3 -bg $bgcol -font $tfont -bg $bgcol -text \
" (2b) If Redo: maybe set non-default recon-all params/flags (else no change)"
  label $m.la4 -bg $bgcol -font $tfont -bg $bgcol -text \
" (3) Click RECON-ALL (monitor progress: Preferences -> View Logs)"
  pack $m.la1 $m.la1b $m.la2 $m.la2b $m.la3 $m.la4 \
    -side top -padx 10 -pady 0 -anchor w
  # main panel hemi/subject subframe
  frame $m.bus -bd 3 -bg $bgcol
  pack $m.bus -side top
  # hemi
  tixSelect $m.bus.hem -allowzero false -radio true -label " hemi:" \
    -orientation horizontal -options "label.width 6"
  $m.bus.hem subwidget label config -font $ffont -bg $bgcol ;#didn't work above
  $m.bus.hem add rh \
    -text RIGHT -font $sfont -width 3 -bg $bgcol -padx 7 -pady 2 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $m.bus.hem add lh \
    -text LEFT -font $sfont -width 3 -bg $bgcol -padx 7 -pady 2 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $m.bus.hem add both \
    -text BOTH -font $sfont -width 3 -bg $bgcol -padx 7 -pady 2 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $m.bus.hem config -variable hemi
  pack $m.bus.hem -side left -padx 15
  # new recon-all subject (existing in combo box)
  tixComboBox $m.bus.cbx -label "new/redo subject:" -dropdown true \
    -command "cbx:select_reconsubject $m" -editable true \
    -variable reconallparms(name) -listwidth 208 \
    -options "label.width 15 entry.width 12 listbox.height 30" ;#14char:was sm
  $m.bus.cbx subwidget label config -font $ffont -bg $bgcol ;#didn't work above
  set subjnamelist [$subjectscombo subwidget listbox get 0 end]
  foreach subjname [lsort $subjnamelist] { $m.bus.cbx insert end $subjname }
  pack $m.bus.cbx -side left -padx 15 -pady 5
  # parameters
  frame $m.par -bg $bgcol  ;# -bd 10
  pack $m.par -side top -padx 20
  # default all reconallparms here (since not yet in setdefaultarrays)
  set hemi both
  set reconallparms(skipstep1flag) 0  ;# requires hacked recon-all
  set reconallparms(noasegflag) 0
  set reconallparms(startwmflag) 0
  set reconallparms(notalcheckflag) 0
  set reconallparms(otheroptions) ""
  checkbutton $m.par.ck0 \
    -text "skip auto failure detection of Talairach align (-notal-check)" \
    -variable reconallparms(notalcheckflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $m.par.ck1 \
    -text "skip automatic brainstem segment (-noaseg)" \
    -variable reconallparms(noasegflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $m.par.ck3 \
    -text "re-run starting with edited orig.mgz (marty: -all-skipstep1)" \
    -variable reconallparms(skipstep1flag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $m.par.ck2 \
    -text "re-run starting with edited wm (-autorecon2-wm, -autorecon3)" \
    -variable reconallparms(startwmflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  tixLabelEntry $m.par.a -label "recon-all options: " -labelside left
  $m.par.a subwidget entry config -textvariable reconallparms(otheroptions) \
    -width 45
  $m.par.a subwidget label config -width 15 -font $ffont
  frame $m.par.sp -height 10 -bg $bgcol
  pack $m.par.ck0 $m.par.ck1 $m.par.ck3 $m.par.ck2 $m.par.a $m.par.sp \
    -side top -anchor w
  # ADD/DEL buttons
  frame $m.bus2 -bd 3 -bg $bgcol
  pack $m.bus2 -side top
  button $m.bus2.bu1 -text "ADD SCAN" -font $ffontb -pady 1 -padx 2 \
    -command "reconallwline add $m.ens" -highlightbackground $bgcol
  set addnewsessbu $m.bus2.bu1
  button $m.bus2.bu2 -text "DEL LAST" -font $ffontb -pady 1 -padx 2 \
    -command "reconallwline delete $m.ens" -highlightbackground $bgcol
  pack $m.bus2.bu1 $m.bus2.bu2 -side left -padx 0
  # labels
  frame $m.tis -bd 3 -bg $bgcol
  pack $m.tis -side top
  label $m.tis.la1 -bg $bgcol -font $tfont \
    -text "ADD one or more NIFTI or AFNI BRIK scans to reconstruct (same subj)"
  pack $m.tis.la1 -side left -padx 8
  # empty frame for configurable scan-to-avg widget lines
  frame $m.ens -bg $bgcol  ;# -bd 10
  pack $m.ens -side top
  # space
  frame $m.bot -height 12 -bg $bgcol
  pack $m.bot -side left

  ### bottom response buttons frame
  button $r.close -text "Close" -font $ffont -width 10 -pady 5 \
    -highlightbackground $bgcol -command "closereconall $f"
  pack $r.close -side right -padx 185

  $subjectscombo config -state disabled
  tkwait visibility $f
  $m.bus2.bu1 invoke  ;# start with at least one scan

  wm protocol . WM_DELETE_WINDOW killboxOK  ;# disarm csurf win killbox
  if { [exec uname] != "Linux" } { raise $f }
  wm resizable $f 0 1
  set geom [wm geometry $f]  ;# 792x581+53+79
  set minx [string range $geom 0 [expr [string first x $geom] - 1]]
  set miny [string range $geom [expr [string first x $geom] + 1] \
                               [expr [string first + $geom] - 1]]
  wm minsize $f $minx $miny  ;# because tixScrolledWindow won't shrink
  focus $f

  # logs avail from this toplevel
  bind $f <$xcmd-l> { \
    if {$logflag} {set logflag 0; hidelogs} else {set logflag 1; showlogs} }
}

### Close Recon-all panel only if purple button finished
proc closereconall { w } {
  global reconallbu selbgcol subjectscombo

  set reconallrunning 0
  ## strings here assume 2 spaces appended to buttonlabel arg to runacmd
  # 2 label chars trimmed: runacmd truncs 4 for "Quit" minus 2 spaces added2arg
  if { [info exists reconallbu] && [info commands $reconallbu] != "" } {
    if { [$reconallbu cget -text] == "QuitRECON-A"} { set reconallrunning 1 }
  }
  if {$reconallrunning} {
    confirmalert "Quit RECON-ALL first"
  } else {
    destroy $w
    foreach cbx "$subjectscombo" {
      $cbx config -state normal
      $cbx subwidget entry config -selectbackground $selbgcol   ;# tix8.4+
      $cbx subwidget listbox config -selectbackground $selbgcol ;# tix8.4+
    }
    wm protocol . WM_DELETE_WINDOW testclose  ;# re-arm csurf window killbox
    if [info exists reconallbu]  { unset reconallbu }
  }
}

### Run MGH recon-all Panel: select subject combo
proc cbx:select_reconsubject { mpan s } {
  global env subjectscombo reconallparms 

  # always clear/reload so Preferences -> Set Subject Dir updates w/panel open
  $mpan.bus.cbx subwidget listbox delete 0 end
  set subjnamelist [$subjectscombo subwidget listbox get 0 end]
  foreach subjname [lsort $subjnamelist] { $mpan.bus.cbx insert end $subjname }
  if { $s == "" } {
    confirmalert " No subject:\n\n\
                   (1) enter new subject name (not in dropdown)\n\
                   followed by <Return>\n\n    or\n\n\
                   (2) select existing subject (to redo recon)\n\n\
                   and click RECON-ALL"
    return
  }
  set found 0
  foreach subj [$subjectscombo subwidget listbox get 0 end] {
    if { $s == "$subj" } { set found 1 }
  }
  if { $found } {
    if { $reconallparms(startwmflag) || $reconallparms(skipstep1flag) } {
      confirmalert "Ready to re-run reconstruction for\
                  \nsubject:\n\n     $s\
                \n\nin SUBJECTS_DIR:\n\n     $env(SUBJECTS_DIR)"
    } else {
      confirmalert "To re-run reconstruction for\
                  \nexisting subject:\n\n     $s\
                \n\n(1) click \"re-run starting with edited orig\"\
                \n\n      or\
                \n\n(2) click \"re-run starting with edited wm\"\
                \n\n      or\
                \n\n(3) to start over, rm -rf $env(SUBJECTS_DIR)/$s\
                \n\nand try again"
    }
  } else {  ;# not found
    if { $reconallparms(startwmflag) || $reconallparms(skipstep1flag) } {
      confirmalert "Can't re-run reconstruction for:\n\n    $s\
                \n\nbecause subject doesn't exist yet\
                \n\nunclick \"re-run starting with edited wm\"\
                  \nand try again"
    } else {
      confirmalert "Ready to create new subject:\n\n     $s\
                \n\nin SUBJECTS_DIR:\n\n     $env(SUBJECTS_DIR)"
    }
  }
}

### RECON-ALL button command
proc reconallcmd { } {
  global env name hemi cmdlog mghbindir noarchdir ftmpcsh purplekill
  global reconallbu mghinprawscanfiles reconallparms afnibindir
  global bintcsh_is_installed

  ### check for tcsh
  if {!$bintcsh_is_installed} {
    confirmalert "Recon-all:  /bin/tcsh is not installed\
              \n\n  => MGH recon-all won't work <=\
              \n\nInstall tcsh (e.g., sudo apt-get install tcsh)\
                \nand try again"
    return
  }

  ### check for .license *or* license.txt file
  if { ![file exists $env(FSURF_DIR)/.license] && 
       ![file exists $env(FSURF_DIR)/license.txt] } {
    confirmalert "Recon-all: MGH license file not found\
              \n\nObtain license, or copy:\
              \n\n    $env(CSURF_DIR)/.license\
                \n            *or*\
                \n    $env(CSURF_DIR)/license.txt  (fs6.0+)\
              \n\nto:\
              \n\n    $env(FSURF_DIR)"
    return
  }

  ### catch "#" in input file path (before create subject dir)
  foreach ent [lsort [array names mghinprawscanfiles]] {
    set num [string range $ent 0 1]
    if { [string first "#" $mghinprawscanfiles($num)] != -1 } {
      confirmalert "Recon-all: \"#\" found in input file path:\
                \n\n    $mghinprawscanfiles($num)\
                \n\nwhich will cause shell script to fail.\
                \n\nMove input file to location without a \"#\"\
                 \nin path, and try again"
      return
    }
  }

  ### conservative (in case it breaks something)
  set spacesOK ""
  if [string match "* *" $env(SUBJECTS_DIR)] {
    putlog "reconallcmd: ### env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  ### inputs
  if { $reconallparms(name) == "" }  {
    confirmalert "Recon-all: type new subject name and hit <Return>"
    return
  }
  set subjectexists 0
  if [file exists $env(SUBJECTS_DIR)/$reconallparms(name)] {
    set subjectexists 1
  }
  if { $subjectexists } {
    # first check for empty
    if { ![file exists $env(SUBJECTS_DIR)/$reconallparms(name)/scripts] &&
         ![file exists $env(SUBJECTS_DIR)/$reconallparms(name)/label] &&
         ![file exists $env(SUBJECTS_DIR)/$reconallparms(name)/mri] &&
         ![file exists $env(SUBJECTS_DIR)/$reconallparms(name)/surf] } {
      confirmalert "Subject dir:\n\n    $reconallparms(name)\
                \n\nexists, but contain no standard\
                \nsubdirs (scripts, label, mri, surf)\
                \n\nTo create new subject with this name,\
                  \nmanually delete the empty subject
                  \ndirectory nand try again"
      return
    }
    # block unless wm or edited orig.mgz
    if { !$reconallparms(startwmflag) &&  !$reconallparms(skipstep1flag) } {
      confirmalert "To re-run recon for $reconallparms(name), tick:\
                \n\n    \"re-run starting with edited wm\"\
                  \n                    or\
                  \n    \"re-run starting with edited orig.mgz\"\
                \n\nand try again"
      return
    }
    # confirm overwrite
    if ![okreplace $reconallparms(name) \
        "RE-RUN recon for existing subject $reconallparms(name)?" \
        "RE-RUN Recon"] {
      confirmalert "Recon-all: subject $reconallparms(name) not altered"
      return
    }
  } else {  ;# new subject: check inputs, confirm create
    foreach ent [lsort [array names mghinprawscanfiles]] {
      set num [string range $ent 0 1]
      set ifile $mghinprawscanfiles($num)
      if ![file exists $ifile] {
        confirmalert "Recon-all: missing input file:\n\n  $ifile"
        return
      }
    }
    set cnt 0
    foreach ent [lsort [array names mghinprawscanfiles]] { incr cnt }
    if { $cnt < 1 } {
      confirmalert "Recon-all: no input files: use ADD SCAN, FIND"
      return
    }
    if ![okreplace $reconallparms(name) \
        "Create subject\n\n    $reconallparms(name)\n\n\
         in SUBJECTS_DIR\n\n    $env(SUBJECTS_DIR)?" "Create"] {
      confirmalert "Recon-all: subject $reconallparms(name) not created"
      return
    }
  }

  ### offer auto BRIK->NIFTI after OK Create
  if { !$subjectexists } {
    foreach ent [lsort [array names mghinprawscanfiles]] {
      set num [string range $ent 0 1]
      set ifile $mghinprawscanfiles($num)
      if [string match *+orig.BRIK $ifile] {  ;# try auto-convert BRIK to NIFTI
        set fullniftiout [string trimright $ifile "+orig.BRIK"].nii
        if [file exists $fullniftiout] {
          confirmalert "NIFTI file:\n\n    $fullniftiout\
                    \n\nalready exists -- csurf won't overwrite it!\
                    \nTo redo:\
                    \n\n    rm NIFTI \
                      \n        OR\
                      \n    select NIFTI instead (skip convert)\
                    \n\n...quitting"
          return
        }
#xxx -- why didn't this catch non-writeable DVD on City iMac??
        if ![canwriteormakefile $ifile] {
          confirmalert "can't convert BRIK->NIFTI:\n\nBRIK dir not writable"
          return
        }
        if ![okreplace "" "OK to locally convert AFNI BRIK:\
                          \n\n    $ifile\n\nto NIFTI?" "Convert/Continue"] {
          confirmalert "Recon-all: AFNI BRIK not converted\n\n...quitting"
          return
        }
        set savedir [pwd]
        cdlog [file dirname $ifile]
        set command \
          "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dAFNItoNIFTI \
          [backslashspaces $ifile]"
        runacmd "$command" $reconallbu "RECON-ALL  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        cdlog $savedir
        if ![file exists $fullniftiout] {
          confirmalert "BRIK->NIFTI conversion failed:\
                    \n\nselect NIFTI infile instead, or\
                      \ncopy BRIK to a writeable directory"
          return
        }
        set mghinprawscanfiles($num) $fullniftiout  ;# reset input
      }
    }
  }

  ### mk cmd: http://surfer.nmr.mgh.harvard.edu/fswiki/ReconAllTableStableV5.1
  # subject
  set subarg "-subjid $reconallparms(name)"
  # directive
  set directive "-all"
  if { $reconallparms(startwmflag) } {
    set directive "-autorecon2-wm -autorecon3"
  }
  if { $reconallparms(skipstep1flag) } {
    set directive "-all-skipstep1"  ;# N.B.: my hacked recon-all
  }
  # input files
  set ifilesarg ""
  foreach ent [lsort [array names mghinprawscanfiles]] {
    set num [string range $ent 0 1]
    set ifilesarg "$ifilesarg -i $mghinprawscanfiles($num)"
  }
  if {$subjectexists} { set ifilesarg "" }
  # flags
  set flagsarg ""
  if { $reconallparms(noasegflag) } {
    set flagsarg "$flagsarg -noaseg"
  }
  if { $reconallparms(notalcheckflag) } {
    set flagsarg "$flagsarg -notal-check"
  }
  if { $hemi == "rh" } {
    set flagsarg "$flagsarg -hemi rh"
  }
  if { $hemi == "lh" } {
    set flagsarg "$flagsarg -hemi lh"
  }
  if { $reconallparms(otheroptions) != "" } {
    set flagsarg "$flagsarg $reconallparms(otheroptions)"
  }
  # cmd
  if { $reconallparms(skipstep1flag) } {  ;# req's: fs 5.3.0 or 6.0.0 or 7.1.1
    if       [string match *5.3.0* [exec cat $env(FSURF_DIR)/build-stamp.txt]] {
      set recon-all-hacked recon-all5.3.0b
    } elseif [string match *6.0.0* [exec cat $env(FSURF_DIR)/build-stamp.txt]] {
      set recon-all-hacked recon-all6.0.0b
    } elseif [string match *7.1.1* [exec cat $env(FSURF_DIR)/build-stamp.txt]] {
      set recon-all-hacked recon-all7.1.1b
    } else {
      confirmalert "modified recon-all (with new opt: -all-skipstep1)\
                  \nrequires freesurfer 5.3.0 or 6.0.0 or 7.1.1"
      return
    }
    set rcacmd \
      "$noarchdir/$recon-all-hacked $subarg $directive $ifilesarg $flagsarg"

  } else {
    set rcacmd "$mghbindir/recon-all $subarg $directive $ifilesarg $flagsarg"
  }

  ### make csh script, cat to log (N.B.: recon-all requires tcsh not just csh)
  set id [open $ftmpcsh w 0755]
  puts $id "#! /bin/tcsh -f"
  puts $id "setenv SUBJECTS_DIR \"$env(SUBJECTS_DIR)\"" ;#Mac10.11 no pass*/
  puts $id "setenv FREESURFER_HOME \"$env(FSURF_DIR)\""
  puts $id "source \"\$FREESURFER_HOME/SetUpFreeSurfer.csh\"" ;#wait-subst,space
  puts $id $rcacmd
  close $id
  runacmd "cat $ftmpcsh" $reconallbu "RECON-ALL  " cmdinput $cmdlog cmdpid
  tkwait variable cmdpid

  ### run csh script in subshell with clean env
  set purplekill 0
  set command "csh $ftmpcsh"
  runacmd "$command" $reconallbu "RECON-ALL  " cmdinput $cmdlog cmdpid
  tkwait variable cmdpid

  ### goto created subjectdir
  if [file exists $env(SUBJECTS_DIR)/$reconallparms(name)] {
    set name $reconallparms(name)
    cdsubjectscripts
    if {$purplekill} { ;#kill csurf->all, kill ftmpcsh req's kill reconall,tee
      set pslines [split [exec ps uxww] "\n"]
      set rcacmd [string trimright $rcacmd]  ;# rm trailing spaces: patt match
      set teecmd \
        "tee -a $env(SUBJECTS_DIR)/$reconallparms(name)/scripts/recon-all.log"
      set pids {}
      foreach line $pslines {
        if [string match "*$rcacmd*" "$line"] { lappend pids [lindex $line 1] }
        if [string match "*$teecmd*" "$line"] { lappend pids [lindex $line 1] }
      }
      foreach pid $pids { catch { exec kill -9 $pid } }
      if [file exists IsRunning.$hemi] { rmlog IsRunning.$hemi }
      if [file exists IsRunning.lh+rh] { rmlog IsRunning.lh+rh } ;# if from wm
      confirmalert "Recon-all: killed recon for subject $reconallparms(name)"
    } else {
      confirmalert "Recon-all: subject $reconallparms(name) done"
    }
  } else {
    confirmalert "Recon-all: failed to create subject $reconallparms(name)"
  }
  rmlog $ftmpcsh
}

### AVGSURF button command (Cross Sess Spherical Average panel)
proc avgsurfcmd { } {
  global spgnums spgsubjects dispname fullname
  global env cmdlog mghbindir gtmpcsh mghsubjtoolsflag
  global avgsurfbu dispnamecombo choosingavgsurfdir usercanceldir
  global bintcsh_is_installed

  # check MGH freesurfer there
  if {!$mghsubjtoolsflag} {
    confirmalert "Make AvgSurf: env var with location of MGH\
                \nfreesurfer (FSURF_DIR) not set:\
              \n\n    (1)  if not installed, install MGH freesurfer\
              \n\n    (2a)  tcsh: setenv FSURF_DIR <installdir>\
                \n    (2b)  bash: export FSURF_DIR=<installdir>\
              \n\n    (3)  restart csurf"
    return
  }

  # check for tcsh
  if {!$bintcsh_is_installed} {
    confirmalert "Make AvgSurf:  /bin/tcsh is not installed\
              \n\n  => MGH make_average_subject won't work <=\
              \n\nInstall tcsh (e.g., sudo apt-get install tcsh)\
                \nand try again"
    return
  }

  # check inputs
  set subjnamelist ""
  foreach num [lsort [array names spgnums]] {  ;# linenums-to-avg
    set subj $spgsubjects($num)
    if ![file exists $env(SUBJECTS_DIR)/$subj] {
      confirmalert "Make AvgSurf: subject dir:\n\n    $subj\
                \n\nnot found in\n\n    $env(SUBJECTS_DIR)"
      return
    }
    set subjnamelist "$subjnamelist $subj"
  }
  if ![llength $subjnamelist] { return }
  set fmtlist ""
  foreach subj $subjnamelist { set fmtlist "$fmtlist\n    $subj" }

  # intro
  confirmalert "Make AvgSurf:\
            \n\nThe next dialog chooses name for\
              \nnew average surface subject:\
            \n\n    (1) can't overlap any current subject\
              \n    (2) must be in current SUBJECTS_DIR\
            \n\nTo remake avg surf with same name,\
              \nfirst hand-remove existing one"

  # check/confirm proposed out 
  set mustexist 0
  set fullname $env(SUBJECTS_DIR)/
  choosedir fullname "Enter new avg surface subjectdir:" $mustexist
  tkwait variable fullname
  if {$usercanceldir} { return }
  if [file exists $fullname] {
    confirmalert "Make AvgSurf: proposed avg subject:\
              \n\n    [file tail $fullname]\n\nalready exists.\
              \n\nTry again with different name"
    return
  }
  if { [file dirname $fullname] != $env(SUBJECTS_DIR) } {
    confirmalert "Make AvgSurf: can't make avg subject in\
                \na different directory:\n\n    [file dirname $fullname]\
              \n\nthan the one containing the indiv subjects:\
              \n\n    $env(SUBJECTS_DIR)"
    return
  }
  if ![canwriteormakefile $fullname] {
    confirmalert "Make AvgSurf: permissions prevent\
                \ncreate new subject:\n\n    [file tail $fullname]\
              \n\nin SUBJECTS_DIR:\n\n    [file dirname $fullname]"
    return
  }
  set currdispname $dispname
  set choosingavgsurfdir 1  ;# block not-found cbx:select_dispsubj callback
  set dispname [file tail $fullname]
  set choosingavgsurfdir 0
  if ![okreplace $dispname \
    " Ready to create new avg surface subject:\n\n    $dispname\n\n\
      in SUBJECTS_DIR:\n\n    $env(SUBJECTS_DIR)\n\n\
      from subject list:\n$fmtlist" "Create"] {
    confirmalert \
     "Make AvgSurf: new avg subject surface:\n\n    $dispname\n\nnot created"
    set choosingavgsurfdir 1  ;# block change namefile callback on restore
    set dispname $currdispname
    set choosingavgsurfdir 0
    return
  }

  # make cmd (make_average_subject is csh that calls mris_make_average_surface)
  set outarg "--out $dispname"
  set subsarg "--subjects $subjnamelist"
  set command "$mghbindir/make_average_subject $outarg $subsarg"

  # make csh script, cat to log (N.B.: make_average_subject req's tcsh not csh)
  set id [open $gtmpcsh w 0755]
  puts $id "#! /bin/tcsh -f"
  puts $id "setenv SUBJECTS_DIR $env(SUBJECTS_DIR)" ;#Mac10.11 no longer pass*/
  puts $id "setenv FREESURFER_HOME $env(FSURF_DIR)"
  puts $id "source \"\$FREESURFER_HOME/SetUpFreeSurfer.csh\"" ;#wait-subst,space
  puts $id $command
  close $id
  runacmd "cat $gtmpcsh" $avgsurfbu "AVGSURF  " cmdinput $cmdlog cmdpid
  tkwait variable cmdpid

  # run csh script in subshell with clean env
  set command "csh $gtmpcsh"
  runacmd "$command" $avgsurfbu "AVGSURF  " cmdinput $cmdlog cmdpid
  tkwait variable cmdpid

  # check output, cleanup
  if ![file exists $env(SUBJECTS_DIR)/$dispname] {
    confirmalert "Make AvgSurf: failed to create avg subj:\n\n    $dispname\
              \n\nFailed command left here:\n\n    $gtmpcsh"
  } else {
    rmlog $gtmpcsh
    $dispnamecombo insert 0 $dispname  ;# put at top (vs. re-alphabetize)
    $dispnamecombo config -value $dispname ;# avgdir now exists: allow callback
    fixinflatedavg $dispname
  }
}

### AVGSURF button subcommand (Cross Sess Spherical Average panel)
proc fixinflatedavg { avgname } {
  global surfdir labeldir inflatedext2 areaext curvext sulcext pialext
  global env bindir avgsurfbu cmdlog stmptcl2 fsaverage

  ## check sub, FIX-POLES labels there
  set firstsurf $env(SUBJECTS_DIR)/$avgname/$surfdir/rh.${inflatedext2}
  if ![file exists $firstsurf] {
    putlog "fix inflated_avg skipped: $firstsurf not found"
    confirmalert "FixInflatedAvg:\n\n    $firstsurf\n\nnot found"
    return
  }
## was: assume fsaverage has been updates w/fsaverage-adds
#  set firstlab $env(SUBJECTS_DIR)/$fsaverage/$labeldir/rh-FIX-POLES.label
#  if ![file exists $firstlab] {
#    putlog "fix inflated_avg skipped: $fsaverage rh-FIX-POLES.label not found"
#  confirmalert "FixInflatedAvg:\n\n    $firstlab\n\nnot found (fsaverage-adds)"
#    return
#  }
  set fixlabdir $env(CSURF_DIR)/$fsaverage-ADDITIONS/$labeldir
  set firstlab $fixlabdir/rh-FIX-POLES.label
  if ![file exists $firstlab] {
    putlog \
     "skip fix inflated_avg: $fsaverage-ADDITIONS rh-FIX-POLES.label not found"
    confirmalert "FixInflatedAvg:\n\n    $firstlab\n\nnot found"
    return
  }

  ## use fsaverage FIX-POLES labels to fix N/S poles of cross-subj inflated_avg
  foreach hem { rh lh } {
    # copy old area,surf to ORIG (vs. mv since surf fix starts w/existing)
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${areaext} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${areaext}ORIG
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${inflatedext2} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${inflatedext2}ORIG
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${curvext} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${curvext}ORIG
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${sulcext} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${sulcext}ORIG
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${pialext} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${pialext}ORIG

    # inflated_avg: make tksurfer tcl script, cat to log, run it
    set id [open $stmptcl2 w 0644]
    puts $id "### tksurfer tcl script to fix inflated_avg poles"
    puts $id "setfile label $fixlabdir/$labeldir/$hem-FIX-POLES.label"
    puts $id "read_label_to_annot_using_col 120 120 255"
    puts $id "set locklabelflag 1"
    puts $id "shrink 40"
    #puts $id "compute_normals_areas"    ;# already done by shrink
    puts $id "setfile area ~/$surfdir/$hem.$areaext"
    puts $id "write_binary_areas"
    puts $id "setfile outsurf ~/$surfdir/$hem.$inflatedext2"
    puts $id "write_binary_surface"
    puts $id "setfile curv ~/$surfdir/$hem.$curvext"
    puts $id "read_binary_curv"
    puts $id "smooth_curv 1"    ;# N.B.: respects locklabelflag
    puts $id "write_binary_curv"
    puts $id "setfile curv ~/$surfdir/$hem.$sulcext"
    puts $id "read_binary_curv"
    puts $id "smooth_curv 1"
    puts $id "write_binary_curv"
    puts $id "exit"
    close $id
    runacmd "cat $stmptcl2" $avgsurfbu "AVGSURF  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    set command "$bindir/tksurfer $avgname $hem $inflatedext2 -tcl $stmptcl2"
    runacmd "$command" $avgsurfbu "AVGSURF  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid

    # pial: make tksurfer tcl script, cat to log, run it
    set id [open $stmptcl2 w 0644]
    puts $id "### tksurfer tcl script to fix pial poles"
    puts $id "setfile label $fixlabdir/$labeldir/$hem-FIX-POLES.label"
    puts $id "read_label_to_annot_using_col 120 120 255"
    puts $id "set locklabelflag 1"
    puts $id "set ws 0.5"
    puts $id "set wn 0.05"
    puts $id "shrink 30"
    puts $id "setfile outsurf ~/$surfdir/$hem.$pialext"
    puts $id "write_binary_surface"
    puts $id "exit"
    close $id
    runacmd "cat $stmptcl2" $avgsurfbu "AVGSURF  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    set command "$bindir/tksurfer $avgname $hem $pial -tcl $stmptcl2"
    runacmd "$command" $avgsurfbu "AVGSURF  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid

    # cp curr to NEW
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${areaext} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${areaext}NEW
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${inflatedext2} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${inflatedext2}NEW
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${curvext} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${curvext}NEW
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${sulcext} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${sulcext}NEW
    cplog $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${pialext} \
          $env(SUBJECTS_DIR)/$avgname/$surfdir/$hem.${pialext}NEW
  }
  rmlog $stmptcl2
  putlog "csurf: fixed $avgname inflated_avg poles with rh,lh-FIX-POLES.label"
  putlog "csurf: fixed $avgname pial poles with rh,lh-FIX-POLES.label"
}

### Strip Skull (hi-res) menu item
proc runtkstriphires { } {
  global env name datfile stripskullparms

  if [file exists $datfile] { readarrayparms $datfile struct }
  if {!$stripskullparms(usehiresstripskullflag)} {
    if ![okreplace "nofile" \
        " Expert Prefs -> StripSkull curr set to use \"mri_strip_skull\":\n\n\
          Re-set to use \"tkstrip\" instead?"\
        "Use tkstrip"] {
      confirmalert "use mri_strip_skull (Expert Prefs) -- not changed"
      return
    } else {
      set stripskullparms(usehiresstripskullflag) 1
      writearrayparmscmd $env(SUBJECTS_DIR) $name
    }
  }
  if {$stripskullparms(usehiresstripskullflag)} {
    after 500 {  ;# wait for bgsequencewin
      setupexpertparms                             ;# N.B.: reads dat
      set winx [expr [winfo rootx .progress]+45]   ;# rel to existing
      set winy [expr [winfo rooty .progress]+130]  ;# unoverlap
      wm geometry .setuppopup +${winx}+${winy}
      .setuppopup.to.nb raise stripskull
    }
  }
  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  set cmdlablist { "Strip skull" }
  set commandlist { tkstriphirescmd }
  set wilabel "STRIP SKULL (hi-res)"
  set bulabel StripSkull
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

### Strip Skull (hi-res) step 1 (of 1) command
proc tkstriphirescmd { subjectsdir name } {
  global cmdlog processbu processkill subprocessredo
  global stripskullparms
  global volumedir origdir pddir pdbraindir braindir
  global force bindir smallscreenflag doublebufferflag minglxdepthflag

  set invol1 $subjectsdir/$name/$volumedir/$pddir    ;# first try PD
  set invol2 $subjectsdir/$name/$volumedir/$origdir  ;# skip T1, just use orig

  set outvol1 $subjectsdir/$name/$volumedir/$pdbraindir
  set outvol2 $subjectsdir/$name/$volumedir/$braindir

  set firstin $invol1/COR-001
  putlog "\ntkstrip (hi-res): (1) look for input volume:\n  $firstin ..."
  if ![file exists $firstin] {
    set invol $invol1.mgz  ;# TODO: .mgh
    putlog "tkstrip (hi-res): (2) look for input volume:\n  $invol ..."
    set outvol $outvol1.mgz
    if ![file exists $invol] {
      set firstin $invol2/COR-001
      putlog "tkstrip (hi-res): (3) look for input volume:\n  $firstin ..."
      set outvol $outvol2
      if ![file exists $firstin] {
        set invol $invol2.mgz  ;# TODO: .mgh
        putlog "tkstrip (hi-res): (4) look for input volume:\n  $invol ..."
        set outvol $outvol2.mgz
        if ![file exists $invol] {
          confirmalert "Input to \"tkstrip\" not found in:\
                    \n\n    $subjectsdir/$name/$volumedir\
                    \n\nLooked for (in order):\
                    \n\n    (1) [file tail [file rootname $invol1]]  (COR dir)\
                      \n    (2) [file tail $invol1].mgz\
                    \n\n    (3) [file tail [file rootname $invol2]]  (COR dir)\
                      \n    (4) [file tail $invol2].mgz\
                    \n\n...first put \"orig\" and maybe \"PD\" dataset in:\
                      \n$subjectsdir/$name/$volumedir"
          set processkill 1
          return
        }
      }
    }
  }
  putlog "\ntkstrip (hi-res): using input volume:\n  $invol"

  set opts ""
  if {$smallscreenflag} { set opts "$opts -followglwinflag 0" }
  if {!$doublebufferflag} { set opts "$opts -doublebufferflag 0" }
  if {$minglxdepthflag} { set opts "$opts -glxdepth 24" }
  if {$stripskullparms(usescript)} { ;#script: PD->PDbrain->calcimg->brain,orig
    set command  "$bindir/tkstrip $name [backslashspaces $invol] \
      -tcl [backslashspaces $stripskullparms(tclscript)] $opts"
  } else {
    if {$stripskullparms(action) != "default"} {
      set opts "$opts -fzero $stripskullparms(action)"
    }
    if {$stripskullparms(fzero) != "default"} {
      set opts "$opts -fzero $stripskullparms(fzero)"
    }
    if {$stripskullparms(fmax) != "default"} {
      set opts "$opts -fzero $stripskullparms(fmax)"
    }
    if {$stripskullparms(dfrac) != "default"} {
      set opts "$opts -fzero $stripskullparms(dfrac)"
    }
    if {$stripskullparms(istilt) != "default"} {
      set opts "$opts -fzero $stripskullparms(istilt)"
    }
    if {$stripskullparms(fsteepness) != "default"} {
      set opts "$opts -fzero $stripskullparms(fsteepness)"
    }
    if {$stripskullparms(fstrength) != "default"} {
      set opts "$opts -fzero $stripskullparms(fstrength)"
    }
    if {$stripskullparms(update) != "default"} {
      set opts "$opts -fzero $stripskullparms(update)"
    }
    if {$stripskullparms(decay) != "decay"} {
      set opts "$opts -fzero $stripskullparms(decay)"
    }
    set command "$bindir/tkstrip $name $invol $opts"
  }

  if {!$force} {
    ## N.B.: now only checks $outvol (if complex script, check more overwrite)
    if { [file extension $outvol] == ".mgz" } {
      set firstout $outvol
    } else {
      set firstout $outvol/COR-001
    } 
    if [file exists $firstout] {
      if {$subprocessredo} {
        set action [okreplace $firstout \
          "Stripskull: Images ($braindir): $firstout...\
          exist (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $firstout \
          "Strip Skull: Images ($braindir): $firstout...\
          exist--use them or redo/overwrite?" "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
	    }
	  }
  runacmd "$command" $processbu TKSTRIPintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Filter WM (hi-res) menu item (use same Expert Prefs as mri_segment)
proc runwmfilterhires { } { 
  global env name datfile wmfilterparms

  if [file exists $datfile] { readarrayparms $datfile struct }
  if {!$wmfilterparms(usehireswmfilterflag)} {
    if ![okreplace "nofile" \
        " Expert Prefs -> FilterWM currently set to use \"mri_segment\":\n\n\
          Re-set to use \"wmfilter\" instead?"\
        "Use wmfilter"] { confirmalert \
          "use mri_segment (Expert Prefs) -- not changed\n\n    ...quitting"
      return
    } else {
      set wmfilterparms(usehireswmfilterflag) 1
      writearrayparmscmd $env(SUBJECTS_DIR) $name
    }
  }
  if {$wmfilterparms(usehireswmfilterflag)} {
    after 500 {  ;# wait for bgsequencewin
      setupexpertparms                             ;# N.B.: reads dat
      set winx [expr [winfo rootx .progress]+45]   ;# rel to existing
      set winy [expr [winfo rooty .progress]+130]  ;# unoverlap
      wm geometry .setuppopup +${winx}+${winy}
      .setuppopup.to.nb raise wmfilter
    }
  }
  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  set cmdlablist { "WM aniso filter" }
  set commandlist { wmfilterhirescmd }
  set wilabel "FILTER WM (hi-res)"
  set bulabel FilterWM
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

### Filter WM (hi-res) step 1 (of 1) command
proc wmfilterhirescmd { subjectsdir name } {
  global cmdlog processbu processkill subprocessredo
  global wmfilterparms
  global volumedir origdir t1dir braindir wmdir
  global force bindir

  set invol1 $subjectsdir/$name/$volumedir/$braindir
  set invol2 $subjectsdir/$name/$volumedir/$t1dir
  set invol3 $subjectsdir/$name/$volumedir/$origdir

  set outvol1 $subjectsdir/$name/$volumedir/$wmdir
  set outvol2 $outvol1
  set outvol3 $outvol1

  set firstin $invol1/COR-001
  putlog "\nwmfilter (hi-res): (1) look for input volume:\n  $firstin ..."
  if ![file exists $firstin] {
    set invol $invol1.mgz  ;# TODO: .mgh
    putlog "wmfilter (hi-res): (2) look for input volume:\n  $invol ..."
    set outvol $outvol1.mgz
    if ![file exists $invol] {
      set firstin $invol2/COR-001
      putlog "wmfilter (hi-res): (3) look for input volume:\n  $firstin ..."
      set outvol $outvol2
      if ![file exists $firstin] {
        set invol $invol2.mgz  ;# TODO: .mgh
        putlog "wmfilter (hi-res): (4) look for input volume:\n  $invol ..."
        set outvol $outvol2.mgz
        if ![file exists $invol] {
          set firstin $invol3/COR-001
          putlog "wmfilter (hi-res): (5) look for input volume:\n  $firstin ..."
          set outvol $outvol3
          if ![file exists $firstin] {
            set invol $invol3.mgz  ;# TODO: .mgh
            putlog "wmfilter (hi-res): (6) look for input volume:\n  $invol ..."
            set outvol $outvol3.mgz
            if ![file exists $invol] {
              confirmalert \
                    "Input to \"wmfilter\" not found in:\
                 \n\n    $subjectsdir/$name/$volumedir\
                 \n\nLooked for (in order):\
                 \n\n    (1) [file tail [file rootname $invol1]]  (COR dir)\
                   \n    (2) [file tail $invol1].mgz\
                 \n\n    (3) [file tail [file rootname $invol2]]  (COR dir)\
                   \n    (4) [file tail $invol2].mgz\
                 \n\n    (5) [file tail [file rootname $invol3]]  (COR dir)\
                   \n    (6) [file tail $invol3].mgz\
                 \n\n...no T1 input data found"
              set processkill 1
              return
            }  ;# else found $invol3.mgz
          } else {
            if [file exists $invol3.mgz] {  ;# warn CORdir precedence
                confirmalert \
                  "${invol3}/COR-001 (CORdir) and $invol2.mgz both present:\
               \n\nUsing CORdir (move CORdir aside to use mgz)"
            }
          }
        }  ;# else found $invol2.mgz
      } else {
        if [file exists $invol2.mgz] {  ;# warn CORdir precedence
            confirmalert \
              "${invol2}/COR-001 (CORdir) and $invol2.mgz both present:\
           \n\nUsing CORdir (move CORdir aside to use mgz)"
        }
      }
    }  ;# else found $invol1.mgz
  } else {
    if [file exists $invol1.mgz] {  ;# warn CORdir precedence
        confirmalert "${invol1}/COR-001 (CORdir) and $invol1.mgz both present:\
                  \n\nUsing CORdir (move CORdir aside to use mgz)"
    }
  }
  putlog "\nwmfilter (hi-res): using input volume:\n  $firstin"

  set opts ""
  if {$wmfilterparms(wm_hi) != "default"} { 
    set opts "$opts -white_hilim $wmfilterparms(wm_hi)"
  }
  if {$wmfilterparms(wm_low) != "default"} { 
    set opts "$opts -white_lolim $wmfilterparms(wm_low)"
  }
  if {$wmfilterparms(gray_hi) != "default"} { 
    set opts "$opts -gray_hilim $wmfilterparms(gray_hi)"
  }
  if {$wmfilterparms(gausstruncflag)} { ;# N.B.: trunc parms *after* gaussflag
    set opts "-gaussflag 1 -kfwhm $wmfilterparms(kfwhm) $opts"
  }
  set command "$bindir/wmfilter \
    [backslashspaces $invol] [backslashspaces $outvol] $opts"

  if {!$force} {
    if { [file extension $outvol] == ".mgz" } {
      set firstout $outvol
    } else {
      set firstout $outvol/COR-001
    }
    if [file exists $firstout] {
      if {$subprocessredo} {
        set action [okreplace $firstout \
          "Filter/Segment WM: Images ($wmdir): $firstout...\nexist\
          (stale, but may be edited!)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $firstout \
          "Filter/Segment WM: Images ($wmdir): $firstout...\nexist\
          (may be edited!)--use them or redo/overwrite?" "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu WMFILTERintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Fill WM (hi-res) menu command
proc runfillhires { } {
  global env name hemi datfile wmfillparms

  if [file exists $datfile] { readarrayparms $datfile struct }
  if {!$wmfillparms(usehiresfillflag)} {
    if ![okreplace "nofile" \
        " Expert Prefs -> Fill WM currently set to use \"mri_fill\":\n\n\
          Re-set to use \"fill\" instead?"\
        "Use fill"] {
      confirmalert "use mri_fill (Expert Prefs) -- not changed"
      return
    } else {
      set wmfillparms(usehiresfillflag) 1
      writearrayparmscmd $env(SUBJECTS_DIR) $name
    }
  }
  if {$wmfillparms(usehiresfillflag)} {
    after 500 {  ;# wait for bgsequencewin
      setupexpertparms
      set winx [expr [winfo rootx .progress]+45]   ;# rel to existing
      set winy [expr [winfo rooty .progress]+130]  ;# unoverlap
      wm geometry .setuppopup +${winx}+${winy}
      .setuppopup.to.nb raise wmfill
    }
  }
  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  set cmdlablist { "fill white matter" }
  set commandlist { wmfillcmd }  ;# N.B.: wmfillcmd does old/hi-res or mri_fill
  set wilabel "FILL WM (hi-res)"
  set bulabel FillWM
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist
  writearrayparmscmd $origsubjectsdir $origname
}

### Create Orig Surface (hi-res) menu command
proc runsurfhires { } {
  global env name datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  set cmdlablist { "tessellate white matter RH" "tessellate white matter LH" }
  set commandlist { surfhirescmdrh surfhirescmdlh }
  set wilabel "CREATE ORIG SURFACE (hi-res)"
  set bulabel CreateOrigSurface 
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc surfhirescmdrh { subjectsdir name } {
  surfhirescmd $subjectsdir $name rh
}

proc surfhirescmdlh { subjectsdir name } {
  surfhirescmd $subjectsdir $name lh
}

### Create Orig Surface (hi-res) step 1 (of 1) command
proc surfhirescmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global wmfillparms surfparms volumedir filleddir
  global surfdir origext
  global force bindir

  set invol $subjectsdir/$name/$volumedir/$filleddir
  set firstin $invol/COR-001
  if ![file exists $firstin] {
    set invol $invol.mgz
    if ![file exists $invol] {
      confirmalert "Input to \"surf\" not found in:\
                \n\n$subjectsdir/$name/$volumedir\
                \n\nLooked for:\
                \n\n    (1) [file tail [file rootname $invol]]  (COR dir)\
                  \n    (2) [file tail $invol]\
                \n\n...fill first"
      set processkill 1
      return
    }
  } else {  ;# CORdir exists
    if [file exists $invol.mgz] {  ;# warn CORdir precedence
      confirmalert \
        "${filleddir}/COR-001 (CORdir) and $filleddir.mgz both present:\
     \n\nUsing CORdir (move CORdir aside to use mgz)"
    }
  }

  if {$hemi == "rh"} { set fillcolor $wmfillparms(seed1valRH) }
  if {$hemi == "lh"} { set fillcolor $wmfillparms(seed2valLH) }
  set opts ""
  if {$surfparms(newquadoutputflag)} { set opts "$opts -newquad" }
  set origsurf $subjectsdir/$name/$surfdir/$hemi.$origext
  set command "$bindir/surf [backslashspaces $invol] $fillcolor \
    [backslashspaces $origsurf] $opts"
  if {!$force} {
    if [file exists $origsurf] {
      if {$subprocessredo} {
        set action [okreplace $origsurf \
          "Tessellate: Surface: $origsurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $origsurf \
         "Tessellate: Surface: $origsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu TESSELLATEintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid

  # no adjustable parms to save (fill color set in fillhires)
}

### Smooth(Curv)/Inflate(Sulc) menu command
proc mghsmoothinflate { } {
  global env name hemi datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { \
      "smooth (make curv/area) RH surf" "smooth (make curv/area) LH surf" \
      "inflate (make sulc) RH surface" "inflate (make sulc) LH surface" }
    set commandlist { \
      mghsmoothcmdrh mghsmoothcmdlh mghinflatecmdrh mghinflatecmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { \
      "smooth (make curv/area) RH surf" "inflate (make sulc) RH surface" }
    set commandlist { mghsmoothcmdrh mghinflatecmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { \
      "smooth (make curv/area) LH surf" "inflate (make sulc) LH surface" }
    set commandlist { mghsmoothcmdlh mghinflatecmdlh }
  }
  set wilabel "SMOOTH, INFLATE ORIG SURFACE"
  set bulabel SmoothInflateSurface 
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc mghsmoothcmdrh { subjectsdir name } {
  mghsmoothcmd $subjectsdir $name rh
}

proc mghsmoothcmdlh { subjectsdir name } {
  mghsmoothcmd $subjectsdir $name lh
}

### Smooth(Curv)/Inflate(Sulc) step 1 (of 2) command (=smoothcmd w/mghbindir)
proc mghsmoothcmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global inflateparms  ;# same as old
  global force mghbindir
  global surfdir origext foldedext curvext areaext

  set origsurf   $subjectsdir/$name/$surfdir/$hemi.$origext
  set foldedsurf $subjectsdir/$name/$surfdir/$hemi.$foldedext
  set curvfile   $subjectsdir/$name/$surfdir/$hemi.$curvext
  set areafile   $subjectsdir/$name/$surfdir/$hemi.$areaext

  set opts ""
  if {$inflateparms(smoothcycles) != "default"} {
    set opts "$opts -n $inflateparms(smoothcycles)"
  }
  if {$inflateparms(write_per_iters) != "default"} {
    set opts "$opts -w $inflateparms(write_per_iters)"
  }
  set command "$mghbindir/mris_smooth $opts \
    [backslashspaces $origsurf] [backslashspaces $foldedsurf]"

  if ![file exists $origsurf] {
    confirmalert "Surface: $origsurf\nnot found  ...tessellate first"
    set processkill 1
    return
  }
  if {!$force} {
    if [file exists $foldedsurf] {
      if {$subprocessredo} {
        set action [okreplace $foldedsurf \
        "Smooth Surface: $foldedsurf exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $foldedsurf \
          "Smooth Surface: $foldedsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
    # redo: always overwrite curv,area
  }
  runacmd "$command" $processbu SMOOTHWMintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

proc mghinflatecmdrh { subjectsdir name } {
  mghinflatecmd $subjectsdir $name rh
}

proc mghinflatecmdlh { subjectsdir name } {
  mghinflatecmd $subjectsdir $name lh
}

### Smooth(Curv)/Inflate(Sulc) step 2 (of 2) command (=inflatecmd w/mghbindir) 
proc mghinflatecmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global inflateparms   ;# same as old
  global force mghbindir
  global surfdir foldedext inflatedext sulcext

  set foldedsurf   $subjectsdir/$name/$surfdir/$hemi.$foldedext
  set inflatedsurf $subjectsdir/$name/$surfdir/$hemi.$inflatedext
  set sulcfile     $subjectsdir/$name/$surfdir/$hemi.$sulcext

  set opts ""
  if {$inflateparms(inflatecycles) != "default"} {
    set opts "$opts -n $inflateparms(inflatecycles)"
  }
  if {$inflateparms(metric2smooth) != "default"} {
    set opts "$opts -dist $inflateparms(metric2smooth)"
  }
  if {$inflateparms(nbrs) != "default"} {
    set opts "$opts -nbrs $inflateparms(nbrs)"
  }
  if {$inflateparms(write_per_iters) != "default"} {
    set opts "$opts -w $inflateparms(write_per_iters)"
  }
  set command "$mghbindir/mris_inflate $opts \
    [backslashspaces $foldedsurf] [backslashspaces $inflatedsurf]"
  
  if ![file exists $foldedsurf] {
    confirmalert "Surface: $foldedsurf\nnot found  ...smooth first"
    set processkill 1
    return
  }
  if {!$force} {
    if [file exists $inflatedsurf] {
      if {$subprocessredo} {
        set action [okreplace $inflatedsurf \
          "Inflate Surface: $inflatedsurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $inflatedsurf \
          "Inflate Surface: $inflatedsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
    # redo: always overwrite sulc
  }
  runacmd "$command" $processbu INFLATEintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Smooth(Curv)/Inflate(Sulc) (hi-res) menu command (=above w/hires parms)
proc mghsmoothinflatehires { } {
  global env name hemi datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { \
      "MGH smooth (mkcurv/area) RHsurf" "MGH smooth (mkcurv/area) LH surf" \
      "MGH inflate (mk sulc) RH surface" "MGH inflate (mk sulc) LH surface" }
    set commandlist { \
      mghsmoothhirescmdrh mghsmoothhirescmdlh \
      mghinflatehirescmdrh mghinflatehirescmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { \
      "MGH smooth (mkcurv/area) RHsurf" "MGH inflate (mk sulc) RH surface" }
    set commandlist { mghsmoothhirescmdrh mghinflatehirescmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { \
      "MGH smooth (mkcurv/area) LH surf" "MGH inflate (mk sulc) LH surface" }
    set commandlist { mghsmoothhirescmdlh mghinflatehirescmdlh }
  }
  set wilabel "SMOOTH, INFLATE ORIG SURFACE (hi-res)"
  set bulabel SmoothInflateSurface 
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc mghsmoothhirescmdrh { subjectsdir name } {
  mghsmoothhirescmd $subjectsdir $name rh
}

proc mghsmoothhirescmdlh { subjectsdir name } {
  mghsmoothhirescmd $subjectsdir $name lh
}

### Smooth(Curv)/Inflate(Sulc) hi-res step 1 (of 2) command
proc mghsmoothhirescmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global inflateparms  ;# same as old
  global force mghbindir
  global surfdir origext foldedext curvext areaext

  set origsurf   $subjectsdir/$name/$surfdir/$hemi.$origext
  set foldedsurf $subjectsdir/$name/$surfdir/$hemi.$foldedext
  set curvfile   $subjectsdir/$name/$surfdir/$hemi.$curvext
  set areafile   $subjectsdir/$name/$surfdir/$hemi.$areaext

  set opts ""
  if {$inflateparms(smoothhirescycles) != "default"} {
    set opts "$opts -n $inflateparms(smoothhirescycles)"
  }
  if {$inflateparms(write_per_iters) != "default"} {
    set opts "$opts -w $inflateparms(write_per_iters)"
  }
  set command "$mghbindir/mris_smooth $opts \
    [backslashspaces $origsurf] [backslashspaces $foldedsurf]"

  if ![file exists $origsurf] {
    confirmalert "Surface: $origsurf\nnot found  ...tessellate first"
    set processkill 1
    return
  }
  if {!$force} {
    if [file exists $foldedsurf] {
      if {$subprocessredo} {
        set action [okreplace $foldedsurf \
        "Smooth Surface: $foldedsurf exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $foldedsurf \
          "Smooth Surface: $foldedsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
    # redo: always overwrite curv,area
  }
  runacmd "$command" $processbu SMOOTHWMintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

proc mghinflatehirescmdrh { subjectsdir name } {
  mghinflatehirescmd $subjectsdir $name rh
}

proc mghinflatehirescmdlh { subjectsdir name } {
  mghinflatehirescmd $subjectsdir $name lh
}

### Smooth(Curv)/Inflate(Sulc) (hi-res) step 2 (of 2) command
proc mghinflatehirescmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global inflateparms   ;# same as old
  global force mghbindir
  global surfdir foldedext inflatedext sulcext

  set foldedsurf   $subjectsdir/$name/$surfdir/$hemi.$foldedext
  set inflatedsurf $subjectsdir/$name/$surfdir/$hemi.$inflatedext
  set sulcfile     $subjectsdir/$name/$surfdir/$hemi.$sulcext

  set opts ""
  if {$inflateparms(inflatehirescycles) != "default"} {
    set opts "$opts -n $inflateparms(inflatehirescycles)"
  }
  if {$inflateparms(metric2smooth) != "default"} {
    set opts "$opts -dist $inflateparms(metric2smooth)"
  }
  if {$inflateparms(nbrshires) != "default"} {
    set opts "$opts -nbrs $inflateparms(nbrshires)"
  }
  if {$inflateparms(write_per_iters) != "default"} {
    set opts "$opts -w $inflateparms(write_per_iters)"
  }
  set command "$mghbindir/mris_inflate $opts \
    [backslashspaces $foldedsurf] [backslashspaces $inflatedsurf]"
  
  if ![file exists $foldedsurf] {
    confirmalert "Surface: $foldedsurf\nnot found  ...smooth first"
    set processkill 1
    return
  }
  if {!$force} {
    if [file exists $inflatedsurf] {
      if {$subprocessredo} {
        set action [okreplace $inflatedsurf \
          "Inflate Surface: $inflatedsurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $inflatedsurf \
          "Inflate Surface: $inflatedsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
    # redo: always overwrite sulc
  }
  runacmd "$command" $processbu INFLATEintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Re-Make Surf (Fill->Inflate) menu item (all-in-one combining hi-res w/MGH)
proc fillcreatesmoothinflatehires { } {
  global env name force datfile hemi wmfillparms oldsubjtoolsflag

  if [file exists $datfile] { readarrayparms $datfile struct }

  # next ignore oldsubjtoolsflag (FreeSurfer0.8 mri_fill can't use hi-res)
  if {!$wmfillparms(usehiresfillflag)} { ;
    confirmalert "Re-Make Surf: hi-res csurf requires use \"fill\":\
              \n\nPreferences -> Expert Preferences -> FillWM tab:\
              \n\n    => click \"use fill (vs. mri_fill)\"\
                \n    => set values for  manual seeds, cuts"
    return
  }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  set saveforce $force
  set force 1
  if {$hemi == "both"} {
    set cmdlablist { \
      "fill white matter" \
      "tessellate white matter RH" "tessellate white matter LH" \
      "MGH smooth (mkcurv/area) RH surf" "MGH smooth (mkcurv/area) LH surf" \
      "MGH inflate (mk sulc) RH surface" "MGH inflate (mk sulc) LH surface" \
    }
    set commandlist { \
      wmfillcmd surfhirescmdrh surfhirescmdlh \
      mghsmoothhirescmdrh mghsmoothhirescmdlh \
      mghinflatehirescmdrh mghinflatehirescmdlh \
    }
  }
  if {$hemi == "rh"} {  ;# don't retessellate both despite possibly stale
    #old: " tessellate white matter RH" "tessellate white matter LH"
    set cmdlablist { \
      "fill white matter" \
      "tessellate white matter RH" \
      "MGH smooth (mkcurv/area) RH surf" \
      "MGH inflate (mk sulc) RH surface" \
    }
    #old: wmfillcmd surfhirescmdrh surfhirescmdlh
    set commandlist { \
      wmfillcmd surfhirescmdrh \
      mghsmoothhirescmdrh \
      mghinflatehirescmdrh \
    }
  }
  if {$hemi == "lh"} {  ;# don't retessellate both despite possibly stale
    #old:  "tessellate white matter RH" "tessellate white matter LH"
    set cmdlablist { \
      "fill white matter" \
      "tessellate white matter LH" \
      "MGH smooth (mkcurv/area) LH surf" \
      "MGH inflate (mk sulc) LH surface" \
    }
    #old:  wmfillcmd surfhirescmdrh surfhirescmdlh
    set commandlist { \
      wmfillcmd surfhirescmdlh \
      mghsmoothhirescmdlh \
      mghinflatehirescmdlh \
    }
  }
  set wilabel "FILL, CREATE, SMOOTH, INFLATE (hi-res)"
  set bulabel FillCreateSmoothInflate
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
  set force $saveforce
}

### Make Final Surface menu command
proc mghmkfinalsurf { } {
  global env name hemi datfile finalparms

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name

  if {$finalparms(usescript)} {
    if ![okreplace "" "Expert Parms (Final tab) currently\
                     \nset to use tksurfer tcl script:\
                   \n\nOK to unclick \"use tksurfer tcl script\"\
                     \nand use mris_make_surfaces instead?" \
          "Update Expert Preferences"] {
        confirmalert "Expert Preferences settings not altered"
        return
    } else {
      set finalparms(usescript) 0
      writearrayparmscmd $origsubjectsdir $origname
    }
  }

  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "make final RH surfaces" "make final LH surfaces" }
    set commandlist { mghmkfinalsurfcmdrh mghmkfinalsurfcmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "make final RH surfaces" }
    set commandlist { mghmkfinalsurfcmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "make final LH surfaces" }
    set commandlist { mghmkfinalsurfcmdlh }
  }
  set wilabel "MAKE FINAL SURFACE"
  set bulabel MakeFinalSurface
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc mghmkfinalsurfcmdrh { subjectsdir name } {
  mghmkfinalsurfcmd $subjectsdir $name rh
}

proc mghmkfinalsurfcmdlh { subjectsdir name } {
  mghmkfinalsurfcmd $subjectsdir $name lh
}

### Make Final Surface step 1 (of 1) command (=mkfinalsurfcmd w/mghbindir)
proc mghmkfinalsurfcmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global finalparms
  global force mghbindir
  global surfdir curvext origext whiteext graymidext pialext thkext
  global volumedir origdir wmdir filleddir

  set origvol   $subjectsdir/$name/$volumedir/$origdir        ;# only incheck
  set wmvol     $subjectsdir/$name/$volumedir/$wmdir
  set filledvol $subjectsdir/$name/$volumedir/$filleddir
  set curvfile  $subjectsdir/$name/$surfdir/$hemi.$curvext
  set origsurf  $subjectsdir/$name/$surfdir/$hemi.$origext

  set whitesurf   $subjectsdir/$name/$surfdir/$hemi.$whiteext ;# only outcheck
  set graymidsurf $subjectsdir/$name/$surfdir/$hemi.$graymidext
  set pialsurf    $subjectsdir/$name/$surfdir/$hemi.$pialext
  set thkfile     $subjectsdir/$name/$surfdir/$hemi.$thkext

  set opts ""
  #if {$finalparms(selfintersect)} { set opts "-graymid" }
  if {$finalparms(quickfinalflag)} { set opts "$opts -q" }
  if {$finalparms(whiteonlyflag)}  { set opts "$opts -whiteonly" }
  if {$finalparms(noasegflag)}     { set opts "$opts -noaseg" }
  if {$finalparms(noaparcflag)}    { set opts "$opts -noparc" }
  if {$finalparms(noautoflag)}     { set opts "$opts -noauto" }
  if {$finalparms(longflag)}       { set opts "$opts -long" }
  if {$finalparms(max) != "default"} {
    set opts "$opts -max $finalparms(max)"
  }
  set command "$mghbindir/mris_make_surfaces $opts $name $hemi"

  if ![file exists $origsurf] {
    confirmalert \
      "Make Final Surfaces: $origsurf\nnot found  ...tessellate first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $whitesurf] } {
      if {$subprocessredo} {
        set action [okreplace $whitesurf \
          "Make Final Surfaces: $whitesurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $whitesurf \
          "Make Final Surfaces: $whitesurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      # redo implies overwrite (curv), pial, white, thickness
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu FINALSURFACESintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Make Final Surface (hi-res) menu command
proc tksurfermkfinalsurf { } {
  global env name hemi datfile finalparms

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name

  if {!$finalparms(usescript)} {
    if ![okreplace "" "Expert Parms (Final tab) set to use\
                     \nmris_make_surfaces:\
                   \n\nClick \"use tksurfer tcl script\" and\
                     \nuse tksurfer tcl script instead?" \
        "Update Expert Preferences"] {
      confirmalert "Expert Preferences settings not altered"
      return
    } else {
      set finalparms(usescript) 1
      writearrayparmscmd $origsubjectsdir $origname
    }
  }

  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "make final RH surfaces" "make final LH surfaces" }
    set commandlist { tksurfermkfinalsurfcmdrh tksurfermkfinalsurfcmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "make final RH surfaces" }
    set commandlist { tksurfermkfinalsurfcmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "make final LH surfaces" }
    set commandlist { tksurfermkfinalsurfcmdlh }
  }
  set wilabel "MAKE FINAL SURFACE"
  set bulabel MakeFinalSurface
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc tksurfermkfinalsurfcmdrh { subjectsdir name } {
  tksurfermkfinalsurfcmd $subjectsdir $name rh
}

proc tksurfermkfinalsurfcmdlh { subjectsdir name } {
  tksurfermkfinalsurfcmd $subjectsdir $name lh
}

### Make Final Surfaces (hi-res) step 1 (of 1) command
proc tksurfermkfinalsurfcmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global finalparms
  global force bindir
  global surfdir curvext origext foldedext whiteext graymidext pialext thkext
  global volumedir origdir braindir t2dir filleddir

  set origvol    $subjectsdir/$name/$volumedir/$origdir
  set brainvol   $subjectsdir/$name/$volumedir/$braindir
  set t2vol      $subjectsdir/$name/$volumedir/$t2dir
  set filledvol  $subjectsdir/$name/$volumedir/$filleddir
  set curvfile   $subjectsdir/$name/$surfdir/$hemi.$curvext
  set origsurf   $subjectsdir/$name/$surfdir/$hemi.$origext  ;# only incheck
  set foldedsurf $subjectsdir/$name/$surfdir/$hemi.$foldedext

  set whitesurf $subjectsdir/$name/$surfdir/$hemi.$whiteext ;# only outcheck
  set pialsurf  $subjectsdir/$name/$surfdir/$hemi.$pialext
  set thkfile   $subjectsdir/$name/$surfdir/$hemi.$thkext

  ### tksurfer tcl script (library or local scripts dir)
  #tcl: -loadmri1 $braindir.mgz -loadmri2 $filleddir.mgz -loadmri3 $t2dir.mgz
  set command \
    "$bindir/tksurfer $name $hemi $origext \
       -tcl [backslashspaces $finalparms(tclscript)] \
       -tksurferinterface macro \
       -dividequadsflag 0"  ;# backslash maybe local script
  if ![file exists $origsurf] {
    confirmalert \
      "Make Final Surfaces: $origsurf\nnot found  ...tessellate first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $whitesurf] } {
      if {$subprocessredo} {
        set action [okreplace $whitesurf \
          "Make Final Surfaces: $whitesurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $whitesurf \
          "Make Final Surfaces: $whitesurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      # redo implies overwrite (curv), pial, white, thickness
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu FINALSURFACESintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### Inflate Surface Patch (hi-res) menu command
proc tksurferinflatepatch { } {
  global env name hemi datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "inflate RH patch" "inflate LH patch" }
    set commandlist { tksurferinflatepatchcmdrh tksurferinflatepatchcmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "inflate RH patch " }
    set commandlist { tksurferinflatepatchcmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "inflate LH patch" }
    set commandlist { tksurferinflatepatchcmdlh }
  }
  set wilabel "INFLATE PATCH"
  set bulabel InflatePatch
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc tksurferinflatepatchcmdrh { subjectsdir name } {
  tksurferinflatepatchcmd $subjectsdir $name rh
}

proc tksurfermkfinalsurfcmdlh { subjectsdir name } {
  tksurferinflatepatchcmd $subjectsdir $name lh
}

### Inflate Surface Patch (hi-res) step 1 (of 1) command
proc tksurferinflatepatchcmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global inflateparms surfparms flattenparms
  global force bindir stmptcl3 cmdsonlyid
  global surfdir surfext patchext bitmapdir begin3dext
  global smallscreenflag doublebufferflag tksurferlogflag minglxdepthflag
  global outpatch  ;# maybe only def'd here

  ### in/out names
  set inpatch $subjectsdir/$name/$surfdir/$hemi.$patchext
  set patchroot [file rootname [file rootname $patchext]] ;# just init stem
  set outpatch $subjectsdir/$name/$surfdir/$hemi.$patchroot-inflated.patch.3d
  set rgbdir $subjectsdir/$name/$bitmapdir
  set rgbstem [file tail $outpatch]

  ### check inpatch
  if ![string match *.$begin3dext $inpatch] {
    if ![okreplace $inpatch "Inflate Patch: input patch:\n\n    $inpatch\
        \n\nsuffix not .${begin3dext}\n\nOK to inflate anyway?" "Inflate"] {
      set processkill 1
      return
    }
  }
  if ![file exists $inpatch] {
    confirmalert "Inflate Patch: inpatch not found:\n\n    $inpatch"
    set processkill 1
    return
  }
  wm title .progress "$name (input: [file tail $inpatch])"

  ### check outpatch
  if {!$force} {
    if { [file exists $outpatch] } {
      if {$subprocessredo} {
        set action [okreplace $outpatch \
          "Inflate Patch: $outpatch exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $outpatch \
          "Inflate Patch: $outpatch exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }

  ### make tmp tcl script (TODO: make into lib script, allow edit from csurf)
  set id [open $stmptcl3 w 0644]
  puts $id "cd $subjectsdir/$name/scripts"
  puts $id "open_window"
  puts $id "read_binary_curv"
  puts $id "read_binary_areas"
  puts $id "setfile patch $inpatch"
  puts $id "read_binary_patch"
  puts $id "set flag2d 0; restore"    ;# back to 3d
  puts $id "really_center_brain"
  puts $id "recalc_surface_center"
  puts $id "make_lateral_view"
  puts $id "reloadarea"               ;# tksurfer.tcl funct to un-zero midline
  puts $id "set areaflag 1"           ;# use area_shrink (vs. shrink)
  puts $id "set ws $inflateparms(ws)"
  puts $id "set wn $inflateparms(wn)"
  puts $id "set wa $inflateparms(wa)"
  puts $id "set wc $inflateparms(wc)" ;# off
  puts $id "set bordneiflag $inflateparms(bordneiflag)" ;#mv bord w/nonbord nei
  puts $id "set rmvtx2nonbordflag $inflateparms(rmvtx2nonbordflag)" ;#rm bad
  puts $id "set wt $inflateparms(wt)"
  puts $id "redraw"
  ## next tksurfer.tcl funct works but can't add normalize_area, dump tiffs
  #puts $id "startstopshrink $inflateparms(tkstepspercycle) \
  #                          $inflateparms(tkinflatecycles)"
  ## unwrap/augment tksurfer.tcl startstopshrink
  puts $id "set steps $inflateparms(tkstepspercycle)"
  puts $id "set cycles $inflateparms(tkinflatecycles)"
  puts $id "update"
  puts $id "update idletasks"
  puts $id "after 500"
  puts $id "confirmalert \"Adjust brain pose/scale before inflate if desired\
            \\n\\nTo begin inflate: click OK\""
  puts $id "update"
  puts $id "for {set cyc 0} {\$cyc < \$cycles} {incr cyc} {"
  puts $id "  shrink \$steps"
  puts $id "  update"
  puts $id "  update idletasks"
  puts $id "  set currcyc \[expr \$cyc+1\]"
  puts $id "  set currstep \[expr \$currcyc*\$steps\]"
  puts $id "  set total \[expr \$cycles*\$steps\]"
  puts $id "  puts \"$stmptcl3: cyc \$currcyc: (\$currstep of \$total steps)\""
  puts $id "  normalize_area"
  puts $id "  redrawbutton"
  if {$inflateparms(tktiffpercycleflag)} {
    puts $id "  if !\[file exists $rgbdir\] { exec mkdir $rgbdir }"
    puts $id "  set rgb $rgbdir/$rgbstem-\[format \"%05d\" \$currstep\].tiff"
    puts $id "  save_rgb"
  }
  puts $id "}"
  ## unwrap startstopshrink done
  puts $id "setfile patch $outpatch"
  puts $id "write_binary_patch"
  puts $id "confirmalert \"Wrote inflated patch:\
            \\n\\n    $outpatch\
            \\n\\nTksurfer left up for final surf inspect\
            \\n\\nTo exit: click OK\""
  puts $id "exit"
  close $id
  set id [open $stmptcl3 r]
  if {$cmdsonlyid != "fileNONE"} {  ;# if log open, dump tcl script into it
    puts $cmdsonlyid "### made tmp tksurfer tcl script: ${stmptcl3}"
    foreach line [split [read $id] "\n"] { puts $cmdsonlyid "# $line" }
  } else {  ;# dump to csurf log (N.B.: cmdlog, not surflog)
    putlog "### made tmp tksurfer tcl script: ${stmptcl3}"
    foreach line [split [read $id] "\n"] { putlog "# $line" }
  }
  close $id

  ### make cmd
  set glxdeptharg ""
  if {$minglxdepthflag} { set glxdeptharg "-glxdepth 12" }
  set opts " \
    -tksurferinterface mini \
    -dividequadsflag $surfparms(dividequadsflag) \
    -undividequadsflag $surfparms(undividequadsflag) \
    -newquadoutputflag $surfparms(newquadoutputflag) \
    -newcurvareaoutputflag $surfparms(newcurvareaoutputflag) \
    -writefloatpatchflag $flattenparms(writefloatpatchflag) \
    -overlayflag 0 \
    -smallscreenflag $smallscreenflag \
    -doublebufferflag $doublebufferflag \
    $glxdeptharg \
    -tksurferlogflag $tksurferlogflag \
    "
  set command "$bindir/tksurfer $name $hemi $surfext -tcl $stmptcl3 $opts"

  ### run command
  runacmd "$command" $processbu INFLATEPATCHintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
  rmlog $stmptcl3
}

### MGH Flatten Surface menu command (same as orig except $bindir)
proc mghflatten { } {
  global env name hemi datfile
  global patchescombo patchext
  global outpatch   ;# maybe only def'd here

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "flatten RH surface" "flatten LH surface" }
    set commandlist { mghflattencmdrh mghflattencmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "flatten RH surface" }
    set commandlist { mghflattencmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "flatten LH surface" }
    set commandlist { mghflattencmdlh }
  }
  set wilabel "FLATTEN SURFACE"
  set bulabel FlattenSurface
  set title "$name (input: $hemi.$patchext)"
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist $title

  writearrayparmscmd $origsubjectsdir $origname  ;# trigs fixpatches callback
  if { [info exists outpatch] && [file exists $outpatch] } {  ;# reset combo
    $patchescombo config -value [string range [file tail $outpatch] 3 end]
  }
}

proc mghflattencmdrh { subjectsdir name } {
  mghflattencmd $subjectsdir $name rh
}

proc mghflattencmdlh { subjectsdir name } {
  mghflattencmd $subjectsdir $name lh
}

### Flatten Surface step 1 command
proc mghflattencmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global flattenparms  ;# same as old
  global force mghbindir
  global surfdir begin3dext beginflatext endflatext patchext fullpatch
  global fullpref patchinfix
  global outpatch  ;# maybe only def'd here

  set pos $subjectsdir/$name/scripts/position.tcl
  if ![file exists $pos] { mkpositiontcl }

  ### inpatch (allow reflatten already flat)
  set inpatch $subjectsdir/$name/$surfdir/$hemi.$patchext
  if ![file exists $inpatch] {
    confirmalert "Flatten Surface: inpatch not found:\n\n    $inpatch"
    set processkill 1
    return
  }
  if {!$force} {
    if [string match *.$endflatext $inpatch] {
      if ![okreplace $inpatch \
          "Flatten Surface: OK to re-flatten already flat?\n\n$inpatch" \
          "Re-Flatten"] {
        set processkill 1
        return
      } else {
        set subprocessredo 1  ;# don't offer "use existing" b/c decided here
      }
    }
  }
  wm title .progress "$name (input: [file tail $inpatch])"
  set patchroot [file rootname $patchext]   ;# e.g., full0.3d -> full0
  set outpatch $subjectsdir/$name/$surfdir/$hemi.$patchroot.$endflatext

  ### command (subprocessredo overwrites w/sleep)
  set opts ""
  if {$flattenparms(write_per_iters) != "default"} {
    set opts "$opts -w $flattenparms(write_per_iters)"
  }
  #old: if { [string match ${fullpatch}* $patchroot] } { } => "full.patch"
  if { [string match ${fullpref}*.${patchinfix}* $patchroot] } {
    if {$flattenparms(vertices_per_full) != "default" &&
        $flattenparms(sampledist_mm_full) != "default"} {
      set opts "$opts -distances \
         $flattenparms(sampledist_mm_full) $flattenparms(vertices_per_full)"
    }
  } else {  ;# non-full more stringent occip ("patch") parms
    if {$flattenparms(vertices_per_patch) != "default" &&
        $flattenparms(sampledist_mm_patch) != "default"} {
      set opts "$opts -distances \
         $flattenparms(sampledist_mm_patch) $flattenparms(vertices_per_patch)"
    }
  }
  set command "$mghbindir/mris_flatten $opts \
    [backslashspaces $inpatch] [backslashspaces $outpatch]"

  ### outpatch
  if {!$force} {
    if { [file exists $outpatch] } {
      if {$subprocessredo} {
        set action [okreplace $outpatch \
          "Flatten Surface: $outpatch exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $outpatch \
          "Flatten Surface: $outpatch exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }

  ### go
  runacmd "$command" $processbu FLATTENintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### MGH Sphere/Register Surface menu cmd -- re-register: skip sph or redo
proc mghspherereg { } {
  global env name hemi datfile surfext

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "sphere RH surface" "sphere LH surface" \
                     "register RH to target" "register LH to target" }
    set commandlist { mghspherecmdrh mghspherecmdlh \
                      mghsphereregcmdrh mghsphereregcmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "sphere RH surface" "register RH to target" }
    set commandlist { mghspherecmdrh mghsphereregcmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "sphere LH surface" "register LH surface" }
    set commandlist { mghspherecmdlh mghsphereregcmdlh }
  }
  set wilabel "REGISTER SURFACE"
  set bulabel RegisterSurface
   set title "$name (input: $hemi.$surfext)"
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist $title

  writearrayparmscmd $origsubjectsdir $origname
}

proc mghspherecmdrh { subjectsdir name } {
  mghspherecmd $subjectsdir $name rh
}

proc mghspherecmdlh { subjectsdir name } {
  mghspherecmd $subjectsdir $name lh
}

### Register Surface step 1 (of 2) command  ;#diffs: mghbindir, called directly
proc mghspherecmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global sphereparms
  global force mghbindir
  global surfdir inflatedext sphereext

  set inflatedsurf $subjectsdir/$name/$surfdir/$hemi.$inflatedext
  set spheresurf $subjectsdir/$name/$surfdir/$hemi.$sphereext

  set opts ""
  if {$sphereparms(write_per_iters) != "default"} {
    set opts "$opts -w $sphereparms(write_per_iters)"
  }
  #xxx -- current mris_sphere usage incorrect (leave all default for now)
  #if {$sphereparms(tol) != "default"} {
  #  set opts "$opts -tol $sphereparms(tol)"
  #}
  #if {$sphereparms(nav) != "default"} {
  #  set opts "$opts -nav $sphereparms(nav)"
  #}
  #if {$sphereparms(parea) != "default"} {  ;# just -area??
  #  set opts "$opts -parea $sphereparms(parea)"
  #mgh}
  #if {$sphereparms(dist) != "default"} {
  #  set opts "$opts -dist $sphereparms(dist)"
  #}
  set command "$mghbindir/mris_sphere $opts \
    [backslashspaces $inflatedsurf] [backslashspaces $spheresurf]"

  if ![file exists $inflatedsurf] {
    confirmalert "Sphere Surface: $inflatedsurf\nnot found  ...inflate first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $spheresurf] } {
      if {$subprocessredo} {
        set action [okreplace $spheresurf \
          "Sphere Surface: $spheresurf exists (stale)--redo/overwrite?" "Redo"]
      } else {
        set action [okreplace $spheresurf \
          "Sphere Surface: $spheresurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu SPHEREintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

proc mghsphereregcmdrh { subjectsdir name } {
  mghsphereregcmd $subjectsdir $name rh
}

proc mghsphereregcmdlh { subjectsdir name } {
  mghsphereregcmd $subjectsdir $name lh
}

### MGH Sphere/Register Surface step 2 (of 2) cmd ;#diffs:mghbindir,direct call
proc mghsphereregcmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global sphereparms
  global surfdir avgdir sphereext regext
  global force mghbindir
  global env

  set spheresurf $subjectsdir/$name/$surfdir/$hemi.$sphereext
  ### targs: $hemi.average.tif, $hemi.average.curvature.filled.buckner40.tif
  ### N.B.: next targs no longer exist in my non-FreeSurfer0.8 distro
  #set targsurf $env(CSURF_DIR)/$avgdir/$hemi.$sphereparms(morphtarg).tif
  ### N.B.: instead use ones in MGH distro
  set targsurf $env(FSURF_DIR)/$avgdir/$hemi.$sphereparms(morphtarg).tif
  if ![file exists $targsurf] {
    confirmalert \
      "Sphere-Register Surface: morph target:\n\n    $targsurf\n\nnot found"
    set processkill 1
    return
  }
  set sphereregsurf $subjectsdir/$name/$surfdir/$hemi.$sphereext.$regext

  ### command
  set opts ""
  if {$sphereparms(write_per_iters) != "default"} {
    set opts "$opts -w $sphereparms(write_per_iters)"
  }
  if {$sphereparms(tol) != "default"} {
    set opts "$opts -tol $sphereparms(tol)"
  }
  if {$sphereparms(nav) != "default"} {
    set opts "$opts -nav $sphereparms(nav)"
  }
  if {$sphereparms(sulcfirst) != "default"} {
    set opts "$opts -curv"   ;# curv touch-up after main sulc
  }
  if {$sphereparms(parea) != "default"} {
    set opts "$opts -parea $sphereparms(parea)"
  }
  if {$sphereparms(corr) != "default"} {
    set opts "$opts -corr $sphereparms(corr)"
  }
  if {$sphereparms(dist) != "default"} {
    set opts "$opts -dist $sphereparms(dist)"
  }
  #mris_register -curv -corr <def:1.0> -parea <def:0.2> -dist <def:5.0> ...
  # new defaults (~2008) dist:0.1->5.0, new nav:256->1024
  set command "$mghbindir/mris_register $opts [backslashspaces $spheresurf] \
    [backslashspaces $targsurf] [backslashspaces $sphereregsurf]"

  if ![file exists $spheresurf] {
    confirmalert \
      "Sphere-Register Surface: $spheresurf\nnot found  ...sphere first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $sphereregsurf] } {
      if {$subprocessredo} {
        set action [okreplace $sphereregsurf \
  "Sphere-Register Surface: $sphereregsurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $sphereregsurf \
  "Sphere-Register Surface: $sphereregsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu SPHEREREGintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### MGH Register Surface to Symm (symmetric) menu cmd
proc mghregsymm { } {
  global env name hemi datfile

  if [file exists $datfile] { readarrayparms $datfile struct }

  set origsubjectsdir $env(SUBJECTS_DIR)
  set origname $name
  selecthemi "Process both hemispheres?"
  if {$hemi == "both"} {
    set cmdlablist { "register2symm RH surface" "register2symm LH surface" }
    set commandlist { mghregsymmcmdrh mghregsymmcmdlh }
  }
  if {$hemi == "rh"} {
    set cmdlablist { "register2symm RH surface" }
    set commandlist { mghregsymmcmdrh }
  }
  if {$hemi == "lh"} {
    set cmdlablist { "register2symm LH surface" }
    set commandlist { mghregsymmcmdlh }
  }
  set wilabel "REG-TO-SYMM SURFACE"
  set bulabel RegSymmSurface
  bgsequencewin $wilabel $bulabel $cmdlablist $commandlist

  writearrayparmscmd $origsubjectsdir $origname
}

proc mghregsymmcmdrh { subjectsdir name } {
  mghregsymmcmd $subjectsdir $name rh
}

proc mghregsymmcmdlh { subjectsdir name } {
  mghregsymmcmd $subjectsdir $name lh
}

proc mghregsymmcmd { subjectsdir name hemi } {
  global cmdlog processbu processkill subprocessredo
  global sphereparms
  global surfdir avgdir sphereext regext
  global force mghbindir
  global env

### xhemireg
#  create "xhemi" subdir in $subject
#  foreach hemi:
#    flip vols: orig T1 brain brainmask norm aseg aparc+aseg
#      mri_vol2vol --mov $invol --targ $invol --reg $reg \
#                  --o $outdir/mri/$vol.mgz --keep-precision --no-save-reg
#    flip seg label codes:  aseg aparc+aseg wmparc aparc.a2009s+aseg
#      mri_convert $outdir/mri/$vol.mgz $outdir/mri/$vol.mgz \
#                  --left-right-swap-label
#    recompute talairach (skip with --no-tal)
#    flip surfs: orig white pial smoothwm sphere inflated
#      mri_surf2surf --s $subject --sval-xyz $surf --hemi $srchemi \ 
#                    --tval-xyz --tval $outdir/surf/$trghemi.$surf
#    flip labels: cortex (just swap lh/rh)
#    flip annotations: (aparc BA aparc.a2009s (just swap lh/rh)
#    register to average.curvature.filled.buckner40.tif:
#      recon-all -sb $xsubject -hemi $trghemi -surfreg
#      N.B.: -sb same as -s w/o basename to pass subdir of subj
#      mris_register -curv `fsr-getxopts mris_register $XOptsFile` \
#        ../surf/$hemi.sphere $AvgTif ../surf/$hemi.sphere.reg  # expert opts
###

#xxxxxxxx -- opphemi: unfinished: begin local TODO
confirmalert "REGISTER-TO-SYMMETRIC STILL IN PROG"
return
  set spheresurf $subjectsdir/$name/$surfdir/$hemi.$sphereext
  ### targs: $hemi.average.tif, $hemi.average.curvature.filled.buckner40.tif
  ### N.B.: next targs no longer exist in my non-FreeSurfer0.8 distro
  #set targsurf $env(CSURF_DIR)/$avgdir/$hemi.$sphereparms(morphtarg).tif
  ### N.B.: instead use ones in MGH distro
  set targsurf $env(FSURF_DIR)/$avgdir/$hemi.$sphereparms(morphtarg).tif
  if ![file exists $targsurf] {
    confirmalert \
      "RegisterSymm Surface: morph target:\n\n    $targsurf\n\nnot found"
    set processkill 1
    return
  }
  set sphereregsurf $subjectsdir/$name/$surfdir/$hemi.$sphereext.$regext

  ### command
  set opts ""
  if {$sphereparms(write_per_iters) != "default"} {
    set opts "$opts -w $sphereparms(write_per_iters)"
  }
  if {$sphereparms(tol) != "default"} {
    set opts "$opts -tol $sphereparms(tol)"
  }
  if {$sphereparms(nav) != "default"} {
    set opts "$opts -nav $sphereparms(nav)"
  }
  if {$sphereparms(sulcfirst) != "default"} {
    set opts "$opts -curv"   ;# curv touch-up after main sulc
  }
  if {$sphereparms(parea) != "default"} {
    set opts "$opts -parea $sphereparms(parea)"
  }
  if {$sphereparms(corr) != "default"} {
    set opts "$opts -corr $sphereparms(corr)"
  }
  if {$sphereparms(dist) != "default"} {
    set opts "$opts -dist $sphereparms(dist)"
  }
  #mris_register -curv -corr <def:1.0> -parea <def:0.2> -dist <def:5.0> ...
  # new defaults (~2008) dist:0.1->5.0, new nav:256->1024
  set command "$mghbindir/mris_register $opts [backslashspaces $spheresurf] \
   [backslashspaces $targsurf] [backslashspaces $sphereregsurf]"
#xxxxxxxx -- opphemi: unfinished: end local TODO

  if ![file exists $spheresurf] {
    confirmalert \
      "RegisterSymm Surface: $spheresurf\nnot found  ...sphere first"
    set processkill 1
    return
  }
  if {!$force} {
    if { [file exists $sphereregsurf] } {
      if {$subprocessredo} {
        set action [okreplace $sphereregsurf \
    "RegisterSymm Surface: $sphereregsurf exists (stale)--redo/overwrite?" \
          "Redo"]
      } else {
        set action [okreplace $sphereregsurf \
    "RegisterSymm Surface: $sphereregsurf exists--use it or redo/overwrite?" \
          "Redo" "Use Existing"]
      }
      if {$action == 0} { set processkill 1; return }  ;# cancel
      if {$action == 1} { set subprocessredo 1 }       ;# overwrite
      if {$action == 2} { set command "sleep 0" }      ;# use existing
    }
  }
  runacmd "$command" $processbu REGSYMMintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### write out array parms using original (cmd-entering) subjectsdir and name
proc writearrayparmscmd { origsubjectsdir origname } {
  global env name datfile

  set currsubjectsdir $env(SUBJECTS_DIR)
  set currname $name
  set env(SUBJECTS_DIR) $origsubjectsdir
  set name $origname
  writearrayparms $datfile struct  ;# does cdsubjectscripts
  set env(SUBJECTS_DIR) $currsubjectsdir
  set name $currname
}

### MAKE SCANDIRS/ORIGDIRS buttoncmds (Make Scan/Origdirs, Find/Copy Raw panel)
proc mkdirscmd { nbwin type } {
  global env session functdirstyle name volumedir origdir origsubdirstem
  global mkdscandirnames mkdrawscanfiles mkdstripinitTRs mkdnewscannames
  global lastrawscandir

  if {$type == "origdirs"} { ;# varnames below still -scan- for both orig/scan
    set parentofdirs $env(SUBJECTS_DIR)/$name/$volumedir/$origdir
    set typ Orig
  } elseif {$type == "scandirs"} {
    set parentofdirs $env(FUNCTIONALS_DIR)/$session
    if {$functdirstyle == "imagesubdir"} {set parentofdirs $parentofdirs/image}
    set typ Scan
  } else { return }

  ### 1st pass for errors
  set uniqscandirlist {}
  foreach index [lsort [array names mkdscandirnames]] {
    set fullrawscanfile $mkdrawscanfiles($index)
    set newscandir $mkdscandirnames($index)
    set fullnewscandir $parentofdirs/$newscandir
    set fullnewlink $fullnewscandir/[file tail $fullrawscanfile]
    set fullrawscanfilelist [glob -nocomplain $fullrawscanfile]
    if { [llength $fullrawscanfilelist] > 1 } {
      confirmalert "$fullrawscanfile matches multiple files\n\n\
                    ...not yet implemented"  ;# TODO: accept set of ima's
      return
    }
    if {$newscandir == ""} {
      confirmalert \
        "Make/Link ${typ}dir: $typ Dir name\n\n  dir: $index\n\n...is empty"
      return
    }
    if [string match ?- $newscandir] {
      confirmalert \
     "Make/Link ${typ}dir: $typ Dir name:\n\n  $newscandir\n\n...is incomplete"
      return
    }
    if [file exists $fullnewscandir] {
      confirmalert \
    "Make/Link ${typ}dir: $typ Dir:\n\n\  $fullnewscandir\n\n...already exists"
      return
    }
    if {[lsearch -exact $uniqscandirlist $newscandir] == -1} {
      lappend uniqscandirlist $newscandir
    } else {
      confirmalert \
        "Make/Link ${typ}dir: $typ Dir name:\n\n  $newscandir\n\n...not unique"
      return
    }
    if [string match "* *" $newscandir] {
      confirmalert \
   "Make/Link ${typ}dir: $typ Dir name\n\n  \"$newscandir\"\n\n...remove space"
      return
    }
    if [string match "*;*" $newscandir] {
      confirmalert \
"Make/Link ${typ}dir: $typ Dir name\n\n  \"$newscandir\"\n\n...remove semicolon"
      return
    }
    if {$fullrawscanfile == ""} {
      confirmalert \
"Make/Link ${typ}dir: empty Raw Scan name for:\n\n  $newscandir\n\n...use FIND"
      return
    }
    if ![file exists $fullrawscanfile] {
      confirmalert \
        "Make/Link ${typ}dir: Raw scan:\n\n\  $fullrawscanfile\n\n...not found"
      return
    }
  }
  ### 2nd pass to make links, make new scan names, update hlist
  $nbwin subwidget hlist delete all
  foreach index [lsort [array names mkdscandirnames]] {
    # make new default name, allow edit, use at copy/TRstrip time
    set newscandir $mkdscandirnames($index)
    set newhead $newscandir
    if {$type == "scandirs"} { ;# strip num prefix from dir to make filename
      if {[string match ?-* $newscandir] || [string match ??-* $newscandir]} {
        set newhead \
          [string range $newscandir [expr [string first - $newscandir]+1] end]
      }
    } ;# else leave num suffix if "origdirs"
    set fullrawscanfile $mkdrawscanfiles($index)
    set newtail [file extension $fullrawscanfile]
    if {$newtail == ".BRIK"} { set newtail "+orig.BRIK" }
    if {$newtail == ".HEAD"} { set newtail "+orig.HEAD" }
    set mkdnewscannames($index) ${newhead}${newtail}
    set newscandir $mkdscandirnames($index)
    set fullnewscandir $parentofdirs/$newscandir
    set fullnewlink $fullnewscandir/zzz-[file tail $fullrawscanfile] ;# to end
    mkdirlog $fullnewscandir
    ### got rid of these 3 cp-killers (when links dangling)
    #exec ln -s $fullrawscanfile $fullnewlink
    exec echo $fullrawscanfile > ${fullnewlink}.txt
    if {[file extension $fullrawscanfile] == ".BRIK"} {
      #exec ln -s \
        [file rootname $fullrawscanfile].HEAD [file rootname $fullnewlink].HEAD
      exec echo [file rootname $fullrawscanfile].HEAD > \
                [file rootname $fullnewlink].HEAD.txt
    }
    if {[file extension $fullrawscanfile] == ".HEAD"} { ;# reset HEAD entries
      #exec ln -s [file rootname $fullrawscanfile].BRIK \
                      [file rootname $fullnewlink].BRIK
      exec echo [file rootname $fullrawscanfile].BRIK > \
                [file rootname $fullnewlink].BRIK.txt
      set mkdrawscanfiles($index) [file rootname $fullrawscanfile].BRIK
      set mkdnewscannames($index) [file rootname $mkdnewscannames($index)].BRIK
    }
    if {$type == "origdirs"} {
      set hlistentry $volumedir/$origdir/$newscandir
    }
    if {$type == "scandirs"} {
      set hlistentry $newscandir
      if {$functdirstyle == "imagesubdir"} { set hlistentry image/$newscandir }
    }
    $nbwin subwidget hlist add [manglepath $hlistentry] -text $hlistentry
  }
  ### 3rd pass to histogram new scan names and uniq-ize them
  set uniqnamelist {}
  foreach index [array names mkdnewscannames] {
    if {[lsearch -exact $uniqnamelist $mkdnewscannames($index)] == -1} {
      lappend uniqnamelist $mkdnewscannames($index)
    }
  }
  set namecntlist {}
  foreach uniqname $uniqnamelist {
    set namecnt 0
    foreach index [array names mkdnewscannames] {
      if {"$mkdnewscannames($index)" == "$uniqname"} { incr namecnt }
    }
    lappend namecntlist $namecnt
  }
  set i 0
  foreach uniqname $uniqnamelist {
    if {[lindex $namecntlist $i] != 1} {  ;# add num infix only if multiple
      set infix 1
      foreach index [lsort [array names mkdnewscannames]] { ;# num in scanorder
        set oldname $mkdnewscannames($index)
        if {"$oldname" == "$uniqname"} {
          set stem [file rootname $oldname]
          set ext [file extension .BRIK]
          if {"$ext" == ".BRIK"} {  ;# deal w/+orig
            set stem [string range $stem 0 [expr [string last + $stem] - 1]]
            set stem ${stem}-${infix}+orig
          } else { 
            set stem ${stem}-${infix}
          }
          set mkdnewscannames($index) ${stem}${ext}
          incr infix
        }
      }
    }
    incr i
  }
}

### strip init TRs, copy scan to origdir/scandir => AFNI-only!
proc stripinitTRscopyrawcmd { type } {
  global env session name volumedir origdir functdirstyle bindir afnibindir
  global mkdscandirnames mkdrawscanfiles mkdstripinitTRs mkdnewscannames
  global cmdlog stripcopybu lastrawscandir

  if {$type == "origdirs"} {
    set act Copy
    set typ Orig
    set runbuname "COPY-RAW"
  } elseif {$type == "scandirs"} {
    set act Strip/Copy
    set typ Scan
    set runbuname "STRIP/COPY-RAW  "
  } else { return }

  ### conservative (in case it breaks something)
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog "stripinit: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  ### 1st pass for errors
  set uniqscannamelist {}
  foreach index [lsort [array names mkdscandirnames]] {
    set newscandir $mkdscandirnames($index)
    set fullrawfile $mkdrawscanfiles($index)
    set tr1 $mkdstripinitTRs($index)
    set newscanname $mkdnewscannames($index)
    if {$newscanname == ""} {
      confirmalert \
        "$act Raw Scans: empty New Scan name for dir:\n\n    $newscandir\
     \n\n(forgot to click MAKE SCANDIRS)?"
      return
    }
    if {$type == "origdirs"} {
      set fullnewname \
        $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$newscandir/$newscanname
    }
    if {$type == "scandirs"} {
      if {$functdirstyle == "imagesubdir"} { set newscandir image/$newscandir }
      set fullnewname $env(FUNCTIONALS_DIR)/$session/$newscandir/$newscanname
    }
    if {$fullrawfile == ""} {
      confirmalert "$act Raw Scans: empty Raw Scan name for ${typ}dir:\n\n\
                    [file tail $newscandir]"
      return
    }
    if ![file exists $fullrawfile] {
     confirmalert "$act Raw Scans: rawfile:\n\n\  $fullrawfile\n\n...not found"
      return
    }
    if [file exists $fullnewname] {
      confirmalert "$act Raw Scans: outfile:\n\n\  $fullnewname\n\n\
                    ...already exists (delete manually to redo)"
      return
    }
    if {[lsearch -exact $uniqscannamelist $newscanname] == -1} {
      lappend uniqscannamelist $newscanname
    } else {
      confirmalert \
        "$act Raw Scans: New Scan name:\n\n  $newscanname\n\n...not unique"
      return
    }
    if { [file extension $fullnewname] != [file extension $fullrawfile] } {
      confirmalert "$act Raw Scans: bad suffix for outfile:\n\n\
       [file tail $fullnewname]\n\n(should be:  [file extension $fullrawfile])"
      return
    }
    if {$type == "scandirs"} {
      if ![isnum $tr1] {
        confirmalert "$act Raw Scans: bad value (=> $tr1 <=) for Strip TRs"
        return
      }
    }
    if [string match *.nii $fullrawfile] {
     if ![okreplace "" "OK convert NIFTI file?" "Convert NIFTI"] { return }
    }
    set rawstem [file rootname $fullrawfile]
    set rawtail [file tail $fullrawfile]
    if {$type == "scandirs"} {
      if { $mkdstripinitTRs($index) > 0 && [getafnireps $rawstem.HEAD] < 2 } {
        confirmalert \
         "$act Raw Scans: can't rm TRs from\n\n  $rawtail\n\n...only 1 time pnt"
        return
      }
    }
  }
  ### 2nd pass for real
  foreach index [lsort [array names mkdscandirnames]] {
    set newscandir $mkdscandirnames($index)
    set fullrawfile $mkdrawscanfiles($index)
    set rawstem [file rootname $fullrawfile]
    set rawsuff [file extension $fullrawfile]
    set newscanname $mkdnewscannames($index)
    if {$type == "origdirs"} {
      set tr1 0
      set fullnewname \
        $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$newscandir/$newscanname
    }
    if {$type == "scandirs"} {
      set tr1 $mkdstripinitTRs($index)
      if {$functdirstyle == "imagesubdir"} { set newscandir image/$newscandir }
      set fullnewname $env(FUNCTIONALS_DIR)/$session/$newscandir/$newscanname
    }
    set newstem [file rootname $fullnewname]
    if {$rawsuff == ".BRIK"} {  ;# just cp
      if {$tr1 == 0} {  ;# anatomical, align, or no-strip funct
        set command \
          "cp [backslashspaces $rawstem.BRIK] [backslashspaces $newstem.BRIK]"
        runacmd "$command" $stripcopybu $runbuname cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        set command \
          "cp [backslashspaces $rawstem.HEAD] [backslashspaces $newstem.HEAD]"
        runacmd "$command" $stripcopybu $runbuname cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      } else {  ;# functional run that needs initial vols stripped
        set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dTcat \
          -prefix [backslashspaces $newstem] \
          [backslashspaces $rawstem]\[${tr1}..$\]"
        runacmd "$command" $stripcopybu $runbuname cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }
      ###TODO: fix flipbrik into general 3D transpose to freesurfer loop order
      #set command "$bindir/flipbrik $newstem $newstem" ;#01-23-45anat=>noflip
      #runacmd "$command" $stripcopybu $runbuname cmdinput $cmdlog cmdpid
      #tkwait variable cmdpid
      forcebrikMSBfirst $newstem nowarn $stripcopybu $runbuname
    } elseif { $rawsuff == ".nii" } {  ;# convert-copy
      if {$tr1 == 0} {  ;# anatomical, align, or no-strip funct
        set command \
         "3dcopy [backslashspaces $rawstem.nii] [backslashspaces $newstem+orig]"
        runacmd "$command" $stripcopybu $runbuname cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      } else {  ;# bail for now if functional NIFTI needs TR's stripped
        confirmalert "Strip Init TRs: do *.nii manually (auto for *.BRIK)"
      }
    } elseif { $rawsuff == ".ima" } {
      confirmalert "Strip Init TRs: do *.ima manually (auto for *.BRIK)"
    } else {
      confirmalert "Strip Init TRs: do manually (auto for: *.BRIK)"
    }
  }
  set lastrawscandir /
}

### INIT and INIT/FLIP register.dat button command (Funct/Align/Extern panels)
proc writedefregdat { page { flip none } } {
  global name env session iscandir
  global sessionscanlists alignscanparms functscanlists 

  set iscandir $page
  if {$sessionscanlists($page,type) == "alignscan"} {
    if { ![info exists alignscanparms(brightness)] } {
      set alignscanparms(brightness) 1.0
    }
    foreach parm { inplane thickness } {
      if { ![info exists alignscanparms($parm)] ||
           $alignscanparms($parm) == "-unset-" ||
           $alignscanparms($parm) == ""} {
        confirmalert " Write Default Align Reg: missing parm ($parm)\n\n\
                       (READ HEADER clicked?)"
        return
      }
    }
    set inplane $alignscanparms(inplane)
    set thickness $alignscanparms(thickness)
    set brightness $alignscanparms(brightness)
    set fullregdat \
       $env(FUNCTIONALS_DIR)/$session/$iscandir/$alignscanparms(regdat)
  }
  if {$sessionscanlists($page,type) == "functscan" ||
      $sessionscanlists($page,type) == "extstatscan"} {
    if { ![info exists functscanlists($page,brightness)] } {
      set functscanlists($page,brightness) 1.0
    }
    foreach parm { inplane thickness } {
      if { ![info exists functscanlists($page,$parm)] ||
           $functscanlists($page,$parm) == "-unset-" ||
           $functscanlists($page,$parm) == ""} {
        confirmalert " Write Default Funct Reg: missing parm ($parm)\n\n\
                       (READ HEADER clicked?)"
        return
      }
    }
    set inplane $functscanlists($page,inplane)
    set thickness $functscanlists($page,thickness)
    set brightness $functscanlists($page,brightness)
    set fullregdat \
       $env(FUNCTIONALS_DIR)/$session/$iscandir/$functscanlists($page,regdat)
  }

  if { [file exists $fullregdat] } {
    if [okreplace $fullregdat "$fullregdat exists--move aside?" "Move Aside"] {
      mvlog $fullregdat $fullregdat~
      confirmalert "Transform: default $fullregdat made--existing moved aside"
    } else {
      confirmalert "Transform: $fullregdat not altered"
      return
    }
  }
  if [canwriteormakefile $fullregdat] {
    set id [open $fullregdat w 0644]
    puts $id "$name"
    puts $id "$inplane"
    puts $id "$thickness"
    puts $id "$brightness"
    if {$flip == "none"} {
      puts $id " 1.00 0.00 0.00 0.00"
      puts $id " 0.00 1.00 0.00 0.00"
      puts $id " 0.00 0.00 1.00 0.00"
      puts $id " 0.00 0.00 0.00 1.00"
    }
    if {$flip == "standardflip"} {
      puts $id " 1.00 0.00 0.00 0.00"
      puts $id " 0.00 0.00 1.00 0.00"
      puts $id " 0.00 1.00 0.00 0.00"
      puts $id " 0.00 0.00 0.00 1.00"
    }
    puts $id "round"
    close $id
  } else {
    confirmalert "Transform: can't write $fullregdat  ...transform not saved"
    return
  }
  if {$flip == "standardflip"} {
    confirmalert "Transform: apply standard flip: SAG-90, HOR-180, mirror"
  }
}

### ALIGN=>SUBJ (Align panel), FUNCT=>ALIGN, FUNCT=>SUBJ (Funct panel) buttons
proc regfunctcmd { page type } {
  global cmdlog align2subjbu funct2subjbu
  global env name session iscandir bindir
  global volumedir name t1dir origdir
  global alignscanparms functscanlists
  global smallscreenflag doublebufferflag minglxdepthflag

  if [checkconcurrent] { return }
  if { [checknamefile] != "match" } { return }
  set iscandir $page

  if {$type == "align2subj"} {
    set targdir $alignscanparms(tkregtargdir)
  }
  if {$type == "funct2subj" || $type == "funct2align"} {
    set targdir $functscanlists($page,tkregtargdir) ;# was $t1dir,then $origdir
  }
  set fulltargdir $env(SUBJECTS_DIR)/$name/$volumedir/$targdir
  if ![file exists $fulltargdir/COR-001] {
    set fulltargdir $env(SUBJECTS_DIR)/$name/$volumedir/$targdir.mgz
    if ![file exists $fulltargdir] {
      confirmalert " Register: target struct volume not found in:\n\n\
                     $env(SUBJECTS_DIR)/$name/$volumedir\n\n\
                     Looked for:\n\n\
                     (1) $targdir  (COR dir)\n\
                     (2) $targdir.mgz"  ;# N.B.: incompat w/old tkregister
      return
    }
  }

  if {$type == "align2subj"} {  ;# only one alignscan
    foreach parm { imagepatt slices xres yres regdat } {
      if { ![info exists alignscanparms($parm)] ||
           $alignscanparms($parm) == "-unset-" ||
           $alignscanparms($parm) == ""} {
        confirmalert "Register: missing parm ($parm) in Setup Align Scan"
        return
      }
    }
    if {$alignscanparms(imagepatt) != "COR-%03d" } {
      set suff [file extension $alignscanparms(imagepatt)]
      set tkregistersuffs ".im .bshort .bfloat .BRIK"
      if { [lsearch -exact $tkregistersuffs $suff] == -1 } {
        confirmalert \
    "Convert Align Scan: tkregister only reads $tkregistersuffs or COR/mgz imgs"
        return
      }
    }
    set fullmovdir $env(FUNCTIONALS_DIR)/$session/$iscandir
    set fullregdat $fullmovdir/$alignscanparms(regdat)
    if { [file extension $fullmovdir/$alignscanparms(imagepatt)] == ".BRIK"} {
      forcebrikMSBfirst \
        [file rootname $fullmovdir/$alignscanparms(imagepatt)] nowarn
    }
    if ![file exists $fullregdat] {
      writedefregdat $page
      confirmalert "Register: Funct->Struct Transform init'd (INIT button)"
    }
    set followarg ""
    set doublebufferarg ""
    set glxdeptharg ""
    if {$smallscreenflag}   { set followarg "-followglwinflag 0" }
    if {!$doublebufferflag} { set doublebufferarg "-doublebufferflag 0" }
    if {$minglxdepthflag}   { set glxdeptharg "-glxdepth 12" }
    set regoptions \
      "-movformat $alignscanparms(imagepatt) \
       -nslices $alignscanparms(slices) \
       -reps 1 \
       -imres $alignscanparms(xres) \
              $alignscanparms(yres) \
       -blur 1 \
       -invert 0 \
       $followarg \
       $doublebufferarg \
       $glxdeptharg \
       -regdat [backslashspaces $fullregdat]"
    set command "$bindir/tkregister \
      [backslashspaces $fullmovdir] [backslashspaces $fulltargdir] $regoptions"
    runacmd \
      "$command" $align2subjbu($page) "ALIGN=>SUBJ" cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
  }

  if {$type == "funct2subj" || $type == "funct2align"} {
    foreach parm { imagepatt slices reps xres yres regdat } {
      if { ![info exists functscanlists($page,$parm)] ||
           $functscanlists($page,$parm) == "-unset-" ||
           $functscanlists($page,$parm) == ""} {
        confirmalert "Register: missing parm ($parm) in Setup Funct Scan"
        return
      }
    }
    set fullmovdir $env(FUNCTIONALS_DIR)/$session/$iscandir
    set fullregdat $fullmovdir/$functscanlists($page,regdat)
    set movext [file extension $fullmovdir/$functscanlists($page,imagepatt)]
    if { $movext == ".BRIK"} {
      set fullmov $fullmovdir/$functscanlists($page,imagepatt)
      if ![file exists $fullmovdir/$functscanlists($page,imagepatt)] {
        confirmalert "Register: file to register not found:\n\
                      $fullmovdir/$functscanlists($page,imagepatt)"
        return
      }
      forcebrikMSBfirst [file rootname $fullmov] nowarn
      set briktypes [readheadbriktypes [file rootname $fullmov].HEAD]
      if [llength $briktypes] {  ;# none implies short 
        set targvoltype [lindex $briktypes $functscanlists($page,vregtargTR)]
        if { $targvoltype != "short" && $targvoltype != "float"} {
          confirmalert "Register: type=$targvoltype BRIK (req. short,float)"
          return
        }
      }
    } elseif { $movext == ".bshort" } {
      # TODO: check for existence of first bshort
    } elseif { $movext == ".mgz" } {
      set fullmov $fullmovdir/$functscanlists($page,imagepatt)
      if ![file exists $fullmovdir/$functscanlists($page,imagepatt)] {
        confirmalert "Register: file to register not found:\n\
                      $fullmovdir/$functscanlists($page,imagepatt)"
        return
      }
      # TODO: make functscan READ HEADER read mgz header
    } else {
      confirmalert "Register: suffix of Image Name Format not .BRIK/.bshort?\n\
                    (try reselect Image File, redo READ HEADER)"
    }
    if ![file exists $fullregdat] {
      writedefregdat $page
      confirmalert "Register: Funct->Struct Transform init'd (INIT button)"
    }
    set followarg ""
    set doublebufferarg ""
    set glxdeptharg ""
    if {$smallscreenflag}   { set followarg "-followglwinflag 0" }
    if {!$doublebufferflag} { set doublebufferarg "-doublebufferflag 0" }
    if {$minglxdepthflag}   { set glxdeptharg "-glxdepth 12" }
    set regoptions \
      "-movformat $functscanlists($page,imagepatt) \
       -nslices $functscanlists($page,slices) \
       -reps $functscanlists($page,reps) \
       -imres $functscanlists($page,xres) \
              $functscanlists($page,yres) \
       -blur 1 \
       -invert 1 \
       $followarg \
       $doublebufferarg \
       $glxdeptharg \
       -tr $functscanlists($page,vregtargTR) \
       -regdat [backslashspaces $fullregdat]"
    if {$type == "funct2subj"} {
      set command "$bindir/tkregister [backslashspaces $fullmovdir] \
        [backslashspaces $fulltargdir] $regoptions"
      runacmd \
        "$command" $funct2subjbu($page) "FUNCT=>SUBJ" cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
    }
  }
}

### COPY ALIGN... (Align panel), CP PREV,CP TO OTHERS (Funct panel) button cmds
proc cpregcmd { page type } {
  global name env session iscandir
  global sessionscanlists alignscanparms functscanlists
  global prevpage

  set iscandir $page
  # get source regdat, make list of target dirs
  if {$type == "cpalign2all"} {
    set sourceregdat \
      $env(FUNCTIONALS_DIR)/$session/$iscandir/$alignscanparms(regdat)
    set targlist ""
    set allfuncts [getfunctiscandirslist]
    foreach dir $allfuncts {
      if ![info exists sessionscanlists($dir,type)] { continue }
      if {$sessionscanlists($dir,type) != "functscan" &&
          $sessionscanlists($dir,type) != "extstatscan"} { continue }
      set aligndir $functscanlists($dir,aligndir)
      if {$aligndir == $iscandir} {
        lappend targlist $dir
      }
    }
    if ![llength $targlist] {
      confirmalert "Register: No Funct Dirs presently\
                  \nconfigured to use this Align Dir\
                \n\n...forgot to set Funct Dir field:\
                  \n\"Same-Plane Structural Dir\"?"
      return
    }
  }
  if {$type == "cpfromprev"} {
    if ![info exists functscanlists($prevpage,regdat)] {
      confirmalert \
        "Copy Transform: transform file not config'd for $prevpage\n\n\
         ...copy transform aborted"
      return
    }
    if {$page == "def"} {
      confirmalert "Register: No transform file to mod ...make default first"
      return
    }
    set sourceregdat \
     $env(FUNCTIONALS_DIR)/$session/$prevpage/$functscanlists($prevpage,regdat)
    set targlist $page
  }
  if {$type == "cpcurr2all"} {
    if ![info exists functscanlists($page,regdat)] {
      confirmalert \
        "Copy Transform: transform file not config'd for $page\n\n\
         ...copy transform aborted"
      return
    }
    set sourceregdat \
      $env(FUNCTIONALS_DIR)/$session/$page/$functscanlists($page,regdat)
    set targlist ""
    set allfuncts [getfunctiscandirslist]
    foreach dir $allfuncts {
      if ![info exists sessionscanlists($dir,type)] { continue }
      if {$sessionscanlists($dir,type) != "functscan" &&
          $sessionscanlists($dir,type) != "extstatscan"} { continue }
      if {$dir == $page} { continue }
      lappend targlist $dir
    }
    if ![llength $targlist] {
      confirmalert " Register: No Funct Dirs presently\n\
                     configured to copy this Funct to"
      return
    }
  }
  if { ![file exists $sourceregdat] } {
    confirmalert "Register: Can't find transform file to copy: $sourceregdat"
    return
  }

  # read source regdat
  set i 0
  set roundarg ""
  set id [open $sourceregdat r]
  foreach line [split [read $id] "\n"] {
    if {$i == 4} { set mat0 $line }
    if {$i == 5} { set mat1 $line }
    if {$i == 6} { set mat2 $line }
    if {$i == 7} { set mat3 $line }
    if {$i == 8} { set roundarg $line }
    incr i
  }
  close $id

  set printtarglist ""
  foreach dir $targlist {
    if {$type == "cpalign2all" && $dir == $page} { continue }
    set printtarglist "$printtarglist $dir\n"
    foreach parm { inplane thickness brightness blockcenteroffset } {
      if { $parm == "brightness" &&
           ![info exists functscanlists($dir,brightness)] } {
        set functscanlists($dir,brightness) 0.1
      }
      if { ![info exists functscanlists($dir,$parm)] ||
           $functscanlists($dir,$parm) == ""} {
        confirmalert "Copy Transform: parameter: $parm not found for $dir\n\n\
                       ...copy transform aborted"
        return
      }
    }
  }

  # allow cancel, else fix last column of matrix, write regdat into target dir
  if {$type == "cpalign2all"} { set srcdir $iscandir }
  if {$type == "cpcurr2all"} { set srcdir $iscandir }
  if {$type == "cpfromprev"}  { set srcdir $prevpage }
  set prrnd "float2int: tkregister (=floor)"
  if { [string match *round* $roundarg] } {set prrnd "float2int: round (=rint)"}
  if ![okreplace "" \
        "Copy Transform from:\n\n $srcdir\n\n to:\n\n$printtarglist\n$prrnd"\
        "Copy Transform"] {
    confirmalert "register.dat file(s) not altered"
    return
  } else {
    foreach targdir $targlist {
      if {$type == "cpalign2all" && $targdir == $page} { continue }
      set targregdat \
       $env(FUNCTIONALS_DIR)/$session/$targdir/$functscanlists($targdir,regdat)
      if [canwriteormakefile $targregdat] {
        if [file exists $targregdat] { mvlog $targregdat $targregdat~ }
        set mat0targ $mat0
        set mat1targ $mat1
        set mat2targ $mat2
        set mat3targ $mat3
        # 4x4 matrix is scale/rotate + translate for *centered* alignscan
        # add offset between block-centers to last col of functscan matrix
        if {$type == "cpalign2all"} {
          set doffset [expr $alignscanparms(blockcenteroffset) - \
                       $functscanlists($targdir,blockcenteroffset)]
        }
        if {$type == "cpcurr2all" || $type == "cpfromprev"} { ;#maybe different
          set doffset [expr $functscanlists($srcdir,blockcenteroffset) - \
                            $functscanlists($targdir,blockcenteroffset)]
        }
        for {set i 0} {$i < 4} {incr i} {
          for {set j 0} {$j < 4} {incr j} {
            set m($i,$j) [lindex [set mat$i] $j]
          }
        }
        set dx 0.0        ;# assume align/funct,funct/funct inplane-centered
        set dy $doffset
        set dz 0.0        ;# assume align/funct,funct/funct inplane-centered
        set x [expr $m(0,3) + $dx] 
        set y [expr $m(1,3) + $dy] 
        set z [expr $m(2,3) + $dz] 
        set mat0targ [format \
          "%13.6e %13.6e %13.6e %13.6e" $m(0,0) $m(0,1) $m(0,2) $x]
        set mat1targ [format \
          "%13.6e %13.6e %13.6e %13.6e" $m(1,0) $m(1,1) $m(1,2) $y]
        set mat2targ [format \
          "%13.6e %13.6e %13.6e %13.6e" $m(2,0) $m(2,1) $m(2,2) $z]
        set mat3targ [format \
          "%13.6e %13.6e %13.6e %13.6e" $m(3,0) $m(3,1) $m(3,2) $m(3,3)]
        set id [open $targregdat w 0644]
        puts $id "$name"
        puts $id "$functscanlists($targdir,inplane)"
        puts $id "$functscanlists($targdir,thickness)"
        puts $id "$functscanlists($targdir,brightness)"
        puts $id "$mat0targ"
        puts $id "$mat1targ"
        puts $id "$mat2targ"
        puts $id "$mat3targ"
        if { $roundarg != "" } { puts $id $roundarg }
        if { [string match *round* $roundarg] } {
          set functscanlists($targdir,initroundflag) 1
        } else {
          set functscanlists($targdir,initroundflag) 0
        }
        close $id
      } else {
        confirmalert "Transform: Can't write $targregdat  ...xform not copied"
        return
      }
    }
  }
}

### ALL=>T, CURR=>T button commands (Funct panel) to run AFNI 3dvolreg
proc 3dvolregcmd { page type } {
  global cmdlog vregall2selbu vregcurr2selbu
  global env session
  global functscanlists sessionscanlists
  global force afnibindir vregname datfile

  if [checkconcurrent] { return }  ;# stops 2nd volreg from another page

  if {$functscanlists($page,vregtargdir) == ""} {  ;# curr is default targ
    set functscanlists($page,vregtargdir) $page
  }
  set vregtargdir $functscanlists($page,vregtargdir)
  set vregtargTR $functscanlists($page,vregtargTR) ;# def1:mkpg def2:READ HEAD
  set maxTR [expr $functscanlists($vregtargdir,reps)-1]
  if {$vregtargTR < 0 || $vregtargTR >= $maxTR} {
    confirmalert \
     "3DAlign: Targ TR: $vregtargTR out of bounds (valid: 0-[expr $maxTR - 1])"
    return
  }

  if {$type == "vregall2sel"}  {
    set vregsrcdirlist ""
    foreach dir [getfunctiscandirslist] {
      if { [info exists sessionscanlists($dir,type)] &&
           $sessionscanlists($dir,type) == "functscan"} {
        lappend vregsrcdirlist $dir
      }
    }
    if [llength $vregsrcdirlist] {
      set tr1 $functscanlists([lindex $vregsrcdirlist 0],vregtargTR)
      foreach dir $vregsrcdirlist {
        if { $functscanlists($dir,vregtargTR) != $tr1 } {
          confirmalert "3DAlign: target TR for $dir:\
                    \n\n    $functscanlists($dir,vregtargTR)\
                    \n\ndoesn't match first target TR:\
                    \n\n    $tr1\
                    \n\nSet same target TR for all config'd scandirs"
          return
        }
      }
    }
  }
  if {$type == "vregcurr2sel"} {
    set vregsrcdirlist $page
  }
  foreach dir $vregsrcdirlist {
    if { ![string match *+orig.BRIK $functscanlists($dir,imagepatt)] } {
      confirmalert "3DAlign: requires bona fide *.BRIK's as inputs"
      return
    }
    if { [string match *-${vregname}*.BRIK $functscanlists($dir,imagepatt)] } {
      confirmalert " 3DAlign: input file:\
                     \n\n    $functscanlists($dir,imagepatt)\n\n\
                     in scandir:\
                     \n\n    $dir\n\n\
                  has infix indicating it was 3dvolreg'd (-${vregname})\n\n\n\
                     To Redo 3dvolreg: select non-3dvolreg'd input\n\
                     in Setup Align/Funct and READ HEADER\n\n\n\
                     (or if you just want to skip this input file,\n\
                     temporarily Unset scandir to ignore it for\n\
                     this 3DAlign)"
      return
    }
  }

  set printsrclist ""
  foreach dir $vregsrcdirlist { set printsrclist "$printsrclist $dir\n" }
  if ![okreplace \
     "" "3DVolumeRegister:\n\n$printsrclist\n\nto:\n\n $vregtargdir\n\
     (TR=$vregtargTR)" "3dvolreg"] {
    confirmalert "3dvolreg(s) aborted"
    return
  }

  ### conservative (in case it breaks something)
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog "3dvolreg: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  set fullsess $env(FUNCTIONALS_DIR)/$session
  set fulltargim $fullsess/$vregtargdir/$functscanlists($vregtargdir,imagepatt)
  set fulltargimstem [file rootname $fulltargim]       ;# strip .BRIK
  set fulltargimstemTR $fulltargimstem\[$vregtargTR\]  ;# add targ TR
  set firstsrcdir [lindex $vregsrcdirlist 0]
  set fullfirstsrc \
    $fullsess/$firstsrcdir/$functscanlists($firstsrcdir,imagepatt)
  if ![file exists $fulltargim] {
    confirmalert "3DAlign: $fulltargim (target funct image)\nnot found"
    return
  }
  if ![file exists $fullfirstsrc] {
    confirmalert "3DAlign: $fullfirstsrc (first funct to volreg)\nnot found"
    return
  }
  # full first out brik: strip also +orig, insert vreg, re-add +orig.BRIK
  set stemend [expr [string length $fulltargimstem] - 6]
  set firstout [string range $fulltargimstem 0 $stemend]-${vregname}+orig.BRIK
  if {!$force} {
    if { [file exists $firstout] } {
      if ![okreplace $firstout "$firstout exists--Redo 3dvolreg?" "Redo"] {
        confirmalert "3DAlign: BRIK file(s) not altered"
        return
      }
    }
  }

  # reg each to target TR (TODO: detect interrupt -- TODO: use new purple flag)
  foreach dir $vregsrcdirlist {
    cdlog $fullsess/$dir    ;# 3dvolreg reads anywhere, writes locally
    set inbrik $functscanlists($dir,imagepatt)
    set stemend [expr [string length $inbrik] - 11] ;# strip +orig.BRIK
    set outstem [string range $inbrik 0 $stemend]-${vregname}
    set outbrik ${outstem}+orig.BRIK
    set outhead ${outstem}+orig.HEAD
    if [file exists $outbrik] { rmlog $outbrik }  ;# so AFNI stays cmdline
    if [file exists $outhead] { rmlog $outhead }
    set functscanlists($dir,vregdfile) motion.1D  ;# was: $outstem.motion.1D
    set opts "-dfile $functscanlists($dir,vregdfile) -zpad 4"

    if { [info exists functscanlists($page,sliceorder)] &&
         $functscanlists($page,sliceorder) != "simul" } {
      putlog "3dvolreg: using slice-dependent time-offset correction"
      set opts "$opts -tshift 0" ;# slice-dependent time-offset correction
    }
    if {$functscanlists($page,vreg2passflag)} { set opts "$opts -twopass" }
    set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dvolreg \
        $opts -base [backslashspaces $fulltargimstemTR] \
        -prefix [backslashspaces $outstem] [backslashspaces $inbrik]"
   if {$type == "vregall2sel"}  {set bu $vregall2selbu($page); set nm "ALL=>T"}
   if {$type == "vregcurr2sel"} {set bu $vregcurr2selbu($page);set nm "CURR=>T"}
    runacmd "$command" $bu $nm cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    # next because Linux AFNI autoswaps MSBfirst to LSBfirst on output
    forcebrikMSBfirst [file rootname $outbrik] nowarn $bu $nm
    cdfunctscripts   ;# go back
  }

  # update each vreg'd Image Name Format, imagecombo currpage (only 1 of these)
  foreach dir $vregsrcdirlist {
    set inbrik $functscanlists($dir,imagepatt)
    set stemend [expr [string length $inbrik] - 11]  ;# strip +orig.BRIK
    set outstem [string range $inbrik 0 $stemend]-${vregname}
    # new inbrik: inherits non-reg'd functscan scan parms
    set functscanlists($dir,imagepatt) ${outstem}+orig.BRIK
    set functscanlists($dir,vregtargdir) $vregtargdir ;# override inconsistent
    set functscanlists($dir,vregtargTR) $vregtargTR   ;# same
  }
  fiximages $page functscan

  writearrayparms $datfile alignfunct
}

### run AFNI in tcl pwd, allow spaces in dyld/img paths (nbwin not yet used)
proc runafni { nbwin } {
  global env afnibindir

  # add path to fix afni crash on XQuartz w/newer MacOS 10.11+
  set dyld ""
  set addpath /opt/X11/lib/flat_namespace
  if { [exec uname] == "Darwin" && [file exists $addpath] } {
    set dyld "DYLD_LIBRARY_PATH=$env(DYLD_LIBRARY_PATH):$addpath"
  }  ;# backslash-quote to shell below b/c maybe spaces

  # conservative (in case it breaks something)
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog "runafni: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  # run AFNI in tcl pwd (emtpy $spacesOK resolves to space in $command)
  if {"$dyld" != ""} {  ;# backslash quote $dyld for possible space in DYLD
    set command "env $spacesOK AFNI_VERSION_CHECK=NO AFNI_ENFORCE_ASPECT=YES \
      \"$dyld\" $afnibindir/afni"
  } else {  ;# omit empty $dyld w/explicit quotes: it is empty arg, *not* space
    set command "env $spacesOK AFNI_VERSION_CHECK=NO AFNI_ENFORCE_ASPECT=YES \
      $afnibindir/afni"
  }
  putlog "$command &"
  eval exec $command &
}

### AFNI button on Setup Functional Scan panels): N.B.: cd's to curr scandir!
proc afnicmd { nbwin } {
  if [checkconcurrent] { return } ;#don't cd somewhere w/bg (afni) proc running
  cdscandir  ;# logs the cd
  runafni $nbwin
  cdfunctscripts
}

### AFNI-ALL button Setup Functional Scan: mklinks/viewall BRIKs: N.B.: cd's!
proc afniallcmd { nbwin } {
  global env session tmpafnidir

  if [checkconcurrent] { return }
  if ![file exists $tmpafnidir] {
    mkdirlog $tmpafnidir
    eval exec chmod go+rwx $tmpafnidir  ;# so other user can rm old links
  }
  if ![file exists $tmpafnidir] {
    confirmalert "Make links for AFNI failed:\n\n    can't create $tmpafnidir"
    return
  }
  if ![canwriteormakefile $tmpafnidir/asdf] {
    confirmalert "Make links for AFNI failed:\n\n    can't write in $tmpafnidir"
    return
  }

  cdlog $tmpafnidir
  set i 0
  foreach file [glob -nocomplain $tmpafnidir/*] { rmlog $file }
  set briklist \
    [lsort [glob -nocomplain $env(FUNCTIONALS_DIR)/$session/image/*/*.BRIK]]
  foreach brikfile $briklist {
    set uniqid s[format "%03d" $i]  ;# multiple cross scan avgs may overlap
    set headfile [file rootname $brikfile].HEAD
    lnslog $brikfile $uniqid-[file tail $brikfile]
    lnslog $headfile $uniqid-[file tail $headfile]
    incr i
  }
  runafni $nbwin
  cdfunctscripts
}

### AFNI on Setup Structural Scan panel: N.B.: cd's to curr struct dir!
proc afnicmdstruct { nbwin } {
  global env name program tmpdir

  if [checkconcurrent] { return }
  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  set fullrawdir $env(SUBJECTS_DIR)/$name/mri/orig/$page
  if ![file exists $fullrawdir] { set fullrawdir $tmpdir }
  if ![file isdirectory $fullrawdir] { set fullrawdir $tmpdir }

  cdlog $fullrawdir
  wm title . "$program -- $fullrawdir"
  runafni $nbwin
  cdsubjectscripts
}

### COMBINE button command (Combine 3D Raw Images panel)
proc rawaveragecmd { nbwin } {   ;# one raw scan per indir
  global env session iscandir
  global cmdlog rawaveragebu
  global functscanlists
  global force bindir afnibindir datfile boundsfile paradigmdefdir

  if [checkconcurrent] { return }
  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  set iscandir $page

  # check rawoperation, enough dirs, parm
  if { $functscanlists($page,rawoperation) != "average" &&
       $functscanlists($page,rawoperation) != "concat" } {
    confirmalert "Raw Combine: first select Operation (average/concat)"
    return
  }
  if { [llength $functscanlists($page,rawtoavgdirs)] < 2 &&
        $functscanlists($page,rawoperation) != "average" } {  ;# maybe rev one
    confirmalert "Raw Combine: first select at least 2 dirs to average"
    return
  }
  if { ![info exists functscanlists($page,revtTRs)] ||
       $functscanlists($page,revtTRs) == "-unset-" ||
       $functscanlists($page,revtTRs) == ""} {
    confirmalert " Raw Combine: bad/missing parm:\n\n    Time Offset of Rev'd"
    return
  }

  # check infile parms
  set parmlist \
      { imagepatt slices xres yres reps inplane thickness \
        paintdmin paintdmax paintdstep paintnormop paintnormtype \
        regdat brightness }
  if {$functscanlists($page,rawoperation) == "concat"} {
    lappend parmlist vregdfile
  }
  foreach dir $functscanlists($page,rawtoavgdirs) {
    foreach parm $parmlist {
      if { ![info exists functscanlists($dir,$parm)] ||
           $functscanlists($dir,$parm) == "-unset-" ||
           $functscanlists($dir,$parm) == ""} {
        confirmalert \
          " Raw Combine: failed\n Parm(s) missing from Setup Funct Scan\n\
            (first missing: $parm)\n\n\
            (if older session, make sure input scandir config'd:\n\
            SessionTools -> Setup Align/Funct, Save/Close)"
        return
      }
    }
  }
  foreach dir $functscanlists($page,rawtoavgdirs) {
    set stem [gettimeseriesinputstem $dir $functscanlists($dir,imagepatt)]
    if {$stem == "badsuffix" || $stem == "firstnotfound"} { return }
  }

  # check 1st-to-avg dir regdat 
  set firstdir [lindex $functscanlists($page,rawtoavgdirs) 0]
  set fullsess $env(FUNCTIONALS_DIR)/$session
  set fullfirstregdat $fullsess/$firstdir/$functscanlists($firstdir,regdat)
  if ![info exists functscanlists($page,regdat)] {  ;# copy others after
    set functscanlists($page,regdat) $functscanlists($firstdir,regdat)
  }
  set fullregdat $fullsess/$iscandir/$functscanlists($page,regdat)
  if [file exists $fullfirstregdat] {
    cplog $fullfirstregdat $fullregdat
  } else {
    confirmalert "Raw Combine: Can't copy Transform file to $page:\
              \n\n$functscanlists($firstdir,regdat) not found in 1st inp dir:\
              \n\n    $firstdir\
              \n\nDo manual register or COPY ALIGN TO ALL FUNCTS"
    return
  }

  # check concat paradigm dirs, block abspaths, else set default
  if {$functscanlists($page,rawoperation) == "concat"} { ;# def for concat only
    set found 0
    foreach rawtoavgdir $functscanlists($page,rawtoavgdirs) {
      if ![info exists functscanlists($rawtoavgdir,paradigmdir)] {
        set functscanlists($rawtoavgdir,paradigmdir) $paradigmdefdir
      }
      if [string match /* functscanlists($rawtoavgdir,paradigmdir)] {incr found}
    }
    ### block all abspath paradigm dirs
    if {$found} {
      confirmalert "Raw Combine: found $found absolute-path Paradigm Dir's:\
                \n\nHOWTO fix:\
                  \n  For each scandir with absolute path:\
                  \n    (1) change Paradigm Dir to relative (e.g., \"stim1Ds\")\
                  \n    (2) create that dir within scandir\
                  \n    (3) copy corresponding 1D files into it\
                  \n    (4) redo Concat"
      return
    }
    lappend parmlist paradigmdir
  }

  foreach parm $parmlist {
    set functscanlists($page,$parm) $functscanlists($firstdir,$parm)
  }
  set avgoutdir $env(FUNCTIONALS_DIR)/$session/$iscandir
  set pattstem [file rootname $functscanlists($page,imagepatt)] ;# firstdirname
  set pattext [file extension $functscanlists($page,imagepatt)]

  # catch time reverse or time delay w/concat
  if {$functscanlists($page,rawoperation) == "concat"} {
    foreach rev $functscanlists($page,rawtoavgrevs) {
      if {$rev == "on"} {
        confirmalert "Raw Combine: Can't time-reverse concatenated scans"
        return
      }
    }
    if {$functscanlists($page,revtTRs) != 0} {
      confirmalert "Raw Combine: Can't time-delay concatenated scans"
      return
    }
  }

  # check int num TRs
  if ![string is integer $functscanlists($page,revtTRs)] {
    confirmalert "Raw Combine: Num TRs to shift:\
              \n\n    $functscanlists($page,revtTRs)\
              \n\nnot integer  ...fix and re-run"
    return
  }

  # check overwrite, average or concat
  if {$functscanlists($page,rawoperation) == "average"} {
    if {$pattext == ".bshort"} {  }  ;# TODO: check bshort *input* logic
    if {$pattext == ".BRIK"} {       ;# copy rawaverage output
      set firstdir [lindex $functscanlists($page,rawtoavgdirs) 0]
      set functscanlists($page,imagepatt) $functscanlists($firstdir,imagepatt)
      set outbrik $avgoutdir/$functscanlists($firstdir,imagepatt) ;#concat diff
      if {!$force} {
        if { [file exists $outbrik] } {
          if ![okreplace $outbrik "$outbrik exists--Redo Concat?" "Redo"] {
            confirmalert "Raw Combine: files not altered"
            return
          }
        }
      }
    }
    if {$pattext == ".brik"} {
      confirmalert "Raw Combine: rawaverage doesn't support headerless .brik\
                \n\nRename .BRIK's and make .HEAD files (with to3d or manually)"
      return
    }
    #TODO: overwrites bshorts without asking (rawaverage biffs BRIK, too)
  }
  if {$functscanlists($page,rawoperation) == "concat"} {
    if {$pattext != ".BRIK"} {
      confirmalert "Raw Combine: operation \"concatenate\" only works on BRIKs"
      return
    }
    set avgoutname [file tail $iscandir] ;#mk better name: firstscan=>rawavgdir
    set functscanlists($page,imagepatt) ${avgoutname}+orig.BRIK
    set outbrik $avgoutdir/${avgoutname}+orig.BRIK
    set outhead $avgoutdir/${avgoutname}+orig.HEAD
    if {!$force} {
      if { [file exists $outbrik] } {
        if ![okreplace $outbrik "$outbrik exists--Redo Concat?" "Redo"] {
          confirmalert "Raw Combine: files not altered"
          return
        }
      }
    }
    rmlog $outbrik
    rmlog $outhead
  }

  # conservative (in case it breaks something)
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog "rawavg: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

#xxx -- forcebrik should be OK w/spaces till call out
#xxx -- try to get swap prob on just analyze avg, see if fixes (prob was AFNI!)
#  # re-run forceMSB just in case!
#  foreach dir $functscanlists($page,rawtoavgdirs) {
#    set fullbrik \
#      $env(FUNCTIONALS_DIR)/$session/$dir/$functscanlists($dir,imagepatt)
#    #forcebrikMSBfirst \
#      [file rootname $fullbrik] nowarn $calcfourbu "COMBINE    " ;# 190725
#  }

  ### average by rawaverage
  if {$functscanlists($page,rawoperation) == "average"} {
    set intercalatedlist ""
    foreach dir $functscanlists($page,rawtoavgdirs) {
      lappend intercalatedlist $env(FUNCTIONALS_DIR)/$session/$dir
      lappend intercalatedlist $functscanlists($dir,imagepatt)
    }
    # optional revlist for rawaverage
    set revlist ""
    foreach rev $functscanlists($page,rawtoavgrevs) {
      if {$rev == "on"}                     { lappend revlist 1 }
      if {$rev == "off" || $rev == "none"}  { lappend revlist 0 }
    }
    set revopts ""
    if [llength $functscanlists($page,rawtoavgrevs)] {
      set revopts "-revt $revlist -shiftrev $functscanlists($page,revtTRs)"
    }
    set command "$bindir/rawaverage \
      $revopts \
      -nslices $functscanlists($page,slices) \
      -reps $functscanlists($page,reps) \
      -imres $functscanlists($page,xres) $functscanlists($page,yres) \
       [lbackslashspaces $intercalatedlist] [backslashspaces $avgoutdir]"
    #set avgoutname [lindex $intercalated 1] ;# what rawaverage generates
  }

  ### else concat (AFNI 3dTcat), create bounds, concat motion.1D's, stim.1D's
  if {$functscanlists($page,rawoperation) == "concat"} {
    ## 3dTcat
    set compoundlist ""
    foreach dir $functscanlists($page,rawtoavgdirs) {
      set pattstem [file rootname $functscanlists($dir,imagepatt)]
      lappend compoundlist $env(FUNCTIONALS_DIR)/$session/$dir/$pattstem
    }
    set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dTcat \
      -output [backslashspaces $avgoutdir]/$avgoutname \
      [lbackslashspaces $compoundlist] -verb"
    ## create bounds file
    set fullboundsfile $env(FUNCTIONALS_DIR)/$session/$iscandir/$boundsfile
    if [file exists $fullboundsfile] { rmlog $fullboundsfile }
    set id [open $fullboundsfile w 0644]
    set nextTR 0
    foreach dir $functscanlists($page,rawtoavgdirs) {
      puts $id $nextTR
      set nextTR [expr $nextTR + $functscanlists($dir,reps)]
    }
    close $id
    set functscanlists($page,reps) $nextTR
    set functscanlists($page,concatfiles) \
      [llength $functscanlists($page,rawtoavgdirs)]
    ## concat motion.1D's if there
    set fullmotion1Dlist ""
    set concatcnt 0
    foreach rawtoavgdir $functscanlists($page,rawtoavgdirs) {
      set fullmotion1D \
        $fullsess/$rawtoavgdir/$functscanlists($rawtoavgdir,vregdfile)
      if [file exists $fullmotion1D] { lappend fullmotion1Dlist $fullmotion1D }
      incr concatcnt
    }
    if { [llength $fullmotion1Dlist] == $concatcnt } {
      set fullmotion1Dout $fullsess/$iscandir/$functscanlists($page,vregdfile)
      eval exec "cat $fullmotion1Dlist > $fullmotion1Dout"
      putlog "cat $fullmotion1Dlist > $fullmotion1Dout"  ;# runacmd can't redir
    } else {
      confirmalert "Raw Combine: number dirs, motion.1D's doesn't match:\n\n\
                    $concatcnt dirs\n\
                    [llength $fullmotion1Dlist] motion.1D files"
    }
    if ![llength $fullmotion1Dlist] {putlog "### concat: no motion.1D's found"}
    ## concat stim1Ds if non-first rawtoavgdirs have match to <stem>?.1D
    set fullparadigmdir $fullsess/$page/$functscanlists($page,paradigmdir)
    if ![file exists $fullparadigmdir] { mkdirlog $fullparadigmdir }
    set fullfirstrawtoavgdir \
      $fullsess/[lindex $functscanlists($page,rawtoavgdirs) 0]
    set firststim1Dsdir \
      $fullfirstrawtoavgdir/$functscanlists($page,paradigmdir)
    set fullfirststim1Dslist [glob -nocomplain $firststim1Dsdir/*.1D]
    foreach fullfirststim1D $fullfirststim1Dslist {
      set firststim1D [file tail $fullfirststim1D]
      set firststim1Dpatt [string range $firststim1D 0 \
        [expr [string length $firststim1D] - 5]]?.1D ;# req: <stem>[1-9].1D
      set fullstim1Dslist ""
      foreach rawtoavgdir $functscanlists($page,rawtoavgdirs) {
        set fullstim1Ddir \
          $fullsess/$rawtoavgdir/$functscanlists($rawtoavgdir,paradigmdir)
        set fullstim1Dpatt $fullstim1Ddir/$firststim1Dpatt
        set fullstim1D [glob -nocomplain $fullstim1Dpatt]
        if { [llength $fullstim1D] != 1 } {
          confirmalert " Raw Combine (working on $rawtoavgdir):\n\n\
                         no files (or >1) match this pattern:\n\
                         $fullstim1Dpatt\n\n\
                         further paradigm file concatenation aborted\n\
                         (paradigm file named incorrectly?)"
          return
        }
        lappend fullstim1Dslist $fullstim1D
      }
      set firststim1D [string range $firststim1D 0 \
        [expr [string length $firststim1D] - 5]]C.1D  ;# repl scannum w/"C"
      set fullstim1Dout \
        $fullsess/$iscandir/$functscanlists($page,paradigmdir)/$firststim1D
      eval exec "cat $fullstim1Dslist > $fullstim1Dout"
      putlog "cat $fullstim1Dslist > $fullstim1Dout"
    }
  } ;# end concat

  runacmd "$command" $rawaveragebu "COMBINE  " cmdinput $cmdlog cmdpid
  tkwait variable cmdpid

  set functscanlists($page,rawavgfilepatt) $functscanlists($page,imagepatt)

  writearrayparms $datfile rawavg
}

### FOURIER button command (Calculate 3D Fourier Stats panel)
proc fouriercmd { nbwin } {
  global env session iscandir
  global cmdlog calcfourbu
  global functscanlists
  global realname complexname realfname realfclustname
  global force bindir afnibindir datfile

  if [checkconcurrent] { return }
  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  set iscandir $page

  if ![info exists functscanlists($page,imagepatt)] {
    confirmalert " Fourier: first select Image File, READ HEADER \
                   in Setup Functional Scans"
    return
  }
  if { ![info exists functscanlists($page,stattype)] ||
        $functscanlists($page,stattype) != "complex"} {
    set functscanlists($page,stattype) complex
  }

  # conservative (in case it breaks something)
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog "fourier: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  # setup strings
  set stem [gettimeseriesinputstem $page $functscanlists($page,imagepatt)]
  if {$stem == "badfunctsuffix" || $stem == "firstnotfound"} { return }
  set phasestatformat $functscanlists($page,phasestatformat)
  # ugly: bfloatpatt's passed to {sigaverage,paint}cmd lack _r,_i etc infixes
  if {$phasestatformat == "bfloat"} {
    set functscanlists($page,bfloatpatt) ${stem}_%03d.bfloat ;# paint,sigavg
  }
  if {$phasestatformat == "afnibrik"} {
    set functscanlists($page,bfloatpatt) ${stem}+orig.BRIK   ;# paint,sigavg
  }
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir

  # maybe force MSB
  set brikflag 0
  if { [file extension $fullscandir/$functscanlists($page,imagepatt)] == \
       ".BRIK" } { set brikflag 1 }
  if {$brikflag} {
    forcebrikMSBfirst \
      [file rootname $fullscandir/$functscanlists($page,imagepatt)] nowarn \
      $calcfourbu "FOURIER  "
  }

  # check output
  set fullstem $fullscandir/$stem
  set infixlist "$realname $complexname"
  set infix [lindex $infixlist 0]
  if {$phasestatformat == "bfloat"} {
    set firstout ${fullstem}${infix}_000.bfloat
  }
  if {$phasestatformat == "afnibrik"} {
    set firstout ${fullstem}${infix}+orig.BRIK ;# N.B. 2nd +orig (stem has one)
  }
  if {!$force} {
    if { [file exists $firstout] } {
      if ![okreplace $firstout "$firstout exists--Redo Fourier?" "Redo"] {
        if {$phasestatformat == "bfloat"} { set existing "bfloat" }
        if {$phasestatformat == "afnibrik"} { set existing "BRIK" }
        confirmalert "Fourier: $existing files not altered"
        return
      }
    }
  }

  # check panel filled out (addfourscan already defaults more than this)
  foreach parm { stimcycles lofreqwin hifreqwin omitfreq meandelay \
                 preclustfthr clustarea \
                 fixileaveflag useTAXISflag inclharm23flag \
                 clusterrad clustervol \
                 smoothfwhm permtestcnt \
                 rh,truncphasemin lh,truncphasemin \
                 rh,truncphasemax lh,truncphasemax \
                 filetruncphaseflag truncslope \
                 phasestattype } {
    if { ![info exists functscanlists($page,$parm)] ||
         $functscanlists($page,$parm) == ""} {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }
  foreach parm { imagepatt slices reps xres yres TR } { ;# warn
    if { ![info exists functscanlists($page,$parm)] ||
         $functscanlists($page,$parm) == "-unset-" ||
         $functscanlists($page,$parm) == ""} {
      confirmalert "Fourier: missing parm ($parm) in Setup Funct,Fourier Scan"
      return
    }
  }

  # block/warn non-integer cycles
  if ![string is integer $functscanlists($page,stimcycles)] {
    confirmalert "Fourier: Stim Cycles Per Scan:\
              \n\n    $functscanlists($page,stimcycles)\
              \n\nnot integer  ...fix and re-run"
    return
  }

  # block -slicetiming if multiband set and !=1, or not-set-or-empty
  if {$functscanlists($page,fixileaveflag)} {
    if { [info exists functscanlists($page,mbaccel)] &&
         $functscanlists($page,mbaccel) != "" &&
         $functscanlists($page,mbaccel) != 1} {
      confirmalert "Fourier: \"UseSliceOrd\" doesn't work (yet) with multiband:\
                \n\nUntick it or tick \"UseTAXIS\" instead"
      return
    }
    if { ![info exists functscanlists($page,mbaccel)] ||
         $functscanlists($page,mbaccel) == ""} {
      confirmalert "Fourier: \"Multiband Accel Factor\" not set or empty\
                  \n(on Setup Align/Funct panel)\
                \n\n\"UseSliceOrd\" doesn't work (yet) with multiband so\
                  \ndo one of the following on Setup Align/Funct:\
                \n\n   (1) set Multiband Accel Factor to 1\
                  \n   (2) untick Fourier panel \"UseSliceOrd\"\
                  \n   (3) use Fourier panel \"UseTAXIS\" instead"
      return
    }
  }

  # check taxisoffsets valid (or exists)
  if {$functscanlists($page,useTAXISflag)} {
    if [info exists functscanlists($page,taxisoffsets)] {
      set taxislen [llength $functscanlists($page,taxisoffsets)]
      if { $taxislen != $functscanlists($page,slices) } {
        confirmalert "Fourier: \"UseTAXIS\":\
                  \n\n    \"Slice Time Offsets List\" length (=$taxislen)\
                    \n      (N.B.: on Setup Align/Funct panel)\
                  \n\ndoesn't match:\
                  \n\n    slice count (=$functscanlists($page,slices))"
        return
      }
    } else {
      confirmalert "Fourier: \"UseTAXIS\":\
                \n\n    \"Slice Time Offsets List\" is empty\
                \n\nREAD HEADER (or manually enter) on Setup Align/Funct panel"
      return
    }
  }

  # optional 3D pre-smooth (surprisingly damaging!) req's presmooth > def=0.0
  set fullimagepatt $fullscandir/$functscanlists($page,imagepatt)
  set fwhm $functscanlists($page,smoothfwhm)
  if {$fwhm > 0.0} { ;# AFNI: strip +orig.BRIK, fourier: add back to imagepatt
    if {!$brikflag} {
      confirmalert "Fourier: 3D smooth requires BRIK input"
      set functscanlists($page,smoothfwhm) 0.0
      return
    }
    set datastem \
     [string range $fullimagepatt 0 [expr [string length $fullimagepatt] - 11]]
    set unsmootheddatastem $datastem
    set datastem $datastem-sm[format "%2.1f" $fwhm]
    set smoothhead $datastem+orig.HEAD  ;# full smoothed output
    set smoothbrik $datastem+orig.BRIK
    if { [file exists $smoothhead] || [file exists $smoothbrik] } {
      rmlog $smoothhead  ;# always redo
      rmlog $smoothbrik
    }
    # AFNI cmdline: instem *needs* "+orig", outstem doesn't: auto-appended
    set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dmerge \
                   -verbose \
                   -1blur_fwhm $fwhm \
                   -doall \
                   -prefix [backslashspaces $datastem] \
                   [backslashspaces $unsmootheddatastem+orig]"  ;# input stem
    cdscandir
    runacmd "$command" $calcfourbu "FOURIER  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    forcebrikMSBfirst $datastem+orig nowarn $calcfourbu "FOURIER  " ;# 160608
    cdfunctscripts
    if [file exists $smoothbrik] {
      confirmalert "Fourier: 3D pre-smooth finished:\
                \n\nN.B.: pre-smoothing is surprisingly damaging to Fourier\
                  \nanalysis of topological mapping data since adjacent\
                  \nvoxels will typically differ markedly in phase\
                \n\nOnly recommended if analyzing block design data w/Fourier"
      set fullimagepatt $smoothbrik
    } else {
     confirmalert "Fourier: 3D pre-smooth failed:\n\n  $smoothbrik\n\nnot found"
      return
    }
  }

  # setup cmdline args
  set sliceorderarg ""
  if {$functscanlists($page,fixileaveflag)} {
    # assume not sparse (TODO: allow interslicetime < TR/slices => sparse)
    set interslicetime \
      [expr $functscanlists($page,TR)/$functscanlists($page,slices).0]
    set sliceorder $functscanlists(def,sliceorder)
    #set sliceorderarg \
    #  "-fixileave $sliceorder $interslicetime $functscanlists($page,TR)"
    set sliceorderarg \
      "-slicetiming $sliceorder $interslicetime $functscanlists($page,TR)"
  }
  if {$functscanlists($page,useTAXISflag)} {
    set sliceorderarg "-taxisoffsets \
      $functscanlists($page,TR) $functscanlists($page,taxisoffsets)"
  }
  if {$functscanlists($page,phasestattype) == "sqrt-F"} { set phaseoptarg 0 }
  if {$functscanlists($page,phasestattype) == "p-val"}  { set phaseoptarg 1 }
  if {$functscanlists($page,phasestattype) == "p-FA"}   { set phaseoptarg 2 }
  set inclharmopt ""
  if {$functscanlists($page,inclharm23flag)} { set inclharmopt "-inclharm23" }
  set brikoutopt ""  ;# empty=bfloat (N.B.: no 3D _f stats w/bfloat
  if {$phasestatformat == "afnibrik"} {set brikoutopt "-sigoutbrik -fout"}
  set fullFTopts ""
  if {$functscanlists($page,fullfourierflag)} {
    set fullFTopts "-fullfourier -fullfouramp"  ;# 4+2 = 6x as big as raw
  }

  # go (imres=64,statres=128 => files binary equiv to orig 128x128 analyse)
  set command "$bindir/fourier \
    [backslashspaces $fullimagepatt] [backslashspaces $fullstem] \
    -nslices $functscanlists($page,slices) \
    -reps $functscanlists($page,reps) \
    -imres $functscanlists($page,xres) $functscanlists($page,yres) \
    -statres $functscanlists($page,xres) $functscanlists($page,yres) \
    -stimcyc $functscanlists($page,stimcycles) \
    -infixes $realname $complexname \
    $inclharmopt \
    -freqsurr $functscanlists($page,lofreqwin) \
              $functscanlists($page,hifreqwin) \
    -omitfreq $functscanlists($page,omitfreq) \
    -permtestcnt $functscanlists($page,permtestcnt) \
    -meandelay $functscanlists($page,meandelay) \
    -phasetype $phaseoptarg \
    $brikoutopt \
    $fullFTopts \
    $sliceorderarg"
  runacmd "$command" $calcfourbu "FOURIER  " cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
  # outfiles: 3D volumes: _r,_i,_f

  # feedback, record, prompt PAINT (N.B.: bfloatpattinf no longer packed)
  if {$phasestatformat == "bfloat"} {
    set functscanlists($page,bfloatpattinf) \
       ${stem}{$realname,$complexname}_%03d.bfloat
  }
  if {$phasestatformat == "afnibrik"} {
    set functscanlists($page,bfloatpattinf) \
       ${stem}{$realname,$complexname}+orig.BRIK
  }
  set functscanlists($page,angle_offset1sec) \
    [expr double($functscanlists($page,stimcycles)) / \
     (double($functscanlists($page,reps)) * double($functscanlists($page,TR)))]
  set functscanlists($page,rh,wfile) -runpaint-
  set functscanlists($page,lh,wfile) -runpaint-

  ### 3d clust (3dmerge) for brainstem: cluster{rad/vol},preclustfthr
  if {$phasestatformat != "afnibrik"} {
    if {!$force} {confirmalert "Fourier: 3D clustreq's Stat Format: afnibrik"}
  } elseif { $functscanlists($page,clustervol) == 0 } {
    if {!$force} {confirmalert "Fourier: 3D clustering skipped"}
  } else {
    set inbrik  ${fullstem}${realfname}+orig.BRIK ;# N.B. 2nd +orig (also stem)
    set outhead ${fullstem}${realfclustname}+orig.HEAD
    set outbrik ${fullstem}${realfclustname}+orig.BRIK
    set tmphead $fullscandir/TmpClustMask+orig.HEAD
    set tmpbrik $fullscandir/TmpClustMask+orig.BRIK
    if ![file exists $inbrik] {
      if {!$force} {
        confirmalert "Fourier: Input to 3D Cluster:\n\n    $inbrik\n\nmissing"
      }
    } else {
      if [file exists $tmphead] { rmlog $tmphead } ;# AFNI won't overwrite
      if [file exists $tmpbrik] { rmlog $tmpbrik }
      if [file exists $outhead] { rmlog $outhead }
      if [file exists $outbrik] { rmlog $outbrik }
      ## make tmp binary clustermask from F-stats file
      set nonegarg ""  ;# allow neg (vs. -1noneg), -1clip arg =>0 in (-arg,arg)
      ## -1clust => just clip, -1clust_order => num clusters in order of size
      set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dmerge \
        $nonegarg \
        -dxyz=1 \
        -verbose \
        -1clust $functscanlists($page,clusterrad) \
                $functscanlists($page,clustervol) \
        -1clip $functscanlists($page,preclustfthr) \
        -prefix [file rootname $tmpbrik] \
        [file rootname $inbrik]"
      runacmd "$command" $calcfourbu "FOURIER  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
      ## use it to filter stats: _f => _h (step(b) for numbered clusts)
      #N.B.: left unneeded +orig on output (-prefix) (same with or without)
      set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
        -a [backslashspaces [file rootname $inbrik]] \
        -b [backslashspaces [file rootname $tmpbrik]] \
        -expr \"step(b)*a\" \
        -prefix [file rootname $outbrik]"
      runacmd "$command" $calcfourbu "FOURIER  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
      forcebrikMSBfirst [file rootname $outbrik] nowarn $calcfourbu "FOURIER  "
      ## cleanup -- leave TmpClustMask+orig.BRIK for inspection
      #rmlog $tmpbrik
      #rmlog $tmphead
    }
  }

  writearrayparms $datfile calcfour
}

### DECONVOLVE button command (Calculate 3D Rand Block Stats panel)
proc deconvcmd { nbwin } {
  global env session iscandir
  global cmdlog calcrandbu
  global functscanlists
  global force afnibindir datfile simplediffsflag
  global boundsfile afnistatsinfix parasuff genlintestmatdir deconvscript

  if [checkconcurrent] { return }
  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  set iscandir $page

  if { ![info exists functscanlists($page,stattype)] ||
       $functscanlists($page,stattype) != "paradigm" } { return }
  if ![info exists functscanlists($page,imagepatt)] {
    confirmalert "Deconvolve: first select Image File and READ HEADER\
                \nin Setup Functional Scans"
    return
  } 
  set databrik $functscanlists($page,imagepatt)
  set ext [file extension $databrik]
  if { $ext != ".BRIK" } {
    confirmalert "Deconvolve: bad suffix: $ext\n\n...only works on BRIKs"
    return
  }

  ## check input suffix (always unsmoothed)
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  if ![file exists $fullscandir/$databrik] {
    confirmalert "Deconvolve: input file:\n\n    $databrik\n\nnot found"
    return
  }
  if { ![info exists functscanlists($page,reps)] ||
       $functscanlists($page,reps) == 0 } {
    confirmalert "Deconvolve: reps undefined:\
                \nSetup Align/Funct Scans for \"$page\",\
                \nor re-concat"
    return
  }

  ## check parms exist
  foreach parm { condnames paradigmdir maxlag TR maxlag \
                 vregdfile vregregressflag } {
    if { ![info exists functscanlists($page,$parm)] ||
         $functscanlists($page,$parm) == "-unset-" ||
         $functscanlists($page,$parm) == ""} {
      if {$parm == "condnames"} { set parm "Condition Names" }
      if {$parm == "vregdfile"} { set parm "Motion Params File" }
      confirmalert "Deconvolve: failed\
                \n\nParm(s) missing from Setup Funct Scan\
                \n\n(first missing parm: $parm)"
      return
    }
  }

  ## block abspath paradigmdir's (no longer supported)
  if [string match /* $functscanlists($page,paradigmdir)] {
    confirmalert "Deconvolve: absolute-path Paradigm Dir no longer supported:\
              \n\nHOWTO fix:\
                \n  (1) change Paradigm Dir to relative (e.g., \"stim1Ds\")\
                \n  (2) manually create that dir within this scandir\
                \n  (3) copy corresponding 1D files into it\
                \n  (4) redo DECONVOLVE"
    return
  }

  ## check output (maybe presmoothed), if redo, rm for AFNI
  set datastem [string range $databrik 0 [expr [string length $databrik] - 11]]
  set unsmootheddatastem $datastem ;# input *needs8 +orig, prefix does *not*
  set fwhm $functscanlists($page,smoothfwhm)
  if {$fwhm > 0.0} { set datastem $datastem-sm[format "%2.1f" $fwhm] }
  set statsbrik $fullscandir/${datastem}-${afnistatsinfix}+orig.BRIK
  set statshead $fullscandir/${datastem}-${afnistatsinfix}+orig.HEAD
  if { [file exists $statsbrik] || [file exists $statshead] } {
    if { $functscanlists($page,deconvtype) != "test" } {
      if {!$force} {
        if ![okreplace $statsbrik "$statsbrik exists--Redo Deconvolve?" \
            "Redo"] {
          confirmalert "Deconvolve: stats brik/head not altered"
          return
        }
      }
      rmlog $statshead
      rmlog $statsbrik
    }
  }

  ### conservative (in case it breaks something) -- omit b/c local!
  #set spacesOK ""
  #if [string match "* *" $env(FUNCTIONALS_DIR)] {
  #  putlog "deconv: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
  #  set spacesOK AFNI_PATH_SPACES_OK=YES
  #}

  ## maybe pre-smooth
  if {$fwhm > 0.0} {
    set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dmerge \
                   -1blur_fwhm $fwhm \
                   -doall \
                   -prefix $datastem \
                   $unsmootheddatastem+orig"
    # N.B.: LSB output on Intel accepted by 3dDeconvolve
    cdscandir       ;# tmp go local
    runacmd "$command" $calcrandbu "DECONVOLVE  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    cdfunctscripts  ;# back to def loc
  }

  ## make general linear test matrices
  if ![mkgenlintestmats $page] { return }

  ## stim args
  set stmlist ""
  set condnum 0
  set paradigmdir $functscanlists($page,paradigmdir)  ;# now req rel
  #if { [string first $fullscandir $paradigmdir] == 0 } {  ;# maybe trim abs
  #  set paradigmdir \
  #    [string range $paradigmdir [expr [string length $fullscandir] + 1] end]
  #}
  foreach cond $functscanlists($page,condnames) {
    incr condnum
    set stmlist "$stmlist \
      -stim_file $condnum $paradigmdir/$cond.$parasuff \
      -stim_label $condnum \"$cond\" \
      -stim_maxlag $condnum $functscanlists($page,maxlag)"
  }
  set motnum 0
  if { $functscanlists($page,vregregressflag) } {
    foreach motname { Roll Pitch Yaw dS dL dP } {
      incr condnum
      incr motnum
      set stmlist "$stmlist \
        -stim_file $condnum $functscanlists($page,vregdfile)\[$motnum\] \
        -stim_label $condnum \"$motname\""
    }
  }
  set stms $condnum

  ## glt args
  set gltlist ""
  set condnum 0
  foreach cond $functscanlists($page,condnames) {
    incr condnum
    set gltlist "$gltlist \
      -glt 1 $genlintestmatdir/$cond.mat \
      -glt_label $condnum \"$cond\""
  }
  if {$simplediffsflag} {
    foreach diff $functscanlists($page,condnames2difflist) {
      incr condnum
      set gltlist "$gltlist \
        -glt 1 $genlintestmatdir/$diff.mat \
        -glt_label $condnum \"$diff\""
    }
    foreach add $functscanlists($page,condnames2addlist) {
      incr condnum
      set gltlist "$gltlist \
        -glt 1 $genlintestmatdir/$add.mat \
        -glt_label $condnum \"$add\""
    }
  }
  if {!$simplediffsflag} {
    set contr 0
    while {$contr < $functscanlists($page,contrastcnt)} {
      incr condnum
      set gltname $functscanlists($page,$contr,gltname)
      set gltlist "$gltlist \
        -glt 1 $genlintestmatdir/$gltname.mat \
        -glt_label $condnum \"$gltname\""
      incr contr
    }
  }
  set glts $condnum

  ## concat arg
  if { $functscanlists($page,concatfiles) > 1 } {
    set concatarg "-concat $boundsfile"
  } else { set concatarg "" }

  if { $functscanlists($page,deconvtype) == "test" } {
    set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dDeconvolve \
      -nodata \
      $concatarg \
      -nlast [expr $functscanlists($page,reps) - 1] \
      -polort $functscanlists($page,polort) \
      $functscanlists($page,extraoptsrand) \
      -num_stimts $stms $stmlist \
      -num_glt $glts $gltlist"
  }
  if { $functscanlists($page,deconvtype) == "fout" } {
    set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dDeconvolve \
      -input [file rootname $databrik] \
      $concatarg \
      -nlast [expr $functscanlists($page,reps) - 1] \
      -polort $functscanlists($page,polort) \
      $functscanlists($page,extraoptsrand) \
      -num_stimts $stms $stmlist \
      -num_glt $glts $gltlist \
      -nocout -fout -bucket $datastem-$afnistatsinfix"
  }
  if { $functscanlists($page,deconvtype) == "tout" } {
    set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dDeconvolve \
      -input [file rootname $databrik] \
      $concatarg \
      -nlast [expr $functscanlists($page,reps) - 1] \
      -polort $functscanlists($page,polort) \
      $functscanlists($page,extraoptsrand) \
      -num_stimts $stms $stmlist \
      -num_glt $glts $gltlist \
      -nocout -tout -bucket $datastem-$afnistatsinfix"
  }

  ## run/save shell script in local scandir
  cdscandir       ;# tmp go local
  if [canwriteormakefile $deconvscript] {
    set id [open $deconvscript w 0755]
    puts $id "#!/bin/sh"  ;# avoid csh bracket problem
    puts $id $command
    close $id
  }
  runacmd "$command" $calcrandbu "DECONVOLVE  " cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
  cdfunctscripts  ;# back to def loc

  if { $functscanlists($page,deconvtype) == "test" } {
    confirmalert "3dDeconvolve: look in log for test (-nodata) result"
  }
  set functscanlists($page,stats3ddecon) [file tail $statsbrik]
  # set for Import 3D Stat panel initial startup
  set functscanlists($page,extstatfile) $functscanlists($page,stats3ddecon)

  writearrayparms $datfile calcrand
}

### called by deconvcmd command (Calculate 3D Rand Block Stats panel)
proc mkgenlintestmats { page } {  ;# returns success: 0/1
  global env session iscandir functscanlists simplediffsflag
  global genlintestmatdir boundsfile diffinfix addinfix

  set iscandir $page
  set fullmatdir $env(FUNCTIONALS_DIR)/$session/$iscandir/$genlintestmatdir
  set firstmatfile $fullmatdir/[lindex $functscanlists($page,condnames) 0].mat
  if [file exists $fullmatdir] {
    if { ![canwriteormakefile $firstmatfile] } {
      confirmalert "Make GLT matrices: fail\
                \n\nPermissions prevent write files in genlintest dir:\
                \n\n    $fullmatdir"
      return 0
    }
  } else { mkdirlog $fullmatdir }

  ## orig panel
  if {$simplediffsflag} {
    # polorts+1, one run
    set polorts "0"
    set i 0
    while {$i < $functscanlists($page,polort)} {
      set polorts "$polorts 0"
      incr i 
    }

    # concatpolorts+1 + singleconds+1 + motion
    foreach cond $functscanlists($page,condnames) {
      set row ""
      set run 0
      while {$run < $functscanlists($page,concatfiles)} {
        set row "$row $polorts"
        incr run 
      }
      foreach currcond $functscanlists($page,condnames) {
        set lag 0
        while {$lag <= $functscanlists($page,maxlag)} {
          if {$cond == $currcond} { set row "$row 1" } else { set row "$row 0" }
          incr lag
        }
      }
      if { $functscanlists($page,vregregressflag) } {
        set row "$row 0 0 0 0 0 0"  ;# motion
      }
      set id [open $fullmatdir/$cond.mat w 0644]
      puts $id [string trimleft $row " "]
      close $id
    }

    # contrasts: concatpolorts+1 + diffs+1 + motion
    foreach diff $functscanlists($page,condnames2difflist) {
      set cond1end [expr [string first $diffinfix $diff] - 1]
      set cond2start \
        [expr [string first $diffinfix $diff] + [string length $diffinfix]]
      set cond1 [string range $diff 0 $cond1end]
      set cond2 [string range $diff $cond2start end]
      set row ""
      set run 0
      while {$run < $functscanlists($page,concatfiles)} {
        set row "$row $polorts"
        incr run 
      }
      foreach cond $functscanlists($page,condnames) {
        set lag 0
        while {$lag <= $functscanlists($page,maxlag)} {
          if {$cond == $cond1} {
            set row "$row 1"
          } elseif {$cond == $cond2} {
            set row "$row -1"
          } else {
            set row "$row 0"
          }
          incr lag
        }
      }
      if { $functscanlists($page,vregregressflag) } {
        set row "$row 0 0 0 0 0 0"  ;# motion
      }
      set id [open $fullmatdir/$diff.mat w 0644]
      puts $id [string trimleft $row " "]
      close $id
    }

    # contrasts: concatpolorts+1 + adds+1 + motion
    foreach add $functscanlists($page,condnames2addlist) {
      set cond1end [expr [string first $addinfix $add] - 1]
      set cond2start \
        [expr [string first $addinfix $add] + [string length $addinfix]]
      set cond1 [string range $add 0 $cond1end]
      set cond2 [string range $add $cond2start end]
      set row ""
      set run 0
      while {$run < $functscanlists($page,concatfiles)} {
        set row "$row $polorts"
        incr run 
      }
      foreach cond $functscanlists($page,condnames) {
        set lag 0
        while {$lag <= $functscanlists($page,maxlag)} {
          if {$cond == $cond1} {
            set row "$row 1"
          } elseif {$cond == $cond2} {
            set row "$row 1"  ;# vs. diff -1
          } else {
            set row "$row 0"
          }
          incr lag
        }
      }
      if { $functscanlists($page,vregregressflag) } {
        set row "$row 0 0 0 0 0 0"  ;# motion
      }
      set id [open $fullmatdir/$add.mat w 0644]
      puts $id [string trimleft $row " "]
      close $id
    }
    return 1  ;# success
  }

  ## new general glt's
  if {!$simplediffsflag} {
    set mknamesflag 0    ;# next returns fail if >32 or empty
    if ![chkcontrastsmknames $page $mknamesflag] { return 0 }
    ## make glt lines, write into files
    # polorts+1, one run
    set polorts "0"
    set i 0
    while {$i < $functscanlists($page,polort)} {
      set polorts "$polorts 0"
      incr i
    }

    # concatpolorts+1 + singleconds+1 + motion
    foreach cond $functscanlists($page,condnames) {
      set row ""
      set run 0
      while {$run < $functscanlists($page,concatfiles)} {
        set row "$row $polorts"
        incr run
      }
      foreach currcond $functscanlists($page,condnames) {
        set lag 0
        while {$lag <= $functscanlists($page,maxlag)} {
          if {$cond == $currcond} { set row "$row 1" } else { set row "$row 0" }
          incr lag
        }
      }
      if { $functscanlists($page,vregregressflag) } {
        set row "$row 0 0 0 0 0 0"  ;# motion
      }
      set id [open $fullmatdir/$cond.mat w 0644]
      puts $id [string trimleft $row " "]
      close $id
    }

    # contrasts: concatpolorts+1 + glts+1 + motion
    set contr 0
    while {$contr < $functscanlists($page,contrastcnt)} {
      set gltname $functscanlists($page,$contr,gltname)
      set row ""
      set run 0
      while {$run < $functscanlists($page,concatfiles)} {
        set row "$row $polorts"
        incr run
      }
      foreach cond $functscanlists($page,condnames) {
        set gltnum $functscanlists($page,$contr,$cond,gltnum)
        set lag 0
        while {$lag <= $functscanlists($page,maxlag)} {
          set row "$row $gltnum"
          incr lag
        }
      }  
      if { $functscanlists($page,vregregressflag) } {
        set row "$row 0 0 0 0 0 0"  ;# motion
      }
      set id [open $fullmatdir/$gltname.mat w 0644]
      puts $id [string trimleft $row " "]
      close $id
      incr contr
    }
    return 1  ;# success
  }
}

### errs, translate interface->gltnames for deconvcmd (AUTO NAMES)
proc chkcontrastsmknames { page mknamesflag } {  ;# returns success 0/1
  global functscanlists diffinfix diffprefix

  set contr 0
  while {$contr < $functscanlists($page,contrastcnt)} {
    set indexlist [lsort [array names functscanlists $page,$contr,*,gltnum]]
    set posgltlist {}
    set neggltlist {}
    foreach index $indexlist {  ;# one line
      set beg [expr [string length $page] + 3]
      set end [expr [string length $index] - [string length ,gltnum] - 1]
      set cond [string range $index $beg $end]
      set gltnum $functscanlists($page,$contr,$cond,gltnum)
      if {$gltnum > 0} { lappend posgltlist $cond }
      if {$gltnum < 0} { lappend neggltlist $cond }
    }
    # err
    set cline "contr$contr:"
    foreach cond $functscanlists($page,condnames) {
      set cline "$cline  $functscanlists($page,$contr,$cond,gltnum)"
    }
    if { ![llength $posgltlist] && ![llength $neggltlist] } {
      confirmalert "Make GLT matrices: rm/fix empty row (all 0's):\
                \n\n    $cline"
      return 0
    }
    if { [llength $posgltlist] == 1 && ![llength $neggltlist] } {
      confirmalert "Make GLT matrices: single conditions made\
                  \nautomatically -- can't make again:\
                \n\n    $cline"
      return 0
    }
    ## pos
    set gltn ""
    set j 0
    foreach pos $posgltlist {
      if {$j == 0} { set gltn "$pos" } else { set gltn "$gltn,$pos" }
      incr j
    }
    ## infix
    if {  [llength $posgltlist] &&  [llength $neggltlist] } {
      set gltn "${gltn}${diffinfix}"
    }
    if { ![llength $posgltlist] &&  [llength $neggltlist] } {
      set gltn "${gltn}${diffprefix}"
    }
    if {  [llength $posgltlist] && ![llength $neggltlist] } {
      ;# omit infix/prefix
    }
    ## neg
    set j 0
    foreach neg $neggltlist {
      if {$j == 0} { set gltn "${gltn}$neg" } else { set gltn "$gltn,$neg"}
      incr j
    }
    ## test name
    if {$mknamesflag} {
      set lablen [string length $gltn]
      set labdescription "generated name"
    } else {
      set lablen [string length $functscanlists($page,$contr,gltname)] ;#exist
      set labdescription "name"
      if {!$lablen} {
        confirmalert "Make GLT names: empty name for:\
                  \n\n    contrast: $contr\
                  \n\nuse AUTO NAMES, or fill in entry"
        return 0
      }
    }
    if { $lablen > 32 } {
      confirmalert "Make GLT names: contrast $contr labelname too long:\
                \n\n    $gltn\
                \n\n($lablen chars) -- 3dDeconvolve has 32-char\
                  \nlimit for each -glt_label\
                \n\nTo fix, shorten $labdescription in \"GLT name\" field"
      if {!$mknamesflag} { return 0 } ;# >32: run=>fail, AUTO NAMES=>mk anyway
    }
    if {$mknamesflag} {set functscanlists($page,$contr,gltname) $gltn} ;#write
    incr contr
  }
  return 1
}


### check stems OK for rawaverage:read_xyt_image, fourier:read_raw_images
proc gettimeseriesinputstem { dir patt } {  ;# file must exist, return stem
  global env session
  set ext [file extension $patt]
  if {$ext == ".im"} {
    set stem1 [file rootname $patt]
    set stem [string range $stem1 0 [expr [string last _ $stem1] - 1]]
    set firstim ${stem}_1.im
  } elseif {$ext == ".BRIK"} {  ;# .HEAD consulted for some
    set stem [file rootname $patt]
    set firstim $patt
  } elseif {$ext == ".brik"} {  ;# noheader
    set stem [file rootname $patt]
    set firstim $patt
  } elseif {$ext == ".bshort"} {
    set stem [stripbpatt $patt]
    set firstim ${stem}_000.bshort
  } else {
    confirmalert "Read Funct: bad suffix: $ext (accepts BRIK,brik,im,bshort)"
    return badfunctsuffix
  }
  set fullfirstim $env(FUNCTIONALS_DIR)/$session/$dir/$firstim
  if ![file exists $fullfirstim] {
    confirmalert "Check Time Series Input: first file:\
              \n\n    $fullfirstim\n\nnot found"
    return firstnotfound
  }
  return $stem
}

### COMBINE button command (Combine 3D Phase Stats panel)
proc sigaveragecmd { nbwin } {
  global env session iscandir
  global cmdlog sigaveragebu
  global functscanlists
  global realname complexname amprealname ampcomplexname fullFTname
  global force bindir datfile

  if [checkconcurrent] { return }
  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  set iscandir $page

  ## basic checks, setup
  if { [llength $functscanlists($page,sigtoavgdirs)] < 2 } {
    confirmalert "3D Stats Combine: first select at least 2 dirs to combine"
    return
  }
  set sigoperation $functscanlists($page,sigoperation)
  if {$sigoperation != "phaseaverage" && $sigoperation != "phasecancel" &&
      $sigoperation != "fullphavgsig"} {
    confirmalert "3D Stats Combine: unknown operation: $sigoperation"
    return
  }
  if {$sigoperation == "phasecancel" &&
      [llength $functscanlists($page,sigtoavgdirs)] != 2} {
    confirmalert "3D Stats Combine: phasecancel operation requires 2 dirs only"
    return
  }
  if {$sigoperation == "phaseaverage"} { set stattype complex } ;# rcxcombine
  if {$sigoperation == "phasecancel"}  { set stattype complex } ;# phasecombine
  if {$sigoperation == "fullphavgsig"} { set stattype complex } ;# rcxcombine
  set functscanlists($page,stattype) $stattype
  if {$stattype == "complex"} { ;# default sig average is all 4
    set infix1list { "" }
    set infix2list "$realname $complexname $amprealname $ampcomplexname"
  }

  ## checkinfileparms: bfloatpatt set by deconv,fourier, cp'd from 1stdir below
  # includes parms needed to run fourier on average fullFT's
  set parmlist \
    { imagepatt slices xres yres reps inplane thickness \
      phasestattype phasestatformat stimcycles lofreqwin hifreqwin omitfreq \
      meandelay inclharm23flag fixileaveflag useTAXISflag sliceorder \
      paintdmin paintdmax paintdstep paintnormop paintnormtype \
      regdat bfloatpatt filetruncphaseflag truncslope \
      rh,truncphasemin rh,truncphasemax lh,truncphasemin lh,truncphasemax \
      preclustfthr clustarea }
  foreach dir $functscanlists($page,sigtoavgdirs) { ;# so next not misleading
    if ![file exists $env(FUNCTIONALS_DIR)/$session/$dir] {
      confirmalert "3D Stats Combine: scan directory:\
                 \n\n    $dir\
                 \n\nConfig'd here but doesn't exist\
                   \n(incomplete copy?)"
      return
    }
    foreach parm $parmlist { ;# bak compat
      if { ![info exists functscanlists($dir,$parm)] ||
           $functscanlists($dir,$parm) == "-unset-" ||
           $functscanlists($dir,$parm) == ""} {
        confirmalert "3D Stats Combine:\
                  \n\nParm(s) missing from Setup Funct Scan\
                  \n\nFirst missing:  $parm\
                  \n\nIf older session, fix by:\
                  \n\n  (1) open Setup Align/Funct Scans, Save/Close\
                    \n  (2) open Calculate 3D Fourier Stats, Save/Close\
                    \n  (3) come back here, re-run COMBINE"
        return
      }
    }
  }

  ## check all inputs have same phase stat format
  set firstdir [lsort [lindex $functscanlists($page,sigtoavgdirs) 0]]
  set firstformat $functscanlists($firstdir,phasestatformat) ;#used again below
  set found 0
  foreach dir $functscanlists($page,sigtoavgdirs) {
    if {$functscanlists($dir,phasestatformat) != $firstformat} { set found 1 }
  }
  if {$found} {
    confirmalert "3D Stats Combine: Phase stats format inconsistent:\
              \n\nGo back to Calculate 3D Fourier panel,\
                \nre-run FOURIER for each scandir to COMBINE\
                \nw/\"Phase Stat Out Format\" set same for each"
    return
  }

  ## setup to skip combine _x,_y sig's if first missing
  set fullsess $env(FUNCTIONALS_DIR)/$session
  if {$stattype == "complex"} {
    # skip raw amplitude average if first real (_x) slice missing
    set skipamp 0
    set firstdir [lsort [lindex $functscanlists($page,sigtoavgdirs) 0]]
    set bfloatpatt $functscanlists($firstdir,bfloatpatt)  ;# no infix
    set bfloatstem [stripbpatt $bfloatpatt]
    if {$functscanlists($firstdir,phasestatformat) == "bfloat"} {
      set firstampslice \
        $fullsess/$firstdir/${bfloatstem}${amprealname}_000.bfloat
    }
    if {$functscanlists($firstdir,phasestatformat) == "afnibrik"} {
      set firstampslice \
        $fullsess/$firstdir/${bfloatstem}${amprealname}+orig.BRIK
    }
    if ![file exists $firstampslice] {
      putlog "3D Stats Combine: first raw fourier amp slice not found"
      putlog "  ...skip combine amp ($amprealname,$ampcomplexname)"
      set infix2list "$realname $complexname"  ;# curr just input check
      set skipamp 1
    }
  }

  ## check all sig inputs exist (N.B.: OK to avg stats w/diff stimcycles/reps)
  if {$sigoperation == "phaseaverage" || $sigoperation == "phasecancel"} {
    foreach dir $functscanlists($page,sigtoavgdirs) {
      foreach infix1 $infix1list {
        foreach infix2 $infix2list {
          set bfloatpatt $functscanlists($dir,bfloatpatt)  ;# no infix
          # next to catch badly reset bfloatpatt (but confusing w/o infix)
          set statsuff [file extension $bfloatpatt]
          if { $statsuff != ".bfloat" && $statsuff != ".BRIK" } {
            confirmalert "3D Stats Combine: bad suffix on stat input pattern:\
                      \n\n    \"$bfloatpatt\"\
                      \n\n(not .bfloat or .BRIK)"
            return
          }
          set bfloatstem [stripbpatt $bfloatpatt]
          if {$functscanlists($dir,phasestatformat) == "bfloat"} {
            set firstslice \
              $fullsess/$dir/${bfloatstem}${infix1}${infix2}_000.bfloat
          }
          if {$functscanlists($dir,phasestatformat) == "afnibrik"} {
            set firstslice \
              $fullsess/$dir/${bfloatstem}${infix1}${infix2}+orig.BRIK
          }
          if ![file exists $firstslice] {
            confirmalert "3D Stats Combine: missing input file: $firstslice"
            return
          }
        }
      }
    }
  }

  ## check fullFT inputs exist, consistent stimcyc/reps (before cp->sigavgdir)
  if {$sigoperation == "fullphavgsig"} {  ;# two-part infix: _xf,_yf
    foreach dir $functscanlists($page,sigtoavgdirs) {
      foreach infix "$amprealname $ampcomplexname" {
        set bfloatpatt $functscanlists($dir,bfloatpatt)  ;# no infix
        # next to catch badly reset bfloatpatt (but confusing w/o infix)
        set statsuff [file extension $bfloatpatt]
        if { $statsuff != ".BRIK" } {
          confirmalert "3D Stats Combine full FT: bad suffix on input pattern:\
                    \n\n    \"$bfloatpatt\"\
                    \n\n(not .BRIK)"
          return
        }
        set bfloatstem [stripbpatt $bfloatpatt]
        set brik $fullsess/$dir/${bfloatstem}${infix}${fullFTname}+orig.BRIK
        if ![file exists $brik] {
          confirmalert "3D Stats Combine: missing full FT input file:\n\n$brik"
          return
        }
      }
    }
    set firstdir [lsort [lindex $functscanlists($page,sigtoavgdirs) 0]]
    set firstcyc $functscanlists($firstdir,stimcycles)
    set found 0
    set stimcyclist ""
    foreach dir $functscanlists($page,sigtoavgdirs) {
      set stimcyclist \
        "$stimcyclist\n    $dir:    $functscanlists($dir,stimcycles) cycles"
      if {$functscanlists($dir,stimcycles) != $firstcyc} { set found 1 }
    }
    if {$found} {
      confirmalert "3D Stats Combine: Stim Cycles inconsistent:\
                   \n$stimcyclist\
                 \n\nN.B.: can't avg full FT's w/different stim cycles\
                 \n\nOmit inconsistent scans from Scans to Combine\
                   \n(or fix bad \"Stim Cycles\" and re-run FOURIER)\
                   \nand then re-run COMBINE"
      return
    }
    set firstdir [lsort [lindex $functscanlists($page,sigtoavgdirs) 0]]
    set firstreps $functscanlists($firstdir,reps)
    set found 0
    foreach dir $functscanlists($page,sigtoavgdirs) {
      if {$functscanlists($dir,reps) != $firstreps} { set found 1 }
    }
    if {$found} {
      confirmalert "3D Stats Combine: Images Per Slice inconsistent:\
                \n\nN.B.: can't avg full FT's w/diff num time points\
                \n\nOmit inconsistent scans from Scans to Combine\
                  \nand re-run COMBINE"
      return
    }
  }

  ## check 1st-to-avg dir regdat is there (can't reg avg fourier stats w/o EPI)
  set firstdir [lindex $functscanlists($page,sigtoavgdirs) 0]
  set fullfirstregdat $fullsess/$firstdir/$functscanlists($firstdir,regdat)
  if ![info exists functscanlists($page,regdat)] {
    set functscanlists($page,regdat) $functscanlists($firstdir,regdat)
  }
  set fullregdat $fullsess/$iscandir/$functscanlists($page,regdat)
  if [file exists $fullfirstregdat] {
    cplog $fullfirstregdat $fullregdat
  } else {
    confirmalert "3D Stats Combine: Can't copy Transform file to\
              \n\n    $page\
              \n\nno $functscanlists($firstdir,regdat) found in first inp dir:\
              \n\n    $firstdir\
              \n\nManual Register $page  or  COPY ALIGN TO ALL FUNCTS"
     return
  }

  ## bak compat: old config'd pre-phasestatformat scan w/1st action COMBINE
  if ![info exists functscanlists($page,phasestatformat)] {
    if { [glob -nocomplain $fullsess/$iscandir/*_000.bfloat] != "" &&
         $firstformat == "bfloat" } { ;# req done *and* curr 1st to avg bfloat
      set functscanlists($page,phasestatformat) bfloat  ;# N.B.: sigavgdir
    }
  }

  ## overwrite sigavgdir parms w/firstdir's (except already exist normsearch's)
  foreach parm $parmlist {
    if { $parm == "paintdmin"  || $parm == "paintdmax" ||
         $parm == "paintdstep" || $parm == "paintnormop" ||
         $parm == "paintnormtype" } {
      if ![info exists functscanlists($page,$parm)] {
        set functscanlists($page,$parm) $functscanlists($firstdir,$parm)
      }
    } else { ;# always re-copy possibly changed firstparms to combinedir parms
      set functscanlists($page,$parm) $functscanlists($firstdir,$parm)
    }
  } ;# phasestatformat copied/created for sigavg dir used in next check

  ## check output dir overwrite (outtype same as intype, phavg,fullFT+sig same)
  set infix1 [lindex $infix1list 0]
  set infix2 [lindex $infix2list 0]
  set firstdir [lsort [lindex $functscanlists($page,sigtoavgdirs) 0]]
  set bfloatpatt $functscanlists($firstdir,bfloatpatt)
  set bfloatstem [stripbpatt $bfloatpatt]
  if {$functscanlists($page,phasestatformat) == "bfloat"} {
    set firstout $fullsess/$iscandir/${bfloatstem}${infix1}${infix2}_000.bfloat
  }
  if {$functscanlists($page,phasestatformat) == "afnibrik"} {
    set firstout $fullsess/$iscandir/${bfloatstem}${infix1}${infix2}+orig.BRIK
  }
  if {!$force} {
    if { [file exists $firstout] } {
      if [okreplace $firstout "$firstout exists--Redo Stat Combine?" "Redo"] {
      } else {
        confirmalert "3D Stats Combine: stat images not altered (may be stale)"
        return
      }
    }
  }

  ## make intercalated dir/stem list for rcxcombine/phasecombine
  set intercalatedlist ""
  foreach dir $functscanlists($page,sigtoavgdirs) {
    lappend intercalatedlist $fullsess/$dir
    lappend intercalatedlist [stripbpatt $functscanlists($dir,bfloatpatt)]
  }  ;# rcxcombine/phasecombine add infixes, suffix
#xxx -- TODO: add phasecancel to rcxcombine (phasecancel revs 1 not 2?)
  # make revphase list for rcxcombine
  set revlist ""
  foreach rev $functscanlists($page,sigtoavgrevs) {
    if {$rev == "on"}                     { lappend revlist 1 }
    if {$rev == "off" || $rev == "none"}  { lappend revlist 0 }
  }
  set revopt ""
  if [llength $functscanlists($page,sigtoavgrevs)] {
    set revopt "-revphase $revlist"
  }
  # in/out format
  if {$functscanlists($page,phasestatformat) == "bfloat"} {
    set extopt "-ext bfloat"
  }
  if {$functscanlists($page,phasestatformat) == "afnibrik"} {
    set extopt "-ext BRIK"
  }

  # go: combine (bfloat->bfloat, BRIK->BRIK), if fullFT 1:avg, 2:fourier on it
  if {$stattype == "complex"} {  ;# process in pairs (because need phase)
    set functscanlists($page,phasetype) $functscanlists($firstdir,phasetype)
    if {$sigoperation == "phaseaverage" || $sigoperation == "phasecancel"} {
      foreach phtype { amp sig } {
        if {$phtype == "amp" && $skipamp} { continue }
        if {$phtype == "amp"} {set rfix $amprealname; set ifix $ampcomplexname}
        if {$phtype == "sig"} {set rfix $realname;    set ifix $complexname}
        if {$functscanlists($page,sigoperation) == "phaseaverage"} {
          set command "$bindir/rcxcombine \
            -complex \
            -input [lbackslashspaces $intercalatedlist] \
            $extopt \
            -infixes $rfix $ifix \
            -nslices $functscanlists($page,slices) \
            $revopt \
            -offset $functscanlists($page,sigavgoffset) \
            -outtype avg \
            -outdir [backslashspaces $fullsess/$iscandir] \
            -outstem [stripbpatt $functscanlists($firstdir,bfloatpatt)]"
          runacmd "$command" $sigaveragebu "COMBINE  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
        }
        if {$functscanlists($page,sigoperation) == "phasecancel"} {
          set command "$bindir/phasecombine \
            -nslices $functscanlists($page,slices) \
            -action $sigoperation \
            -infixes $rfix $ifix \
            -smooth $functscanlists($page,smoothsteps3d) \
            [lbackslashspaces $intercalatedlist] \
            [backslashspaces $fullsess/$iscandir]"
          runacmd "$command" $sigaveragebu "COMBINE  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
        }
      }
    }
    if {$sigoperation == "fullphavgsig"} { ;# two-step
      ## average fullFT's -- add stimcycles in case phase offset (rev is after)
      set rfix $amprealname; set ifix $ampcomplexname
      set command "$bindir/rcxcombine \
        -complex -fullFT -fullfouramp \
        -input [lbackslashspaces $intercalatedlist] \
        $extopt \
        -infixes $rfix $ifix \
        -nslices $functscanlists($page,slices) \
        -stimcyc $functscanlists($page,stimcycles) \
        $revopt \
        -offset $functscanlists($page,sigavgoffset) \
        -outtype avg \
        -outdir [backslashspaces $fullsess/$iscandir] \
        -outstem [stripbpatt $functscanlists($firstdir,bfloatpatt)]"
      runacmd "$command" $sigaveragebu "COMBINE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid

      ## run fourier on avg fullFT just made (generates both _r,i and _x,y)
      # stem: from orig (BRIK) firstdir timecourse to fourier (must exist!)
      set stem \
        [gettimeseriesinputstem $firstdir $functscanlists($firstdir,imagepatt)]
      set fullstem $fullsess/$iscandir/$stem  ;# for both in/out
      set fullFTinbrik_r ${fullstem}${amprealname}${fullFTname}+orig.BRIK
      set fullFTinbrik_i ${fullstem}${ampcomplexname}${fullFTname}+orig.BRIK
      set statoutbrikstem $fullstem
      #TODO: sliceorder could differ, omit for now
      #set sliceorderarg ""
      #if { $functscanlists($page,fixileaveflag) } {
      #  # assume not sparse (TODO: allow interslicetime < TR/slices => sparse)
      #  set interslicetime \
      #    [expr $functscanlists($page,TR)/$functscanlists($page,slices).0]
      #  set sliceorder $functscanlists(def,sliceorder)
      #  set sliceorderarg \
      #    "-slicetiming $sliceorder $interslicetime $functscanlists($page,TR)"
      #}
      if {$functscanlists($page,phasestattype) == "sqrt-F"} {set phaseoptarg 0}
      if {$functscanlists($page,phasestattype) == "p-val"}  {set phaseoptarg 1}
      if {$functscanlists($page,phasestattype) == "p-FA"}   {set phaseoptarg 2}
      set inclharmopt ""
      if {$functscanlists($page,inclharm23flag)} {set inclharmopt "-inclharm23"}
      set command "$bindir/fourier \
        -juststats \
        [backslashspaces $fullFTinbrik_r] [backslashspaces $fullFTinbrik_i] \
        [backslashspaces $statoutbrikstem] \
        -nslices $functscanlists($page,slices) \
        -reps $functscanlists($page,reps) \
        -imres $functscanlists($page,xres) $functscanlists($page,yres) \
        -statres $functscanlists($page,xres) $functscanlists($page,yres) \
        -stimcyc $functscanlists($page,stimcycles) \
        -infixes $realname $complexname \
        $inclharmopt \
        -freqsurr $functscanlists($page,lofreqwin) \
                  $functscanlists($page,hifreqwin) \
        -omitfreq $functscanlists($page,omitfreq) \
        -meandelay $functscanlists($page,meandelay) \
        -phasetype $phaseoptarg \
        -sigoutbrik"
      runacmd "$command" $sigaveragebu "COMBINE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
    }
  }
  if {$stattype == "real"} {
    # TODO: non-complex stattypes
  }

  writearrayparms $datfile sigavg
}

### EXTRACT/CONVERT stats button command (External Stats panel)
proc convertfunctcmd { nbwin } {
  global env name session iscandir
  global cmdlog convertfunctbu
  global functscanlists
  global force bindir afnibindir volumedir t1dir datfile

  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  set iscandir $page

  if {$functscanlists($page,bfloatpatt) == "-selectimageset-"} {
    confirmalert "Convert: first select stat image set to convert"
    return
  }

  # conservative (in case it breaks something) -- could omit since AFNI local!
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog \
      "convertfunct: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  set instat $fullscandir/$functscanlists($page,extstatfile)
  set outstem $fullscandir/[stripbpatt $functscanlists($page,bfloatpatt)]
  set infix ""    ;# in case read complex (prob not)
  if {$functscanlists($page,realstatformat) == "bfloat"} {
    set firstslice ${outstem}${infix}_000.bfloat
  }
  if {$functscanlists($page,realstatformat) == "afnibrik"} {
    set firstslice ${outstem}${infix}+orig.BRIK
  }
  if ![info exists functscanlists($page,regdat)] {
    set functscanlists($page,regdat) $functscanlists(def,regdat)
  }
  set fullregdat $fullscandir/$functscanlists($page,regdat)

  ### paint can read bfloats/mgz/BRIK (BRIK: maybe extract 1 subbrik)
  if { $functscanlists($page,statformat) == "bfloat" ||
       $functscanlists($page,statformat) == "mgzsingle" } {
    confirmalert "Convert Funct: Images already native\
                \n(bfloat/BRIK/mgz)\n\n  ...OK to PAINT"
    if { ![file exists $fullregdat] } {
      confirmalert \
        "Convert Funct: $fullregdat not found  ...using identity matrix"
      writedefregdat $page
    }
    set functscanlists($page,stattype) real  ;# firstslice above assumes real
    return
  }

  if {!$force} {
    if [file exists $firstslice] {
      if ![okreplace $firstslice "Stat Images: $firstslice exists--replace?"] {
        confirmalert "Convert Funct: $firstslice not altered"
        return
      }
    }
  }

  ### convert spm (generate bfloats and register.dat) -- removed
  if {$functscanlists($page,statformat) == "spm99" } {
    confirmalert " The SPM99 option has been removed"  ;# if very old
    return
  }

  ### convert one brik (maybe nth subbrik)
  if {$functscanlists($page,statformat) == "briksingle" } {
    if ![file exists $instat] {
      confirmalert "Convert AFNI: failed: $instat not found"
      return
    }
    set instatstem [file rootname $instat]
    set header $instatstem.HEAD
    if ![file exists $header] {
      confirmalert "Convert AFNI: failed: can't find matching HEAD file"
      return
    }
    # next 2 only needed if write default regdat w/no raw data (rare)
    set functscanlists($page,inplane)   [getafniinplane $header]
    set functscanlists($page,thickness) [getafnithickness $header]
    if ![file exists $fullregdat] {
      if ![okreplace "" "Convert AFNI: $fullregdat not found\n\nMake default?"\
         "Make Default"] {
        confirmalert "Convert AFNI: register.dat not found in:\
                  \n\n => $page\
                  \n\n...conversion aborted\
                  \n\n(1) Create register.dat manually in\
                    \n       $page\
                  \n\n     or\
                  \n\n(2) Use Setup Align/Funct panel to create\
                    \n       register.dat in Funct Scan dir and\
                    \n       copy it to $page"
        return
      } else {writedefregdat $page; confirmalert "wrote default register.dat"}
    }
    set bskip $functscanlists($page,bskip)
    forcebrikMSBfirst $instatstem nowarn $convertfunctbu "EXTRACT/CONVERT  "
    if {$functscanlists($page,realstatformat) == "bfloat"} {
      set command "$bindir/brik2bfloat [backslashspaces $instatstem] \
        [backslashspaces $outstem] $bskip"
      runacmd \
        "$command" $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
    }
    if {$functscanlists($page,realstatformat) == "afnibrik"} {
      # do nothing: bskip used at paint single-BRIK time instead
    }
  }

  ### extract/thresh/convert brikmulti
  if {$functscanlists($page,statformat) == "brikmulti" } {
    # check inputs
    if ![file exists $instat] {
      confirmalert "Convert AFNI: $instat not found"
      return
    }
    set instatstem [file rootname $instat]
    set header $instatstem.HEAD
    if ![file exists $header] {
      confirmalert "Convert AFNI: found $instat but can't find $header"
      return
    }
    if ![file exists $fullregdat] {
      if ![okreplace "" "Convert AFNI: $fullregdat not found\n\nMake default?"\
         "Make Default"] {
        confirmalert "Convert AFNI: register.dat not found in:\
                  \n\n => $page\
                  \n\n...conversion aborted\
                  \n\n(1) Create register.dat manually in\
                    \n       $page\n\n     or\
                 \n\n(2) Use Setup Align/Funct panel to create\
                   \n       register.dat in Funct Scan dir and\
                   \n       copy to $page"
        return
      } else {writedefregdat $page; confirmalert "wrote default register.dat"}
    }
    cdlog $fullscandir
    set valuefilelist [getsortedvaluefilelist $page]

    # check/rm already existing extractions (AFNI can't overwrite)
    set printtargfilelist ""
    set rmtargfilelist ""
    foreach valuefile $valuefilelist { ;# valuefile embedded in array indices
      if {!$functscanlists($page,$valuefile,extractflag)} { continue }
      foreach targfile "$valuefile+orig.BRIK \
                        $valuefile-thresh+orig.BRIK \
                        $valuefile-clustmask+orig.BRIK \
                        $valuefile-clust+orig.BRIK" {
        if [file exists $targfile] {
          #set printtargfilelist "$printtargfilelist =>  $targfile\n"
          set printtargfilelist "${printtargfilelist}${targfile}\n"
        }
      }
      foreach rmfile "$valuefile+orig.BRIK        $valuefile+orig.HEAD \
                      $valuefile-thresh+orig.BRIK $valuefile-thresh+orig.HEAD \
                $valuefile-clustmask+orig.BRIK $valuefile-clustmask+orig.HEAD \
                      $valuefile-clust+orig.BRIK  $valuefile-clust+orig.HEAD" {
        if [file exists $rmfile] { lappend rmtargfilelist $rmfile }
      }
    }
    if {"$printtargfilelist" != ""} {
      if {!$force} {
        if ![okreplace "" "Convert AFNI:\
             \n\n$printtargfilelist\nOK to overwrite/re-extract these BRIKs?"\
             "Redo Extract/Convert"] {
          confirmalert "Convert AFNI: extracted BRIKS/bshorts not altered"
          cdfunctscripts
          return
        }
      }
    }
    foreach rmfile $rmtargfilelist { rmlog "$rmfile" }

    ### extract/manipulate AFNI files
    # 3dDeconvolve: (1) coef, (2) fstat/tstat
    # 3dmerge: fstat/tstat -> (3) fstat/tstat-clustermask
    # 3dcalc: mask (1) with (3) -> (4), mask (2) with (3) -> (5)
    # 1 or 2 single-segment output files here per loop
    ### coef operations
    # coef/nocluster/nothresh -> dump coef
    # coef/nocluster/thresh -> thresh coef
    # coef/cluster/thresh -> cluster stat, mask coef
    ### stat operations
    # stat/nocluster/nothresh -> dump stat
    # stat/nocluster/thresh -> thresh stat
    # stat/cluster/thresh -> cluster, mask stat + dump unclustered stat
    ### 3dDeconvolve stats outfile typically LSB

    ### go extract (N.B.: stems all have +orig added)
    foreach valuefile $valuefilelist { ;# valuefile embedded in array indices
      if {!$functscanlists($page,$valuefile,extractflag)} { continue }
      set functscanlists($page,$valuefile,bfloatstem) "-goextract-"
      set subbrikindex $functscanlists($page,$valuefile,subbrikindex)
      set subbriknum [string trimleft $subbrikindex #0] ;# #08=>8 (no hex prob)
      if {$subbrikindex == "#00"} { set subbriknum 0 }  ;# fix trimmed-to-empty
      set maskfile $functscanlists($page,$valuefile,maskfile)
      set maskthresh $functscanlists($page,$valuefile,maskthresh)
      set clusterflag $functscanlists($page,$valuefile,clusterflag)
      set extractedvaluestem -unset-
      set extractedmaskstem -unset-
      if { $maskthresh != 0.0 } {
        if {$maskfile == "-unset-"} {
          confirmalert \
            "Convert AFNI: maskfile for subbrik $subbrikindex not set"
          cdfunctscripts
          return
        } else {
          set masksubbrikindex $functscanlists($page,$maskfile,subbrikindex)
          set masksubbriknum [string trimleft $masksubbrikindex #0] ;# for hex
          if {$masksubbrikindex == "#00"} { set masksubbriknum 0 } ;# fix empty
        }
      }

      ### case1: valuefile is coef subbrik
      if { [string match *Coef $valuefile] ||
           [string match *coef $valuefile] } {
        ## extract coef => <coef>-thresh
        if { !$clusterflag && $maskthresh == 0.0 } {
          set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -a \"$instatstem\[$subbriknum\]\" \
            -expr a \
            -prefix $valuefile-thresh"
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          set extractedvaluestem $valuefile-thresh+orig
        ## thresh coef => <coef>-thresh
        } elseif { !$clusterflag && $maskthresh != 0.0 } {
          set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -a \"$instatstem\[$subbriknum\]\" \
            -expr \"step(a-$maskthresh)*a\" \
            -prefix $valuefile-thresh"
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          set extractedvaluestem $valuefile-thresh+orig
        ## bail
        } elseif { $clusterflag && $maskthresh == 0.0 } {
          confirmalert "Convert AFNI: non-zero thresh required\
                      \nto cluster-filter stats:\
                    \n\n    $valuefile"
          cdfunctscripts
          return
        ## thresh/cluster-mask stat, use to thresh coef => <coef>-clust
        } elseif { $clusterflag && $maskthresh != 0.0 } {
          ## make tmp binary clustermask from *maskfile*
          set nonegarg ""  ;# allow neg (was: if tout, -1noneg, else empty)
          set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dmerge \
            $nonegarg \
            -verbose \
            -dxyz=1 \
            -1clust_order $functscanlists($page,clusterrad) \
                          $functscanlists($page,clustervol) \
            -1thresh $maskthresh \
            -prefix $maskfile-clustmask \
            \"$instatstem\[$masksubbriknum\]\""  ;# (not current valuefile)
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          ## mask coef voxels with it
          set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -a \"$instatstem\[$subbriknum\]\" \
            -b $maskfile-clustmask+orig \
            -expr \"step(b)*a\" \
            -prefix $valuefile-clust"
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          ## save 2 files for painting (forcebrikMSB done at end)
          set extractedvaluestem $valuefile-clust+orig  ;# masked coef
          ## clustmask made here used below
        } else { ; } ;# maybe others

      ### case2: valuefile is stat subbrik
      } elseif { [string match *Fstat $valuefile] ||
           [string match *Tstat $valuefile]  ||
           [string match *F-stat $valuefile] ||
           [string match *t-st $valuefile] } {
        ## just extract stat => <stat>-thresh
        if { !$clusterflag && $maskthresh == 0.0 } {
          set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -a \"$instatstem\[$subbriknum\]\" \
            -expr a \
            -prefix $valuefile-thresh"
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          set extractedvaluestem $valuefile-thresh+orig
        ## thresh stat using itself => <stat>-thresh
        } elseif { !$clusterflag && $maskthresh != 0.0 } {
          set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -a \"$instatstem\[$subbriknum\]\" \
            -expr \"step(a-$maskthresh)*a\" \
            -prefix $valuefile-thresh"
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          set extractedvaluestem $valuefile-thresh+orig
        ## bail
        } elseif { $clusterflag && $maskthresh == 0.0 } {
          confirmalert "Convert AFNI: non-zero thresh required\
                      \nto cluster-filter stats:\
                    \n\n    $valuefile"
          cdfunctscripts
          return
        ## extract stat, thresh/clust-mask stat => <stat>-thresh, <stat>-clust
        } elseif { $clusterflag && $maskthresh != 0.0 } {
          ## extract (zero thresh)
          set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -a \"$instatstem\[$subbriknum\]\" \
            -expr a \
            -prefix $valuefile-thresh"
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          ## make tmp clustermask if not done (assumes same thresh!)
          if ![file exists $valuefile-clustmask+orig.BRIK] {
            set nonegarg ""  ;# allow neg (was: if tout, -1noneg, else empty)
            set command \
             "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dmerge \
              $nonegarg \
              -verbose \
              -dxyz=1 \
              -1clust_order $functscanlists($page,clusterrad) \
                            $functscanlists($page,clustervol) \
              -1thresh $maskthresh \
              -prefix $valuefile-clustmask \
              \"$instatstem\[$subbriknum\]\""
            # N.B.: leave LSB output on Intel (only inspected in AFNI)
            runacmd "$command" \
              $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
            tkwait variable cmdpid
          } else { 
            # using clust made above (N.B. valuefile here == maskfile above)
          }
          ## mask (same) stat voxels with it (diff than above)
          set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -a \"$instatstem\[$subbriknum\]\" \
            -b $valuefile-clustmask+orig \
            -expr \"step(b)*a\" \
            -prefix $valuefile-clust"
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          ## save 2 files for painting
          set extractedvaluestem $valuefile-thresh+orig  ;# stat
          set extractedmaskstem $valuefile-clust+orig    ;# masked stat
          ## save cluster masks for user
          #rmlog $valuefile-clustmask+orig.BRIK  ;# LSB
          #rmlog $valuefile-clustmask+orig.HEAD
        } else { ; }  ;# maybe others

      } else {  ;# leaves extractedvaluestem equals -unset-
        confirmalert "Convert AFNI: unrecognized suffix on Value/MaskFile:\
                  \n\n    $valuefile"
        #return   ;# let pass for manual override
      }

      # forceMSB (paint can directly use BRIKs), optional convert to bfloat
      set outstem $extractedvaluestem  ;# may be -unset-
      if {$extractedvaluestem != "-unset-"} {
        forcebrikMSBfirst \
          $extractedvaluestem nowarn $convertfunctbu "EXTRACT/CONVERT  "
        if {$functscanlists($page,realstatformat) == "bfloat"} {
          set command "$bindir/brik2bfloat $extractedvaluestem $outstem 0"
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
        }
      }
      if {$extractedmaskstem != "-unset-"} {
        forcebrikMSBfirst \
          $extractedmaskstem nowarn $convertfunctbu "EXTRACT/CONVERT  "
        if {$functscanlists($page,realstatformat) == "bfloat"} {
          set command "$bindir/brik2bfloat $extractedmaskstem $outstem 0"
          runacmd "$command" \
            $convertfunctbu "EXTRACT/CONVERT  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
        }
      }

      # save ahead stems for paintcmdbrikmulti
      set functscanlists($page,$valuefile,bfloatstem) $extractedvaluestem
      set functscanlists($page,$valuefile,sbfloatstem) $extractedmaskstem

    } ;# for each extracted valuefile
    set functscanlists($page,bfloatpatt) -multiple-
    set functscanlists($page,phasetype)  ""   ;# so re-addrend not fourier defs
    cdfunctscripts
    set outstem $fullscandir/$outstem ;# for check output below (last set only)
  }

  ### read generated slicecnt,x/ysize,regdat pixsize/thick
  if {$functscanlists($page,realstatformat) == "bfloat"} {
    set slices [llength [glob -nocomplain ${outstem}_???.bfloat]]
    if {!$slices} {
      confirmalert "Stat Images: conversion failed (no .bfloat files found)"
      return
    } else {
      set functscanlists($page,slices) $slices
    }
    set firstheader ${outstem}_000.hdr
    if ![file exists $firstheader] {
      confirmalert "Stat Images: conversion failed (first .hdr file missing)"
      return
    }
    set id [open $firstheader r]
    set lines [split [read $id] "\n"]
    close $id
    set firstline [lindex $lines 0]
      if { [llength $firstline] == 4 } {
      set functscanlists($page,xres) [lindex $firstline 0]
      set functscanlists($page,yres) [lindex $firstline 1]
    }
    if [file exists $fullregdat] {
      set i 0
      set id [open $fullregdat r]
      foreach line [split [read $id] "\n"] {
        if {$i == 1} { set functscanlists($page,inplane) $line }
        if {$i == 2} { set functscanlists($page,thickness) $line }
        incr i
      }
      close $id
    } else {
      confirmalert "Transform: $fullregdat not found  ...convert maybe failed"
    }
  }
  if {$functscanlists($page,realstatformat) == "afnibrik"} { ;# from last
    set functscanlists($page,inplane) [getafniinplane $outstem.HEAD]
    set functscanlists($page,thickness) [getafnithickness $outstem.HEAD]
    set functscanlists($page,slices) [getafnislices $outstem.HEAD]
  }
  writearrayparms $datfile extstat
}

### PAINT button cmd (Fourier, Combine Phase, ExtStats panels)
proc paintcmd { nbwin } {
  global env session iscandir name hemi surfdir
  global origext orig1ext orig2ext whiteext
  global cmdlog paintbu
  global sessionscanlists functscanlists renderscanlists
  global realname complexname statname amprealname ampcomplexname
  global realfname realfclustname realpclustname cplxstatname1 realpname
  global cplxstatname7
  global force bindir datfile

  if [checkconcurrent] { return }
  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  if { [checknamefile] != "match" } { return }
  set iscandir $page

  ### handle brikmulti separately: bfloatstems from multilist, not bfloatpatt
  # N.B.: paintcmd on multiple panels, statformat=brikmulti still after Unset
  if { [info exists functscanlists($page,statformat)] &&
       $functscanlists($page,statformat) == "brikmulti" &&
       [info exists sessionscanlists($page,type)] &&
       $sessionscanlists($page,type) == "extstatscan" } {
    paintcmdbrikmulti $page
    return
  }

  ### special case flag for real .mgz 'stat' volume for Ext Stats (e.g., qT1)
  set realmgzinput 0
  # N.B.: paint accepts pair cplx mgz's, but fourier can't make, no accept here
  if { [info exists functscanlists($page,statformat)] &&
       $functscanlists($page,statformat) == "mgzsingle" &&
       [info exists sessionscanlists($page,type)] &&
       $sessionscanlists($page,type) == "extstatscan" } {
    set realmgzinput 1
  }

  ### check bfloatpatt variable (N.B.: includes suffix but *no* infixes)
  #  --bfloatpatt set by: fouriercmd,deconvcmd,select_statimage
  #  --bfloatpatt cp'd by: addfieldscan,sigaveragecmd
  #  --bfloatpatt not set by: surfaveragecmd (no paint)
  #  --bfloatpatt ignored by: paintcmdbrikmulti (replaced by valuefile array)
  if ![info exists functscanlists($page,bfloatpatt)] {
    confirmalert "Paint: 3D stat imageset not made  ...analyze or import first"
    return
  }
  set bfloatpatt $functscanlists($page,bfloatpatt)  ;# no infix
  if {$bfloatpatt == "-multiple-"} {
    confirmalert "Paint: re-run analysis (or extract/convert) before painting"
    return
  }
  # next to catch badly reset bfloatpatt (but confusing w/o infix)
  set statsuff [file extension $bfloatpatt]
  if { $statsuff != ".bfloat" && $statsuff != ".BRIK" } {
    if { !$realmgzinput || $statsuff != ".mgz" } {  ;# let through mgz real
      confirmalert "Paint: bad suffix on stat input pattern:\
                    \n\n    \"$bfloatpatt\"\
                    \n\n(not .bfloat or .BRIK)"
    }
  }

  ### make fullstem, get stattype (csurf internal, not attached to widget)
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  if ![info exists functscanlists($page,stattype)] {
    set functscanlists($page,stattype) real
  }
  set stattype $functscanlists($page,stattype)

  ### bak compat (default missing csurf.dat parms)
  # for old config'd pre-phasestatformat scan w/1st action PAINT
  if ![info exists functscanlists($page,phasestatformat)] {
    if { [glob -nocomplain $fullscandir/*.BRIK] != "" } { ;# 1st match any BRIK
      set functscanlists($page,phasestatformat) afnibrik 
    }
    if { [glob -nocomplain $fullscandir/*_000.bfloat] != "" } { ;#bfloat overrd
      set functscanlists($page,phasestatformat) bfloat
    }
  }
  set phasestatformat $functscanlists($page,phasestatformat)
  # for old config'd pre-permtestcnt/samevtxthickflag scan w/1st action PAINT
  foreach parm { permtestcnt samevtxthickflag paintext normdsampuniqvtxflag \
                 normdsampsearchflag normdsampuniqvoxflag normdsampallflag } {
    if ![info exists functscanlists($page,$parm)] {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }

  ### check inputs
  set bfloatstem [stripbpatt $bfloatpatt]
  set infix ""
  if {$stattype == "complex"} { set infix $realname }  ;# first only
  # N.B.: fourier *output* phasestatformat here means paint *input* stat type
  if {$phasestatformat == "bfloat"} {
    set firstslice $fullscandir/${bfloatstem}${infix}_000.bfloat
  }
  if {$phasestatformat == "afnibrik"} {
    set firstslice $fullscandir/${bfloatstem}${infix}+orig.BRIK
  }
  # override default afnibrik -- currently only .mgz (TODO: .mgh)
  if {$realmgzinput} {
    if {$stattype == "complex"} {
      confirmalert "Paint: can't (yet) use mgzfile for complex-valued input\
                    \n(and fourier.c doesn't \[yet\] make mgzfiles)"
      return
    }
    set firstslice $fullscandir/${bfloatstem}.mgz
  }
  if ![file exists $firstslice] {
    confirmalert "Paint: $firstslice not found"
    return
  }
  if {$stattype == "complex"} {
    # skip paint complex raw amplitude (new def output of fourier) if missing
    set skipamp 0
    if {$phasestatformat == "bfloat"} {
      set firstampslice $fullscandir/${bfloatstem}${amprealname}_000.bfloat
    }
    if {$phasestatformat == "afnibrik"} {
      set firstampslice $fullscandir/${bfloatstem}${amprealname}+orig.BRIK
    }
    if { !$force && ![file exists $firstampslice] } {
      putlog "Paint: ### 3D raw fourier amp not found (fix: redo curr FOURIER)"
      putlog "  ...skip paint amp ($amprealname,$ampcomplexname)"
      set skipamp 1
    }
    # skip paint 3D _f (newer def output of fourier) if missing
    set paint-3D_f 1
    if {$phasestatformat == "bfloat"} {
      set firstampslice $fullscandir/${bfloatstem}${realfname}_000.bfloat
    }
    if {$phasestatformat == "afnibrik"} {
      set firstampslice $fullscandir/${bfloatstem}${realfname}+orig.BRIK
    }
    if { !$force && ![file exists $firstampslice] } {
      putlog "Paint: ### 3D F-stats not found (fix: redo current FOURIER)"
      putlog "  ...skip paint 3D F (paint will mk by squaring cplx _r,_i amp)"
      set paint-3D_f 0
    }
    # skip paint coherence _c (newer def outp fourier) if missing (bakcompat)
    set paint_coher 1
    if {$phasestatformat == "bfloat"} {
      set firstampslice $fullscandir/${bfloatstem}${cplxstatname7}_000.bfloat
    }
    if {$phasestatformat == "afnibrik"} {
      set firstampslice $fullscandir/${bfloatstem}${cplxstatname7}+orig.BRIK
    }
    if { !$force && ![file exists $firstampslice] } {
      putlog "Paint: ### 3D coherence not found (fix: redo current FOURIER)"
      putlog "  ...skip paint 3D coherence (_c)"
      set paint_coher 0
    }
  }
  if {$functscanlists($page,samevtxthickflag)} {
    set pial $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.pial
    if ![file exists $pial] { confirmalert "Paint: $pial not found"; return }
  }
  # register.dat
  set fullregdat $fullscandir/$functscanlists($page,regdat)
  if ![file exists $fullregdat] {
    confirmalert "Paint: Transform file: $fullregdat not found"
    return
  }
  set i 0
  set id [open $fullregdat r]
  foreach line [split [read $id] "\n"] {
    if {$i == 0} { set regdatname $line }
    incr i
  } 
  close $id
  if {$regdatname != $name} {
    confirmalert "Paint: subject name:\n\n    $regdatname\
              \n\nin transformation matrix file:\n\n    $fullregdat\
              \n\ndoesn't match currently linked subject name\
                \n(in file: $env(FUNCTIONALS_DIR)/$session/name):\
              \n\n    $name\
              \n\nTo synchronize transformation matrix files\
                \nfor currently linked subject (e.g., after\
                \nmanual edit of \"name\" file), go to Setup\
                \nAlign/Funct panel, open each functional\
                \nregistration, and click SAVEREG"
    return
  }
  # weird paint surface suffix
  set paintext $functscanlists($page,paintext)
  if {!$force} {
    if {$paintext != $origext && $paintext != $orig1ext &&
        $paintext != $orig2ext && $paintext != $whiteext} {
      confirmalert "Paint: Non-default surface:\n\n    $paintext\
                \n\nfor sampling 3D data.  Default sample surfaces:\
                \n\n    $origext, $whiteext, $orig1ext, $orig2ext"
    }
  }
  # permtest (AFNI only, check missing p)
  if {$functscanlists($page,permtestcnt)} {
    if {!$force && $phasestatformat != "afnibrik"} { ;# force: also skips below
      confirmalert "Paint: Permutation test requires Stat Format: afnibrik"
      return
    }
    set firstpvalslice $fullscandir/${bfloatstem}${realpname}+orig.BRIK
    if { !$force && ![file exists $firstpvalslice] } {
      confirmalert "Paint: _p BRIK from permutation test:\
                \n\n  $firstpvalslice\n\nnot found"
      return
    }
  }
  # check thickness file before paint cmd fails (b/c new default=frac)
  if { $functscanlists($page,paintnormtype) == "frac" } {
    if {$hemi == "both"} {
      set thkfile $env(SUBJECTS_DIR)/$name/surf/rh.thickness
    } else {
      set thkfile $env(SUBJECTS_DIR)/$name/surf/$hemi.thickness
    }
    if ![file exists $thkfile] {
      confirmalert "Paint: cortical thickness file:\
                \n\n    $thkfile\
                \n\nrequired for vertex normal type \"frac\" is missing.\
                \n\nCreate thickness file or use NormSearch type \"mm\"\
                  \n(at bottom of Setup Align/Funct Scans panel)"
      return
    }
  }

  ### check output overwrite (first only)
  set hemisaved $hemi
  set hemilist ""
  foreach hemi { rh lh } {
    if [file exists $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$paintext] {
      set hemilist "$hemilist $hemi"
    }
  }
  if { [llength $hemilist] == 0 } {
    confirmalert "Paint: no surfaces ending in .${paintext} found"
    set hemi $hemisaved
    return
  }
  if {!$force} {
    if { [llength $hemilist] == 1 } {
      confirmalert "Paint: N.B.: only painting: $hemilist"
    }
  }
  set infix ""
  if {$stattype == "complex"} { set infix $realname }  ;# first only
  set firstout $fullscandir/${bfloatstem}${infix}-${hemi}.w
  if {!$force} {
    if { [file exists $firstout] } {
      if ![okreplace $firstout "$firstout exists--Redo Paint?" "Redo"] {
        confirmalert "Paint: painted vertex files not altered (may be stale)"
        set hemi $hemisaved
        return
      }
    }
  }

  ### get paint parms
  set infix ""
  if {$stattype == "complex"} { set infix $realname }  ;# first only
  # slices (count bfloat, AFNI HEAD, or mgz)
  if {$phasestatformat == "bfloat"} {
    set slices [llength \
     [glob -nocomplain $fullscandir/${bfloatstem}${infix}_???.bfloat]]
  }
  if {$phasestatformat == "afnibrik"} {
    set header $fullscandir/${bfloatstem}${infix}+orig.HEAD
    set slices [getafnislices $header]
  }
  if {$realmgzinput} {  ;# special case override
    set slices [getmgzslices $fullscandir/${bfloatstem}${infix}.mgz]
  }
  # inplane, thickness
  set i 0
  set id [open $fullregdat r]
  foreach line [split [read $id] "\n"] {
    if {$i == 1} { set inplane $line }
    if {$i == 2} { set thickness $line }
   incr i
  } 
  close $id
  set functscanlists($page,slices) $slices
  set functscanlists($page,inplane) $inplane
  set functscanlists($page,thickness) $thickness
  # norm search parms
  if { $functscanlists($page,paintnormtype) == "mm" } {
    set normsearch "-dmin $functscanlists($page,paintdmin) \
                    -dmax $functscanlists($page,paintdmax) \
                    -dstep $functscanlists($page,paintdstep) \
                    -normop $functscanlists($page,paintnormop)"
  } elseif { $functscanlists($page,paintnormtype) == "frac" } {
    set normsearch "-dfracmin $functscanlists($page,paintdmin) \
                    -dfracmax $functscanlists($page,paintdmax) \
                    -dstep $functscanlists($page,paintdstep) \
                    -normop $functscanlists($page,paintnormop)"
  } else {
    confirmalert "Paint: unknown vtx norm search option:\
              \n\n$functscanlists($page,paintnormtype)"
    return
  }
  if {$functscanlists($page,samevtxthickflag)} {
    set normsearch "$normsearch -samevtx pial"
  }
  if {$functscanlists($page,normdsampuniqvtxflag)} {
    set normsearch "$normsearch -uniqsampvtxs"
  }

  ### go paint
  if {$stattype == "complex"} {  ;# process pairs for each hemi (need phase)
    foreach hemi { rh lh } {  ;# complex paint: two inputs => two outputs
      foreach phtype { amp sig } {
        if {$phtype == "amp" && $skipamp} { continue }
        if {$phtype == "amp" } {set rfix $amprealname;set ifix $ampcomplexname}
        if {$phtype == "sig" } {set rfix $realname;   set ifix $complexname}
        set fulloutvert1 $fullscandir/${bfloatstem}${rfix}-$hemi.w
        set fulloutvert2 $fullscandir/${bfloatstem}${ifix}-$hemi.w
        if {$phasestatformat == "bfloat"} {
          set fullbfloatpatt1 $fullscandir/${bfloatstem}${rfix}_%03d.bfloat
          set fullbfloatpatt2 $fullscandir/${bfloatstem}${ifix}_%03d.bfloat
        }
        if {$phasestatformat == "afnibrik"} {
          set fullbfloatpatt1 $fullscandir/${bfloatstem}${rfix}+orig.BRIK
          set fullbfloatpatt2 $fullscandir/${bfloatstem}${ifix}+orig.BRIK
        }
        set trunc ""
        if {$functscanlists($page,filetruncphaseflag)} {
          set trunc "-truncphase \
            $functscanlists($page,$hemi,truncphasemin) \
            $functscanlists($page,$hemi,truncphasemax) \
            $functscanlists($page,truncslope)"
        }
        set allvert ""
        if {$functscanlists($page,allverticesflag)} {
          set allvert "-allvertices"
        }
        set fstatarg "-nofstat"  ;# override paint.c default
        ## only tell paint to mk _f wfile from sqrtf if no 3D _f (old session)
        if { !${paint-3D_f} &&
             [string match *${realname}-$hemi.w    $fulloutvert1] &&
             [string match *${complexname}-$hemi.w $fulloutvert2] } {
          set fstatarg "-fstat"
          putlog \
 "Paint: ### paint will mk _f wfile by squaring sqrtF cplx amp of _r,_i wfiles"
          putlog "       ### N.B.: fix: re-run current FOURIER to get 3D _f"
        }
        set command "$bindir/paint \
          -complex \
            [backslashspaces $fullbfloatpatt1] \
            [backslashspaces $fullbfloatpatt2] \
          $hemi \
          $paintext \
          [backslashspaces $fulloutvert1] \
          [backslashspaces $fulloutvert2] \
          -frame 0 \
          -nslices $functscanlists($page,slices) \
          -regdat [backslashspaces $fullregdat] \
          $normsearch \
          $allvert \
          $trunc \
          $fstatarg"
        runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      } ;# two complex pairs

      ## paint F-stats derived from complex (biffed: 1/6/11 -- err every run!)
      #set fulloutvert $fullscandir/${bfloatstem}${statname}-$hemi.w
      #set fullbfloatpatt \
      #  $fullscandir/${bfloatstem}${statname}_%03d.bfloat
      #set command "$bindir/paint $fullbfloatpatt $hemi $paintext \
      #  $fulloutvert -frame 0 -nslices $functscanlists($page,slices) \
      #  -regdat $fullregdat $normsearch"
      #runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
      #tkwait variable cmdpid

      ## if 3D _f exists, surfsample it (vs. have paint square already-samp'd)
      if {${paint-3D_f}} {
        if {$phasestatformat == "bfloat"} {
          set fullbfloatpatt1 $fullscandir/${bfloatstem}${realfname}_%03d.bfloat
        }
        if {$phasestatformat == "afnibrik"} {
          set fullbfloatpatt1 $fullscandir/${bfloatstem}${realfname}+orig.BRIK
        }
        set fulloutvert1 $fullscandir/${bfloatstem}${realfname}-$hemi.w
        set command "$bindir/paint \
          -real [backslashspaces $fullbfloatpatt1] \
          $hemi \
          $paintext \
          [backslashspaces $fulloutvert1] \
          -frame 0 \
          -nslices $functscanlists($page,slices) \
          -regdat [backslashspaces $fullregdat] \
          $normsearch \
          $allvert \
          $trunc \
          $fstatarg"
        runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }
      ## if 3D coherence (_c) exists, surfsample it (bakcompat)
      if {$paint_coher} {
        if {$phasestatformat == "bfloat"} {
          set fullbfloatpatt1 \
            $fullscandir/${bfloatstem}${cplxstatname7}_%03d.bfloat
        }
        if {$phasestatformat == "afnibrik"} {
          set fullbfloatpatt1 \
            $fullscandir/${bfloatstem}${cplxstatname7}+orig.BRIK
        }
        set fulloutvert1 $fullscandir/${bfloatstem}${cplxstatname7}-$hemi.w
        set command "$bindir/paint \
          -real [backslashspaces $fullbfloatpatt1] \
          $hemi \
          $paintext \
          [backslashspaces $fulloutvert1] \
          -frame 0 \
          -nslices $functscanlists($page,slices) \
          -regdat [backslashspaces $fullregdat] \
          $normsearch \
          $allvert \
          $trunc \
          $fstatarg"
        runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }
    } ;# hemis
  } else {  ;# one per hemi
    foreach hemi { rh lh } {
      set fulloutvert $fullscandir/${bfloatstem}-$hemi.w
      if {$phasestatformat == "bfloat"} {
        set fullbfloatpatt $fullscandir/${bfloatstem}_%03d.bfloat
      }
      if {$phasestatformat == "afnibrik"} {
        set fullbfloatpatt $fullscandir/${bfloatstem}+orig.BRIK
      }
      if {$realmgzinput} {  ;# special case override phasestatformat
        set fullbfloatpatt $fullscandir/${bfloatstem}.mgz
      }
      set allvert ""
      if {$functscanlists($page,allverticesflag)} {
        set allvert "-allvertices"
      }
      set command "$bindir/paint \
        [backslashspaces $fullbfloatpatt] $hemi $paintext \
        [backslashspaces $fulloutvert] \ 
        -frame 0 \
        -frame $functscanlists($page,bskip) \
        -nslices $functscanlists($page,slices) \
        -regdat [backslashspaces $fullregdat] \
        $allvert \
        $normsearch"
      runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
    }
  }
  set hemi $hemisaved

  ### also paint permtest _p (redundant: -log10 of cplxamp of _r,_i)
  ## permtest fourier cmdline:
  # polletdilima1-1.7-vreg+orig.BRIK polletdilima1-1.7-vreg+orig
  # -nslices 30 -reps 512 -imres 96 96 -statres 96 96 -stimcyc 8 -infixes _r _i
  # -freqsurr 3 -1 -omitfreq -1 -permtestcnt 5000 -phasetype 1 -sigoutbrik -fout
  ## permtest fourier outfiles: 
  # polletdilima1-1.7-vreg+orig_x+orig.BRIK
  # polletdilima1-1.7-vreg+orig_y+orig.BRIK
  # polletdilima1-1.7-vreg+orig_r+orig.BRIK  => N.B.: cplxamp is perm -log10(p)
  # polletdilima1-1.7-vreg+orig_i+orig.BRIK  => N.B.: cplxamp is perm -log10(p)
  # polletdilima1-1.7-vreg+orig_f+orig.BRIK  => N.B.: *pre*-perm F
  # polletdilima1-1.7-vreg+orig_p+orig.BRIK  => N.B.: perm -log10(p): redundant
  ### (1) overwrite paint-made '_f' wfile (amp(r,i) => -log10(p)) w/real 3D _f
  ### (2) paint _p directly made by permtest (N.B.: not from 3D _f above!)
  if {$stattype == "complex" && $functscanlists($page,permtestcnt) > 0} {
    foreach hemi { rh lh } {
      foreach infix "$cplxstatname1 $realpname" {  ;# _f, _p
        set fulloutvert $fullscandir/${bfloatstem}${infix}-$hemi.w
        if {$phasestatformat != "afnibrik"} { continue }  ;# gets here if force
        set fullbfloatpatt $fullscandir/${bfloatstem}${infix}+orig.BRIK
        set allvert ""
        if {$functscanlists($page,allverticesflag)} {set allvert "-allvertices"}
        set command "$bindir/paint \
          [backslashspaces $fullbfloatpatt] $hemi $paintext \
          [backslashspaces $fulloutvert] \ 
          -frame 0 \
          -nslices $functscanlists($page,slices) \
          -regdat [backslashspaces $fullregdat] \
          $allvert \
          $normsearch"
        runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }
    }
  }

  ### after paint, save bfloatstem (made from bfloatpatt) ahead to render
  set renderscanlists($page,bfloatstem) $bfloatstem

  ### if complex, run surfclust on new (Jul2013) _f output of paint (if there)
  if {$stattype == "complex" && $functscanlists($page,clustarea) > 0.0} {
    foreach hemi { rh lh } {
      ### run surfclust on _f (to make _h)
      set fullinvtx $fullscandir/${bfloatstem}${realfname}-$hemi.w
      if { ![file exists $fullinvtx] } {
        if {!$force} {
          confirmalert "Surf Cluster: infile missing:\
                    \n\n    $fullinvtx\
                    \n\nIf older sess, re-run FOURIER, re-try PAINT"
        }
        continue
      }
      cd $fullscandir
      set locinstem ${bfloatstem}${realfname}        ;# _f, made by new paint
      set locoutstem ${bfloatstem}${realfclustname}  ;# _h (like cross subj)
      set command "$bindir/surfclust \
        -instem $locinstem \
        -name $name \
        -outstem $locoutstem \
        -hemi $hemi \
        -threshabs \
        -thresh $functscanlists($page,preclustfthr) \
        -minarea $functscanlists($page,clustarea) \
        -surf smoothwm"
      runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
      ### if permtest, also run surfclust on _p (to make _q, _p made directly)
      if { [info exists functscanlists($page,permtestcnt)] &&
           $functscanlists($page,permtestcnt) > 0 } {
        set fullinvtx $fullscandir/${bfloatstem}${realpname}-$hemi.w
        if { ![file exists $fullinvtx] } {
          if {!$force} {
            confirmalert "Surf Cluster: permute test infile missing:\
                      \n\n    $fullinvtx\
                      \n\nRun FOURIER if not yet run, re-try PAINT"
          }
          continue
        }
        cd $fullscandir
        set locinstem ${bfloatstem}${realpname}        ;# _p, made by fourier
        set locoutstem ${bfloatstem}${realpclustname}  ;# _q
        set command "$bindir/surfclust \
          -instem $locinstem \
          -name $name \
          -outstem $locoutstem \
          -hemi $hemi \
          -threshabs \
          -thresh $functscanlists($page,preclustfthr) \
          -minarea $functscanlists($page,clustarea) \
          -surf smoothwm"
        runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }
    }
    cdfunctscripts
  } else {
    if {!$force} {confirmalert "Surf Cluster: 2D surfclust skipped"}
  }

#xxxxxxxxxxxxx -- could run FDR in paintcmd
# need: smoothsteps, smoothtype, desiredFDR, noisedf
# FDR: smooth=___,  v/w switch, noisedf=___, FDR=____, p=___

  ### user feedback, record
  if {$stattype == "real"} {
    set functscanlists($page,rh,wfile) ${bfloatstem}-rh.w
    set functscanlists($page,lh,wfile) ${bfloatstem}-lh.w
  }
  if {$stattype == "complex"} {
    set infixes "$realname,$complexname,$amprealname,$ampcomplexname,$realfname"
    if {$functscanlists($page,clustarea) > 0.0} {
      set infixes "$infixes,$realfclustname"
    }
    set infixes "$infixes,$cplxstatname7"
    set functscanlists($page,rh,wfile) ${bfloatstem}{$infixes}-rh.w
    set functscanlists($page,lh,wfile) ${bfloatstem}{$infixes}-lh.w
  }

  writearrayparms $datfile calcfour  ;# any funct aspect writes all
}

### PAINT button cmd replacement (ExtStats panel, brikmulti statformat only)
proc paintcmdbrikmulti { page } {
  global cmdlog paintbu
  global name env session iscandir hemi
  global bindir force datfile
  global surfdir origext orig1ext orig2ext whiteext
  global functscanlists renderscanlists

  set iscandir $page
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  set sortedvaluefilelist ""
  foreach valuefile [getsortedvaluefilelist $page] {
    if {$functscanlists($page,$valuefile,extractflag)} { ;# implies not -unset-
      lappend sortedvaluefilelist $valuefile
    }
  }
  if {$sortedvaluefilelist == ""} {
    confirmalert "Multi Paint: no extracted valuefiles to paint"
    return
  }
  set firstvaluefile [lindex $sortedvaluefilelist 0]
  set firstbfloatstem $functscanlists($page,$firstvaluefile,bfloatstem)

  # bak compat: for old config'd pre-realstatformat scan w/1st action PAINT
  if ![info exists functscanlists($page,realstatformat)] {
    set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
    if { [glob -nocomplain $fullscandir/*_000.bfloat] != "" } { ;# req done
      set functscanlists($page,realstatformat) bfloat  ;# def now afnibrik
    } else {
      set functscanlists($page,realstatformat) \
          $functscanlists(def,realstatformat)
    }
  }
  # for old config'd pre-permtestcnt/samevtxthickflag scan w/1st action PAINT
  foreach parm { permtestcnt samevtxthickflag paintext normdsampuniqvtxflag \
                 normdsampsearchflag normdsampuniqvoxflag normdsampallflag } {
    if ![info exists functscanlists($page,$parm)] {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }

  # check input
  if {$functscanlists($page,realstatformat) == "bfloat"} {
    set firstslice $fullscandir/${firstbfloatstem}_000.bfloat
  }
  if {$functscanlists($page,realstatformat) == "afnibrik"} {
    set firstslice $fullscandir/${firstbfloatstem}.BRIK  ;# stem has +orig
  }
  if ![file exists $firstslice] {
    confirmalert "Multi Paint: $firstslice not found"
    return
  }
  set fullregdat $fullscandir/$functscanlists($page,regdat)
  if ![file exists $fullregdat] {
    confirmalert "Multi Paint: Transform file: $fullregdat not found"
    return
  }
  set paintext $functscanlists($page,paintext)

  if {$paintext != $origext && $paintext != $orig1ext &&
      $paintext != $orig2ext && $paintext != $whiteext} {
    confirmalert "Multi Paint: Non-default surface:\
              \n\n    $paintext\
              \n\nfor sampling 3D data.  Default sample surfaces:\
              \n\n    $origext, $whiteext"
  }
  # check thickness file before paint cmd fails (b/c new default=frac)
  if { $functscanlists($page,paintnormtype) == "frac" } {
    if {$hemi == "both"} {
      set thkfile $env(SUBJECTS_DIR)/$name/surf/rh.thickness
    } else {
      set thkfile $env(SUBJECTS_DIR)/$name/surf/$hemi.thickness
    }
    if ![file exists $thkfile] {
      confirmalert "Multi Paint: cortical thickness file:\
                \n\n    $thkfile\
                \n\nrequired for vertex normal type \"frac\" is missing.\
                \n\nCreate thickness file or use NormSearch type \"mm\"\
                  \n(at bottom of Import External 3D Statistics panel)"
      return
    }
  }

  # check output, overwrite
  set hemisaved $hemi
  set hemi rh
  set paintsurf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$paintext
  if ![file exists $paintsurf] {
    confirmalert "Multi Paint: surface to paint onto: $paintsurf not found"
    set hemi $hemisaved
    return
  }
  set multiprefix $functscanlists($page,multiprefix)  ;# only paint output
  set multiinfix $functscanlists($page,multiinfix)    ;# only paint output
  set firstout \
    $fullscandir/${multiprefix}${firstbfloatstem}${multiinfix}-${hemi}.w
  if {!$force} {
    if { [file exists $firstout] } {
      if [okreplace $firstout "$firstout exists--Redo Paint?" "Redo"] {
      } else {
        confirmalert \
          "Multi Paint: painted vertex files not altered (may be stale)"
        set hemi $hemisaved
        return
      }
    }
  }

  # get paint parms from counting bfloat files or HEAD, and register.dat
  if {$functscanlists($page,realstatformat) == "bfloat"} {
    set slices \
      [llength [glob -nocomplain $fullscandir/${firstbfloatstem}_???.bfloat]]
  }
  if {$functscanlists($page,realstatformat) == "afnibrik"} {
    set header $fullscandir/${firstbfloatstem}.HEAD
    set slices [getafnislices $header]
  }
  set i 0
  set id [open $fullregdat r]
  foreach line [split [read $id] "\n"] {
    if {$i == 1} { set inplane $line }
    if {$i == 2} { set thickness $line }
    incr i
  }
  close $id
  set functscanlists($page,slices) $slices
  set functscanlists($page,inplane) $inplane
  set functscanlists($page,thickness) $thickness

  if { $functscanlists($page,paintnormtype) == "mm" } {
    set normsearch "-dmin $functscanlists($page,paintdmin) \
                    -dmax $functscanlists($page,paintdmax) \
                    -dstep $functscanlists($page,paintdstep) \
                    -normop $functscanlists($page,paintnormop)"
  } elseif { $functscanlists($page,paintnormtype) == "frac" } {
    set normsearch "-dfracmin $functscanlists($page,paintdmin) \
                    -dfracmax $functscanlists($page,paintdmax) \
                    -dstep $functscanlists($page,paintdstep) \
                    -normop $functscanlists($page,paintnormop)"
  } else {
    confirmalert "Paint: unknown vtx norm search option:\
              \n\n    $functscanlists($page,paintnormtype)"
    return
  }
  if {$functscanlists($page,samevtxthickflag)} {
    set normsearch "$normsearch -samevtx pial"
  }
  if {$functscanlists($page,normdsampuniqvtxflag)} {
    set normsearch "$normsearch -uniqsampvtxs"
  }

  ### paint based on bfloatstems currently in array (check sbfloatstem)
  foreach hemi { rh lh } {
    foreach valuefile $sortedvaluefilelist {  ;# each extracted line
#xxx -- N.B.: won't paint if main valuefile suffix unrec'd in convertfunctcmd
      if { [info exists functscanlists($page,$valuefile,bfloatstem)] &&
           $functscanlists($page,$valuefile,bfloatstem) != "-unset-"} {
        # coef (opt mask-by-clust) or stats (opt thresh, or selfmask by clust)
        set bfloatstem $functscanlists($page,$valuefile,bfloatstem)
        if {$functscanlists($page,realstatformat) == "bfloat"} {
          set firstslice     $fullscandir/${bfloatstem}_000.bfloat
          set fullbfloatpatt $fullscandir/${bfloatstem}_%03d.bfloat
        }
        # N.B.: bfloatstem already ends in +orig (added by convertfunctcmd)
        if {$functscanlists($page,realstatformat) == "afnibrik"} {
          set firstslice     $fullscandir/${bfloatstem}.BRIK
          set fullbfloatpatt $fullscandir/${bfloatstem}.BRIK  ;# literal, same
        }
        if ![file exists $firstslice] {
	  confirmalert "Multi Paint: extracted file to paint:\
                    \n\n    $firstslice\n\nnot found"
          set hemi $hemisaved
	  return
        }
        set fulloutvert \
          $fullscandir/${multiprefix}${bfloatstem}${multiinfix}-$hemi.w
        set command "$bindir/paint \
          [backslashspaces $fullbfloatpatt] \
          $hemi \
          $paintext \
          [backslashspaces $fulloutvert] \
          -frame 0 \
          -nslices $functscanlists($page,slices) \
          -regdat [backslashspaces $fullregdat] \
          $normsearch"
        runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }

      # maybe clustered stats for live tksurfer mask
      if { $functscanlists($page,$valuefile,clusterflag) &&
           [info exists functscanlists($page,$valuefile,sbfloatstem)] &&
           $functscanlists($page,$valuefile,sbfloatstem) != "-unset-" } {
        set sbfloatstem $functscanlists($page,$valuefile,sbfloatstem)
        if {$functscanlists($page,realstatformat) == "bfloat"} {
          set firstslice      $fullscandir/${sbfloatstem}_000.bfloat
          set fullsbfloatpatt $fullscandir/${sbfloatstem}_%03d.bfloat
        }
        # N.B.: sbfloatstem already ends in +orig (added by convertfunctcmd)
        if { $functscanlists($page,realstatformat) == "afnibrik" } {
          set firstslice      $fullscandir/${sbfloatstem}.BRIK
          set fullsbfloatpatt $fullscandir/${sbfloatstem}.BRIK  ;# literal,same
        }
        if ![file exists $firstslice] {
          confirmalert "Multi Paint: extracted file to paint:\
                    \n\n    $firstslice\n\nnot found"
          set hemi $hemisaved
	  return
        }
        set fulloutvert \
          $fullscandir/${multiprefix}${sbfloatstem}${multiinfix}-$hemi.w
        set command "$bindir/paint \
          [backslashspaces $fullsbfloatpatt] \
          $hemi \
          $paintext \
          [backslashspaces $fulloutvert] \
          -frame 0 \
          -nslices $functscanlists($page,slices) \
          -regdat [backslashspaces $fullregdat] \
          $normsearch"
        runacmd "$command" $paintbu "PAINT  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }
    }
  }
  set hemi $hemisaved

  # after multipaint, save ahead bfloatstem (or dummy if many) to renderlist
  if { [llength $sortedvaluefilelist] == 1 } {
    set renderscanlists($page,bfloatstem) \
      ${multiprefix}${firstbfloatstem}${multiinfix}
    #rgbname set by samestem
    set renderscanlists($page,renderlisttype) one
  } else {
    set renderscanlists($page,bfloatstem) -multiple-
    set renderscanlists($page,rgbname)    -multiple-
    set renderscanlists($page,renderlisttype) last
  }
  set renderscanlists($page,samestem) 1  ;# repaint biffs hand-edited stems

  # user feedback, record
  set printlist ${multiprefix}${firstbfloatstem}${multiinfix}
  foreach valuefile [lrange $sortedvaluefilelist 1 end] {
    if {$functscanlists($page,$valuefile,bfloatstem) != "-unset-"} {
      set bfloatstem $functscanlists($page,$valuefile,bfloatstem)
      set printlist $printlist,${multiprefix}${bfloatstem}${multiinfix}
    }
  }
  set functscanlists($page,rh,wfile) \{$printlist\}-rh.w
  set functscanlists($page,lh,wfile) \{$printlist\}-lh.w

  writearrayparms $datfile calcfour  ;# any funct aspect writes all
}

#xxxxxxxxxxx
#done to here: confirmalert backslashes regularized, logic backslashes rm'd

### SURFCOMBINE button command (Combine Surface Stats panel)
proc surfaveragecmd { nbwin } {
  global env session iscandir name tmpdir  ;# keep hemi local
  global cmdlog surfaveragebu
  global functscanlists renderscanlists
  global realname complexname amprealname ampcomplexname
  global force bindir datfile

  if [checkconcurrent] { return }
  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  set iscandir $page   ;# put back after reset by set session traces

  # check setup
  if { [llength $functscanlists($page,surftoavgbigstems)] < 2 } {
    confirmalert "Surf Combine: first select at least 2 scans to combine"
    return
  }
  set surfoperation $functscanlists($page,surfoperation)
  if {$surfoperation != "realaverage" && $surfoperation != "phaseavg-ecc" && \
      $surfoperation != "phaseavg-pol" && $surfoperation != "phaseavg-two"} {
    confirmalert "Surf Combine: unknown operation: $surfoperation"
    return
  }
  if {$surfoperation == "realaverage"} {
    set stattype real
    set phasetype ""
  } 
  if {$surfoperation == "phaseavg-ecc"} {
    set stattype complex
    set phasetype eccen
  }
  if {$surfoperation == "phaseavg-pol"} {
    set stattype complex
    set phasetype polar
  }
  if {$surfoperation == "phaseavg-two"} {
    set stattype complex
    set phasetype 2cond
  }
  set functscanlists($page,stattype) $stattype
  set functscanlists($page,phasetype) $phasetype
  if {$stattype == "real"}    { set infixlist "" }
  if {$stattype == "complex"} {
    set infixlist "$realname $complexname $amprealname $ampcomplexname"
  }

  # check all input wfiles, OK if _x,_y missing
  set skipamp 0
  foreach bigstem $functscanlists($page,surftoavgbigstems) {
    foreach hemi { rh lh } {
      foreach infix $infixlist {
        set infile "$env(FUNCTIONALS_DIR)/${bigstem}${infix}-$hemi.w"
        if ![file exists $infile] {
          if {$infix == $realname || $infix == $complexname} {
            confirmalert "Surf Combine: missing input file: $infile"
            return
          } else {
            set skipamp 1
          }
        }
      }
    }
  }
  if {$stattype == "complex" && $skipamp} {
    putlog "SurfAverage: at least one raw fourier amp wfile not found"
    putlog "  ...skip surface average amp ($amprealname,$ampcomplexname)"
  } else {
    putlog "SurfAverage: average raw amp, too ($amprealname,$ampcomplexname)"
  }

  # check first output file overwrite
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  ## alternate concatenated bfloatstem convention -> not implemented, too long
  #set inbfloatstemlist ""
  #set bfloatstem ""
  #foreach bigstem $functscanlists($page,surftoavgbigstems) {
  #  lappend inbfloatstemlist $env(FUNCTIONALS_DIR)/$bigstem
  #  if {$bfloatstem == ""} {
  #    set bfloatstem [file tail $bigstem]
  #  } else {
  #    set bfloatstem "${bfloatstem}_[file tail $bigstem]"
  #  }
  #}
  set bfloatstem [lindex [split $iscandir "/"] 1]
  set firstout $fullscandir/${bfloatstem}${realname}-$hemi.w
  if {!$force} {
    if { [file exists $firstout] } {
      if [okreplace $firstout "$firstout exists--Redo Surf Combine?" "Redo"] {
      } else {
        confirmalert \
          "Surf Combine: surfcombine vertex files not altered (may be stale)"
        return
      }
    }
  }

  foreach hemi { rh lh } {
    if {$functscanlists($page,surfavgscriptflag)} {
      ### surfcombine
      #TODO: test surfavg w/surfcombine
      set scomfile $fullscandir/${bfloatstem}-$hemi.scom
      if {$functscanlists($page,mksurfavgscriptflag)} {
        if [file exists $scomfile] { mvlog $scomfile $scomfile~ }
        set incnt [llength $functscanlists($page,surftoavgbigstems)]
        if {$surfoperation == "realaverage"} {
          set id [open $scomfile w 0644]
          puts $id "setdir $env(FUNCTIONALS_DIR)"
          foreach bigstem $functscanlists($page,surftoavgbigstems) {
            puts $id "read_real ${bigstem}-$hemi.w"
          }
          puts $id "average_real $incnt"
          puts $id "write_real $fullscandir/${bfloatstem}-$hemi.w"
          close $id
        }
        if {$surfoperation == "phaseavg-ecc" || \
            $surfoperation == "phaseavg-pol" || \
            $surfoperation == "phaseavg-two"} {
          set id [open $scomfile w 0644]
          puts $id "setdir $env(FUNCTIONALS_DIR)"
          set i 0
          foreach bigstem $functscanlists($page,surftoavgbigstems) {
            puts $id "read_complex ${bigstem}${realname}-$hemi.w \
                                   ${bigstem}${complexname}-$hemi.w"
            set revphaseflag 0
            if { [lindex $functscanlists($page,surftoavgrevs) $i] == "on" } {
              set revphaseflag 1
            }
            set angleoffset $functscanlists($page,surfavgoffset) ;# TODO: list
            puts $id "transform_angles $revphaseflag $angleoffset"
            incr i
          }
          puts $id "average_complex $incnt"
          puts $id \
             "write_complex $fullscandir/${bfloatstem}${realname}-$hemi.w \
             $fullscandir/${bfloatstem}${complexname}-$hemi.w"
          # next grows surfcombine stack (OK since STACKSIZE: 20->100)
          if {!$skipamp} {
            set i 0
            foreach bigstem $functscanlists($page,surftoavgbigstems) {
              puts $id "read_complex ${bigstem}${amprealname}-$hemi.w \
                                     ${bigstem}${ampcomplexname}-$hemi.w"
              set revphaseflag 0
              if { [lindex $functscanlists($page,surftoavgrevs) $i] == "on" } {
                set revphaseflag 1
              }
              set angleoffset $functscanlists($page,surfavgoffset) ;# TODO:list
              puts $id "transform_angles $revphaseflag $angleoffset"
              incr i
            }
            puts $id "average_complex $incnt"
            puts $id \
              "write_complex $fullscandir/${bfloatstem}${amprealname}-$hemi.w \
              $fullscandir/${bfloatstem}${ampcomplexname}-$hemi.w"
          }
          close $id
        }
        editfile $scomfile
        after 1200
        confirmalert " Surf Combine: made script for => $hemi <=\n\n$scomfile\
                       \n\nedit script now if needed--OK starts script\!"
      } else {
        if ![file exists $scomfile] {
          confirmalert " Surf Combine: no script file for ${hemi}:\n\n\
                         => click New Script, re-run"
        }
      }
      set command "$bindir/surfcombine $name $hemi [backslashspaces $scomfile]"
      runacmd "$command" $surfaveragebu "SURFCOMBINE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid

    } else {
      ### rcxcombine
      set intercalatedlist ""
      foreach bigstem $functscanlists($page,surftoavgbigstems) {
        set fullstem $env(FUNCTIONALS_DIR)/$bigstem
        lappend intercalatedlist [file dirname $fullstem]
        lappend intercalatedlist [file tail $fullstem]
      }

      # first cmd for real *or* complex sig
      if {$surfoperation == "realaverage"} {
        set command "$bindir/rcxcombine \
          -input $intercalatedlist \
          -ext w \
          -name $name \
          -outtype avg \
          -hemi $hemi \
          -outdir $fullscandir \
          -outstem $bfloatstem"
      }
      if {$surfoperation == "phaseavg-ecc" || \
          $surfoperation == "phaseavg-pol" || \
          $surfoperation == "phaseavg-two"} {
        set revlist ""
        foreach rev $functscanlists($page,surftoavgrevs) {
          if {$rev == "on"}                     { lappend revlist 1 }
          if {$rev == "off" || $rev == "none"}  { lappend revlist 0 }
        }
        set revopt ""
        if [llength $functscanlists($page,surftoavgrevs)] {
          set revopt "-revphase $revlist"
        }
        set command "$bindir/rcxcombine \
          -complex \
          -input [lbackslashspaces $intercalatedlist] \
          -ext w \
          -infixes $realname $complexname \
          -name $name \
          -outtype avg \
          $revopt \
          -offset $functscanlists($page,surfavgoffset) \
          -hemi $hemi \
          -outdir [backslashspaces $fullscandir] \
          -outstem $bfloatstem"
      }
      runacmd "$command" $surfaveragebu "SURFCOMBINE  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid

      # second cmd for complex amp (re-use intercalated/rev lists, w/new infix)
      if {$surfoperation == "phaseavg-ecc" || \
          $surfoperation == "phaseavg-pol" || \
          $surfoperation == "phaseavg-two"} {
        if {!$skipamp} {
          set command "$bindir/rcxcombine \
            -complex \
            -input [lbackslashspaces $intercalatedlist] \
            -ext w \
            -infixes $amprealname $ampcomplexname \
            -name $name \
            -outtype avg \
            $revopt \
            -offset $functscanlists($page,surfavgoffset) \
            -hemi $hemi \
            -outdir [backslashspaces $fullscandir] \
            -outstem $bfloatstem"
          runacmd \
            "$command" $surfaveragebu "SURFCOMBINE  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
        }
      }

    } ;# rcxcombine

  } ;# foreach hemi

  ### stat_w_average: reads n*5 files, writes 5 files (-single else spherical)
  # format: $stem_numer_{r,i}-$hemi.w, $stem_numer_{r,i}.dof, $stem_denom.dof
  #set paintext $functscanlists($page,paintext)
  #foreach hemi { rh lh } {
  #  set command "$bindir/stat_w_average -single -R $flags $hemi 0 $paintext \
  #    $inbfloatstemlist $name $fullscandir"
  #  runacmd "$command" $surfaveragebu "SURFCOMBINE  " cmdinput $cmdlog cmdpid
  #  tkwait variable cmdpid
  #}

  set renderscanlists($page,bfloatstem) $bfloatstem   ;# save ahead like paint
  if {$stattype == "real"} {
    set functscanlists($page,rh,wfile) ${bfloatstem}-rh.w
    set functscanlists($page,lh,wfile) ${bfloatstem}-lh.w
  }
  if {$stattype == "complex"} {
 set functscanlists($page,rh,wfile) ${bfloatstem}{$realname,$complexname}-rh.w
 set functscanlists($page,lh,wfile) ${bfloatstem}{$realname,$complexname}-lh.w
  }

  writearrayparms $datfile surfavg
}

### FIELDSIGN button command (Calculate Visual Fieldsign panel)
proc fieldsigncmd { nbwin } {
  global cmdlog calcfieldbu
  global name surfext patchext endflatext hemi
  global env session iscandir etmptcl
  global surfdir bindir force datfile
  global functscanlists renderscanlists
  global realname complexname

  if [checkconcurrent] { return }
  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  if { [checknamefile] != "match" } { return }
  set iscandir $page

  selecthemi "Fieldsign: Process both hemispheres?"
  if {$hemi == "both"} { set hlist "rh lh" } else { set hlist "$hemi" }
  foreach hemi $hlist {
    set surf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$surfext
    if ![file exists $surf] {
      confirmalert "Surface:\n\n    $surf\n\nnot found"
      return
    }
    set patch \
      $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$functscanlists($page,fspatchext)
    if ![file exists $patch] {
      confirmalert "Patch:\n\n    $patch\n\nnot found"
      return
    }
    if { ![string match *.$endflatext $patch] } {
      if [string match patch $patch] {
        ;# accept old style (e.g., rh.patch) for now
      } else {
        confirmalert "Fieldsign: requires flat patch (suffix: *.$endflatext)"
        return
      }
    }
    set eccdir $env(FUNCTIONALS_DIR)/$session/$functscanlists($page,eccendir)
    set poldir $env(FUNCTIONALS_DIR)/$session/$functscanlists($page,polardir)
    set fulleccenpref $eccdir/$renderscanlists($page,eccenstem)
    set fullpolarpref $poldir/$renderscanlists($page,polarstem)
    foreach pref "$fulleccenpref $fullpolarpref" {
      foreach infix "$realname $complexname" {
        set wfile ${pref}${infix}-${hemi}.w
        if ![file exists $wfile] {
          confirmalert "Fieldsign: painted vertex file $wfile not found\n\
             ...paint first"
          return
        }
      }
    }

    # only check overwrite original fs/fm (fs-make overwrites new wfiles)
    set fsfile $env(FUNCTIONALS_DIR)/$session/$iscandir/$hemi.fs
    set fmfile $env(FUNCTIONALS_DIR)/$session/$iscandir/$hemi.fm
    if {!$force} {
      if { [file exists $fsfile] } {
        if ![okreplace $fsfile "$fsfile exists--Redo Fieldsign?" "Redo"] {
          confirmalert "Fieldsign: fieldsign, fsmask files not altered"
          return
        }
      }
    }
  
    set libscript fs-make.tcl    ;# infixes stripped from bfloatstem
    # changed from patchname=patchext (current/live patch, maybe not flat)
    set dir [trimoneparent $page]  ;# tksurfer's sessiondir child of $session
    set tclenv " \
      dir=$dir \
      eccendir=[trimoneparent $functscanlists($page,eccendir)] \
      polardir=[trimoneparent $functscanlists($page,polardir)] \
      fs=$fsfile \
      fm=$fmfile \
      eccenstem=$renderscanlists($page,eccenstem) \
      polarstem=$renderscanlists($page,polarstem) \
      realname=$realname \
      complexname=$complexname \
      patchname=$functscanlists($page,fspatchext) \
      smoothsteps=$functscanlists($page,smoothstepsfs) \
    "
#xxx -- next MacOSX 10.11 fail: can't use env: PATH/DYLD not passed to subshell
    #set command \
    #  "env $tclenv $bindir/tksurfer -$name $hemi $surfext -tcl $libscript"
    set id [open $etmptcl w 0666]
    foreach line $tclenv { puts $id $line }  ;# bypass Mac 10.11+ env block
    close $id
    set command "$bindir/tksurfer -$name $hemi $surfext -tcl $libscript \
      -csurftclenv $etmptcl"
    cdfunctscripts
    runacmd "$command" $calcfieldbu "FIELDSIGN  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
  }

  writearrayparms $datfile calcfield
}

### GROWBD button command (Calculate Visual Fieldsign panel)
proc findretinborderscmd { nbwin } {
  global cmdlog bordersbu
  global env session etmptcl
  global name surfext sphereext hemi
  global surfdir labeldir bindir force datfile
  global functscanlists renderscanlists
  global realname complexname realbordcntname

  if [checkconcurrent] { return }
  set mpage [$nbwin raised]
  if { $mpage == "" } { return }
  if { [info commands [$nbwin subwidget $mpage].la] == "" } { return }
  set page [demanglepath $mpage]
  if { [checknamefile] != "match" } { return }

  # check all input/output files first
  foreach hemi { rh lh } {
    # input files
    set fullsurf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$sphereext
    if ![file exists $fullsurf] {
      confirmalert \
        "Borders: calc requires RH,LH spheres:\n\n    $fullsurf\n\nnot found"
      return
    }
    set eccdir $env(FUNCTIONALS_DIR)/$session/$functscanlists($page,eccendir)
    set poldir $env(FUNCTIONALS_DIR)/$session/$functscanlists($page,polardir)
    set fulleccenpref $eccdir/$renderscanlists($page,eccenstem) ;#no hemi/infix
    set fullpolarpref $poldir/$renderscanlists($page,polarstem)
    foreach pref "$fulleccenpref $fullpolarpref" {
      foreach infix "$realname $complexname" {
        set wfile ${pref}${infix}-${hemi}.w
        if ![file exists $wfile] {
          confirmalert "Borders: painted vertex file $wfile not found\n\
             ...paint first"
          return
        }
      }
    }
    set label $hemi-$functscanlists($page,retinseedlabel)
    set fulllabel $env(SUBJECTS_DIR)/$name/$labeldir/$label
    if ![file exists $fulllabel] {
      confirmalert \
        "Borders: req's RH,LH retinseeds labels:\n\n    $fulllabel\n\nnot found"
      return
    }
    # output files (N.B.: go to eccen/polar dirs, *not* fsdir, just chk eccen)
    set eccendir [trimoneparent $functscanlists($page,eccendir)] ;# rm image/
    set eccenstem $renderscanlists($page,eccenstem)
    set polarstem $renderscanlists($page,polarstem)
    set borderstem ${eccenstem}+[file tail $polarstem]
    set bdfile ${borderstem}${realbordcntname}-$hemi.w
    set fullbdfile $env(FUNCTIONALS_DIR)/$session/$eccendir/$bdfile
    if {!$force} {
      if { [file exists $fullbdfile] } {
        if ![okreplace $fullbdfile "$fullbdfile exists--Redo Borders?" "Redo"] {
          confirmalert "Borders: existing border count file not altered"
          return
        }
      }
    }
  }

  # run calc
  foreach hemi { rh lh } {
    set libscript borders.tcl   ;# infixes stripped from bfloatstem
    set label $hemi-$functscanlists($page,retinseedlabel)
    set fulllabel $env(SUBJECTS_DIR)/$name/$labeldir/$label
    set eccendir [trimoneparent $functscanlists($page,eccendir)] ;# rm image/
    set polardir [trimoneparent $functscanlists($page,polardir)]
    set eccenstem $renderscanlists($page,eccenstem)
    set polarstem $renderscanlists($page,polarstem)
    set borderstem ${eccenstem}+[file tail $polarstem]
    ### curr all by env (exist opts: retinvtxfrac,maxretinsearch,minretindist)
    # N.B.: env-pass needed to pass label,I/O-stems to borders.tcl script
    set tclenv " \
      eccendir=$eccendir \
      polardir=$polardir \
      eccenstem=$eccenstem \
      polarstem=$polarstem \
      borderstem=$borderstem \
      realname=$realname \
      complexname=$complexname \
      realbordcntname=$realbordcntname \
      smoothsteps=$functscanlists($page,smoothstepsbd) \
      label=$fulllabel \
      retinvtxfrac=$functscanlists($page,retinvtxfrac) \
      maxretinsearch=$functscanlists($page,maxretinsearch) \
      minretindist=$functscanlists($page,minretindist) \
      retinprogressflag=$functscanlists($page,retinprogressflag) \
    "
#xxx -- next MacOSX 10.11 fail: can't use env: PATH/DYLD not passed to subshell
    #set command \
    #  "env $tclenv $bindir/tksurfer -$name $hemi $surfext -tcl $libscript"
    set id [open $etmptcl w 0666]
    foreach line $tclenv { puts $id $line }  ;# bypass Mac 10.11+ env block
    close $id
    set command "$bindir/tksurfer -$name $hemi $surfext -tcl $libscript \
      -csurftclenv $etmptcl"
    cdfunctscripts
    runacmd "$command" $bordersbu "GROWBORD  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
  }

  writearrayparms $datfile calcfield
}

############################################################################
# tcl utils used for cmds
############################################################################
### find display size
proc getxydsp { } {
  set x 1024
  set y 768 
  if { ![catch { exec xdpyinfo | grep dimensions } ret ] } {
    set dims [lindex $ret 1]
    set by [string first x $dims]
    set x [string range $dims 0 [expr $by - 1]]
    set y [string range $dims [expr $by + 1] end]
  } 
  return "$x $y"
}

### stem from printfpatt/BRIK/mgz: rm _%03d.b{short,float}, +orig.BRIK, .mg{z,h}
proc stripbpatt { bpatt } {
  set bstem $bpatt
  if [string match *_%03d.bshort $bpatt] {
    set stemend [expr [string length $bpatt] - 13]
    set bstem [string range $bpatt 0 $stemend]
  }
  if [string match *_%03d.bfloat $bpatt] {
    set stemend [expr [string length $bpatt] - 13]
    set bstem [string range $bpatt 0 $stemend]
  }
  if [string match *+orig.BRIK $bpatt] {
    set stemend [expr [string length $bpatt] - 11]
    set bstem [string range $bpatt 0 $stemend]
  }
  if { [string match *.mgz $bpatt] || [string match *.mgh $bpatt] } {
    set stemend [expr [string length $bpatt] - 5]
    set bstem [string range $bpatt 0 $stemend]
  }
  return $bstem   ;# unstripped if no match
}

### get stem from bfloat file: strip _001.bfloat
proc stripbnum { bfile } {
  set stemend [expr [string length $bfile] - 12]
  set bstem [string range $bfile 0 $stemend]
  return $bstem
}

### check for already running background process (not incl tkmedit/tksurfer)
proc checkconcurrent { } {
  global cmdpid
  if {$cmdpid != -1} {
    #TODO: test posix: ps -p $pid -o comm=
    if { [exec uname] == "Darwin" } {  ;# err to pipe for setuid/DYLD warning
      set currproc [lrange [exec ps uxww |& grep $cmdpid] 10 end]  ;# BSD
    } elseif { [exec uname] == "Linux" } {
      set currproc [lrange [exec ps uxww |& grep $cmdpid] 10 end]  ;# Linux
    } else {
      set currproc [lrange [exec ps af |& grep $cmdpid] 7 end]     ;# old sys5
    }
    if [string match "*/nmovie *" $currproc] {  ;# ignore running nmovie
      return 0
    } else {
      confirmalert "Can't start 2nd process until current finishes:\
                 \n(start another csurf to run jobs in parallel)\
               \n\nCurrent proc: $currproc" 10  ;# force bigger panel for wrap
      return 1
    }
  } else { return 0 }
}

### begin sequence of BOTH hemispheres
proc checkbothhemi { } {
  global hemi otherhemi hemitype
  if {$hemi == "both"} {
    set otherhemi 1
    set hemi rh
    set hemitype 0
  }
}

### check for register.dat newer than vertex list file (allow use stale)
proc checkstaleregdat { fullregdat fullwfile } {
  global force
  if {$force} { return 0 }
  if { [file exists $fullregdat] && [file exists $fullwfile] } {
    if {[file mtime $fullregdat] > [file mtime $fullwfile] } {
      if [okreplace $fullwfile " Render: stale vertex list (paint) file:\n\n\
          $fullwfile\n\n\n The transform file:\n\n $fullregdat\n\n\
          is newer (re-paint to update)" "Use Stale Vertex File"] {
        return 0
      } else { return 1 }
    }
  }
  return 0
}

### check for surface newer than vertex list file (don't allow use stale)
proc checkstalewfile { fullwfile } {
  global env name hemi
  global surfdir origext foldedext inflatedext

  set origsurf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$origext
  set foldedsurf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$foldedext
  set inflatedsurf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$inflatedext
  # TODO: currently only send complex, not fstat infix
  #if ![file exists $fullwfile] {
  #  confirmalert "Render: Vertex List File:\
  #    $fullwfile\n\n: not found\n\n  ...must paint first"
  #  return 1
  #}
  foreach surf "$origext $foldedext $inflatedext" {
    if {[file exists $surf] && [file exists $fullwfile]} {
      if {[file mtime $surf] > [file mtime $fullwfile]} {
        confirmalert "Render: Stale Vertex List File:\
           $fullwfile\n\nSurface: $surf is newer\n\n  ...must re-paint first"
        return 1
      }
    }
  }
  return 0
}

### check if current subject matches name in namefile
proc checknamefile { } {
  global env name session

  set namefile $env(FUNCTIONALS_DIR)/$session/name
  if [file exists $namefile] {
    set id [open $namefile r]
    set namefilename [string trim [read $id]]
    close $id
    if {$name != $namefilename} {
      confirmalert " Surface: name found in namefile:\n\n    $namefilename\n\n\
                     doesn't match current subject:\n\n    $name\n\n\
                     Check if subjects directory set incorrectly\n\
                     (matching subject will be auto-set if present)"
      return nomatch
    } else { return match }
  } else {
    confirmalert "Surface: namefile:\n\n    $namefile\n\nnot found"
    return nonamefile
  }
}

### check if surfer.log writable, (re)fix if owned
proc checksurferlog { } {
  global env session
  set scriptsdir $env(FUNCTIONALS_DIR)/$session/image/scripts
  set slog $scriptsdir/surfer.log
  if ![canwriteormakefile $slog] {
    confirmalert " the file:\n\n\     surfer.log\n\n\
                   in directory:\n\n\     $scriptsdir\n\n\
                   is not writable, which will prevent data display.\n\
                   To fix, run following commands, either as user who\n\
                   owns this session (or as root) in a terminal:\
                   \n\n     cd $scriptsdir\
                     \n     touch surfer.log    (if surfer.log doesn't exist)\
                     \n     chmod go+w surfer.log\n\n\
                   Root can fix entire FUNCTIONALS_DIR at once with:\
                   \n\n     cd \$FUNCTIONALS_DIR\
                     \n     chmod go+w */image/scripts/surfer.log"
    return notwritable
  } else {
    if [file owned $slog] { exec touch "$slog"; exec chmod go+w "$slog" }
    return writable
  }
}

### check for valid FOV in COR-.info
proc checkcorinfoFOV { cordir } {
  global env name volumedir t1dir force bindir

  set corinfo $env(SUBJECTS_DIR)/$name/$volumedir/$cordir/COR-.info
  if [file exists $corinfo] {
    set id [open $corinfo r]
    set lines [split [read $id] "\n"]
    close $id
    foreach line $lines {
      if { [lindex $line 0] == "fov" } { set fov [lindex $line 1] }
    }
    if {$fov == 0 && $cordir == $t1dir} {
      confirmalert " Value of \"fov\" in T1 headerfile:\n\n    $corinfo\n\n\
                     currently set to zero:\n\n    $fov\n\n\
                     Change to default:  0.256  (=256 mm)\n\
                     using a text editor, otherwise SURFACE\n\
                     button will not display surface!"
      return zerofovT1
    } elseif {$fov != 0.256 && $force != 1} {
      confirmalert " Value of \"fov\" in T1 headerfile:\n\n    $corinfo\n\n\
                     currently set to non-default value:\n\n    $fov\n\n\
                     Surfaces may be display/overlay incorrectly.\n\
                     Default value is 0.256 (=256 mm) -- use text\n\
                     text editor to change"
      return nondeffov
    } else { return deffov }
  } else {
    catch { exec $bindir/tksurfer } ret
    if [string match *24m23s23j--OpenGL* $ret] {
      confirmalert \
        " Check: $volumedir/$cordir COR-.info file:\n\n    $corinfo\n\n\
          not found\n\n\
          If recon done using recent freesurfer,\n\
          try SubjectTools -> Back Compat Curv/3d"
      return nocorinfo
    } ;# else re-compiled tksurfer uses default vals if no COR-.info
  }
}

### read HEAD, force short/float brik to MSB byteorder, fix HEAD for bin compat
proc forcebrikMSBfirst { brikstem warningtype {bu hidden} {bulabel hidden} } {
  global tmpdir afnibindir cmdlog env

  # conservative (in case it breaks something)
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog "forceMSB: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  # input stem should look like: <whatever>+orig
  set inhead $brikstem.HEAD; if ![file exists $inhead] { return }
  set inbrik $brikstem.BRIK; if ![file exists $inbrik] { return }
  set idinhead [open $inhead r]
  set lines [split [read $idinhead] "\n"]
  close $idinhead
  set tmphead $tmpdir/TmpAfniHead.[pid]
  if { [catch {set idtmphead [open $tmphead w 0644]}] } { return }
  set checkhead ok
  foreach line $lines {
    if [string match *'LSB_FIRST~* $line] {
      puts $idtmphead "'MSB_FIRST~"
      set checkhead swap
    } else {
      puts $idtmphead $line
    }
  }
  close $idtmphead   ;# TODO: extra CR appended
  putlog "forcebrikMSB: copy $inhead to $tmphead"
  putlog "forcebrikMSB: $tmphead: LSB_FIRST changed to MSB_FIRST"

  set briktypes [readheadbriktypes $inhead]
  if {$briktypes != ""} {
    set firsttype [lindex $briktypes 0]
    foreach type $briktypes {
      if { $type != $firsttype } {
        confirmalert \
          "forceMSB: BRICK_TYPES not all same:\n\n$briktypes\n\n...can't swap"
        return
      }
    }
  } else { set firsttype short }  ;# like AFNI: no BRICK_TYPES assumed short

  if {$checkhead == "swap"} {
    if { $firsttype == "short" } {
      set swapper 2swap
    } elseif { $firsttype == "float" } {
      set swapper 4swap
    } else {
      confirmalert "forceMSB: can't swap this BRIK type: $firsttype"
      return
    }
    if {$warningtype == "warn"} {
      if ![okreplace "" \
         " AFNI BRIK byte order (determined *only*\n\
           from BYTEORDER_STRING parameter in\n\
           this HEAD file):\n\n\    $inhead\n\n\
           is\n\n    Intel  (LSB first)\n\n\
           not\n\n    Sun/SGI/Mac  (MSB first)\n\n\
           Change to MSB first?  (FreeSurfer programs\n\
           on IRIX/Linux/Mac expect MSB first to\n\
           ensure cross-platform binary compatibility)\n\n\
           N.B.: this will be the right thing to do *only*\n\
           if this BRIK currently displays correctly in\n\
           AFNI.  If it doesn't, try manually applying\n\
           2swap (or 4swap) to the BRIK." \
               "Force BRIK to MSB,  Fix HEAD"] {
        confirmalert "BRIK not altered"
        rmlog $tmphead
        return
      }
    }
    if { ![canwriteormakefile $inhead] || ![canwriteormakefile $inbrik] } {
      confirmalert "forceMSB: $inhead is LSBfirst but permissions prevent swap"
      rmlog $tmphead
      return
    }
    set nm .dummybu
    while {[info commands $nm] == "$nm"} {set nm ${nm}x}
    # next: composite path OK
    set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/$swapper \
      -q [backslashspaces $inbrik]"
    if {$bu == "hidden"} { 
      runacmd \
        "$command" [button $nm -text ZZZZ] "ZZZZ  " cmdinput $cmdlog cmdpid
    } else {
      runacmd "$command" $bu $bulabel cmdinput $cmdlog cmdpid
    }
    tkwait variable cmdpid
    if {$bu == "hidden"} { destroy $nm }
    mvlog $tmphead $inhead       ;# mv in here wrapped in catch
    putlog "forcebrikMSB: $brikstem.BRIK ($firsttype BRIK)"
    putlog "  -> BRIK swapped to MSBfirst, HEAD fixed"
  } else {
    putlog "forcebrikMSB: $brikstem.BRIK ($firsttype BRIK)"
    putlog "  -> already MSBfirst (from HEAD)"
  }
  if {$checkhead == "ok" && [file exists $tmphead] } { rmlog $tmphead }
}

### open just-cmds log
proc opencmdsonlyfile { } {
  global env session fullname cmdsonlyid cmdsonlyfile

  set fullscripts $env(FUNCTIONALS_DIR)/$session/image/scripts
  if ![file exists $fullscripts] { 
    confirmalert " No scripts dir in current session:\n\
                   \n     $fullscripts\n\n\
                   Can't create commands-only logfile there"
    return
  }
  if {$cmdsonlyid != "fileNONE"} {
    confirmalert "Commands-only file already open  ...ignored"
    return
  }
  set mustexist 0
  set fullname $env(FUNCTIONALS_DIR)/$session/image/scripts/csurfcmds.log
  choosedir fullname "Enter commands-only log file:" $mustexist
  tkwait variable fullname
  if [file exists $fullname] {
    if { [file type $fullname] == "directory" } {
      confirmalert "Proposed log file is a directory\n\n    ...ignored"
      return
    }
    if ![okreplace $fullname \
          "Overwrite existing cmds-only log:\n\n $fullname?" "Overwrite"] {
      return
    }
  }
  if [catch { open $fullname w 0666 } ret] {
    confirmalert "Can't open command log file:\n\n    $fullname"
    return
  } else {
    confirmalert " Saving commands to log file:\
                   \n\n    $fullname\
                   \n\nWhen done with csurf cmds, close file:\
                   \n\nPreferences -> Close commands-only logfile\
                   \n(or File -> Quit)"
    set cmdsonlyid $ret
    set cmdsonlyfile $fullname
  }
  puts $cmdsonlyid "# csurf cmd log started: [exec date]"
}

### close just-cmds log if open
proc closecmdsonlyfile { } {
  global cmdsonlyid cmdsonlyfile
  if {$cmdsonlyid != "fileNONE"} {
    puts $cmdsonlyid "# csurf cmd log closed: [exec date]"
    close $cmdsonlyid
    set cmdsonlyid fileNONE
    confirmalert "Commands-only log file:\n\n    $cmdsonlyfile\n\n...closed"
  } else {
    confirmalert "No commands-only log file open\n\n    ...ignored"
    set cmdsonlyfile ""
    return
  }
}

### hack more pidnams
proc getcmdpidnam { } {
  global cmdpid

  # N.B.: checkconcurrent only allows multi pids for nmovie
  # N.B.: can get here if runahiddencmd called without first checkconcurrent
  set pidnam cmdpid
  if {$cmdpid == -1} { return $pidnam }
  for {set i 1} {$i < 30} {incr i} {
    global cmdpid$i
    if ![info exists cmdpid$i] { set cmdpid$i -1 }
    if { [set cmdpid$i] == -1 } { set pidnam cmdpid$i; break }
  }
  return $pidnam
}

### run cmd in background, logged, like runacmd, not attached to visible butt
proc runahiddencmd { command } {
  global cmdlog

  set nm .dummybu
  #if [winfo exists $nm] { destroy $nm }
  while {[info commands $nm] == "$nm"} {set nm ${nm}x}  ;# accum hidden buttons
  #ORIG: single cmdpid: kill earlier-started-proc kills later-started!
  #runacmd "$command" [button $nm -text ZZZZ] "ZZZZ  " cmdinput $cmdlog cmdpid
  set pidnam [getcmdpidnam]  
  runacmd "$command" [button $nm -text ZZZZ] "ZZZZ  " cmdinput $cmdlog $pidnam
}

### start cmd in sh in bg, color/+Quit button, log stdout+err, setup kill/intr
## (1) all command printf's must end w/backslash-n, and (2) fflush(stdout)
## HOWTO: attach logged bg commandline to a button, killable w/purpled button
# runacmd "cmdline" $button "BUTTONLABEL  " cmdinput $cmdlog cmdpid
# tkwait variable cmdpid  ;# add if tclfunct needs to wait til cmd done/killed
# backslash literal quotes and brackets to be passed to sh in $command str
# no single quotes or '>' redirects allowed in $command string
# while running, "Quit" pre-appended to BUTTONLABEL, 4 chars trimmed from end
# no spaces inside BUTTONLABEL, add 1-4 quoted spaces to reduce/elim Quit trim
# to search running butt's by name: trunc 4 chars/addedspaces from buttonlabel
# min bg sequence (w/o bgsequencewin): runacmd/tkwait/runacmd/tkwait...
# see bgsequencewin for better feedback
# intr 1butt bgseq: set purplekillseq 0, startseq, brk if purpkillseq, reset it
# won't accept command = "VAR=VALUE prog ..." (use: "env VAR=VALUE prog ...")
#
proc runacmd { command bu bulabel inpnam log pidnam } {
  upvar $inpnam inp
  global $pidnam purplekill purplekillseq
  global runbgcol runactbgcol debugcommands cmdsonlyid

  # block single quotes and redirects
  if [string match *\['>\]* $command] {
    confirmalert "csurf proc runacmd: passed bad command string:\
                  \n\n    $command\
                  \n\nno single quotes (') or redirects (>) allowed"
    return
  }

  # capture stdout+stderr with cat
  if [catch {open "|$command |& cat" a+} inp] { ;# pipe setup, fail dumps resp
    $log insert end $inp\n
    if [winfo exists .progress] {
      destroy .progress
      wm protocol . WM_DELETE_WINDOW testclose
    }
  } else { ;# live dump backslash-n-term'd printf output to log til pipe breaks
    set cmdproc [$bu cget -command]
    fileevent \
       $inp readable "readcmdlog \{$cmdproc\} $bu $bulabel $inp $log $pidnam"
    $log insert end "\n###############################################################################\n"
    $log insert end "pwd=[backslashspaces [pwd]]\n"
    $log insert end "cmd=$command\n"
    $log insert end   "###############################################################################\n\n"
    if {$cmdsonlyid != "fileNONE"} {
      puts $cmdsonlyid "$command"
      flush $cmdsonlyid
    }

    # trim 4 label chars after adding "Quit" (to keep label same size)
    set qlabel [string range $bulabel 0 [expr [string length $bulabel] - 5]]
    set purplekill 0    ;# always reset, to distinguish finish/kill
    $bu config -text "Quit$qlabel" \
       -background $runbgcol -activebackground $runactbgcol \
       -command "quitacmd \{$cmdproc\} $bu $bulabel $inp $log $pidnam; \
                 set purplekill 1; set purplekillseq 1"
    # set/chk/reset purplekillseq to intr seq of runacmd's attached to 1 button
    set $pidnam [lindex [pid $inp] 0]  ;# 2nd: cat pid
  }
  if {$debugcommands} { puts "\n$command"; puts "runacmd pids: [pid $inp]" }
  if {$pidnam != "cmdpid" && "$pidnam" != "medpid" && "$pidnam" != "surfpid"} {
    putlog "runacmd: ### using $pidnam (pid=[set $pidnam])" ;# warn cmdpid$num
  }
}

### put bg process stdout/stderr into appropriate log, quit when process done
proc readcmdlog { cmdproc bu bulabel inp log pidnam } {
  global $pidnam

  set pidval [set $pidnam]
  if [eof $inp] {
    catch {close $inp}
    if {$pidval != -1} { quitacmd "$cmdproc" $bu $bulabel $inp $log $pidnam }
  } else {
    gets $inp line
    $log insert end $line\n
    $log see end
    update idletasks
  }
}

### kill running background process attached to current button, uncolor button
proc quitacmd { cmdproc bu bulabel inp log pidnam } {
  global $pidnam stmptcl mtmptcl bindir purplekill cmdsonlyid debugcommands
  global bgcol actbgcol

  set pidval [set $pidnam]
  if {$pidval != -1} {
    catch { exec kill -9 $pidval }
  }
  set $pidnam -1
  if [info exists bu] {
    $bu config -text $bulabel -command "$cmdproc" \
       -background $bgcol -activebackground $actbgcol
  }
  if {"$pidnam" == "medpid"}  {rmlog $mtmptcl}
  if {"$pidnam" == "surfpid"} {rmlog $stmptcl}
  if [info exists bu] { after 250 "repeatifboth $bu" }
  if { $purplekill && $pidnam == "cmdpid"} { ;# runamd resets kill, not killseq
    $log insert end "Command Killed\n"
    if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "### Command Killed" }
    if {$debugcommands} { puts "\n### Command Killed" }
  } else {
    $log insert end "Command Finished\n"
  }
  $log see end
}

### cd dir, errs, log it
proc cdlog { dir } {
  global cmdlog cmdsonlyid debugcommands
  if ![file exists $dir] {
    confirmalert "directory:\n\n  \"$dir\"\n\nnot found, can't cd to it"
    $cmdlog insert end "\ncd \"$dir\" => ### failed ###\n"
    $cmdlog see end
    if {$cmdsonlyid != "fileNONE"} {
      puts $cmdsonlyid "### cd \"$dir\" => failed"
    }
    if {$debugcommands} { puts "\ncd \"$dir\" => ### failed ###\n" }
    return
  }
  cd "$dir"
  $cmdlog insert end "\ncd \"$dir\"\n"
  $cmdlog see end
  if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "cd \"$dir\"" }
  if {$debugcommands} { puts "\ncd \"$dir" }
}

### mkdir, errs, log it
proc mkdirlog { dir } {
  global cmdlog cmdsonlyid debugcommands
  if [file exists $dir] {
    # could check if already existing writable, warning most important
    $cmdlog insert end "\nmkdir \"$dir\" => ### already exists ###\n"
    $cmdlog see end
    if {$cmdsonlyid != "fileNONE"} {
      puts $cmdsonlyid "### \"$dir\" already exists"
    }
    if {$debugcommands} { puts "\nmkdir \"$dir\" => ### already exists ###\n" }
    return
  }
  if ![canwriteormakefile $dir] {
    confirmalert "can't make directory (permissions):\n\n  \"$dir\""
    $cmdlog insert end "\nmkdir \"$dir\" => ### failed, permissions ###\n"
    $cmdlog see end
    if {$cmdsonlyid != "fileNONE"} {
      puts $cmdsonlyid "### mkdir \"$dir\" failed, permissions"
    }
    if {$debugcommands} {
      puts "\nmkdir \"$dir\" => ### failed, permissions ###\n"
    }
    return
  }
  set ret [catch { exec mkdir "$dir" } err]
  $cmdlog insert end "\nmkdir \"$dir\"\n"
  if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "mkdir \"$dir\"" }
  if {$debugcommands} { puts "\nmkdir \"$dir\"" }
  if {$ret} {
    $cmdlog insert end "error: ### $err\n"
    if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "### error: $err" }
    if {$debugcommands} { puts "\n### error: $err" }
  }
  $cmdlog see end
}

### rm -f list, log it (have to hand log recursive rm's)
proc rmlog { list } {
  global cmdlog cmdsonlyid debugcommands
  foreach file $list {
    set ret [catch { exec rm -f "$file" } err]
    $cmdlog insert end "rm -f \"$file\"\n"
    if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "rm -f \"$file\"" }
    if {$debugcommands} { puts "\nrm -f \"$file\"" }
    if {$ret} {
      $cmdlog insert end "error: ### $err\n"
      if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "### error: $err" }
      if {$debugcommands} { puts "\n### error: $err" }
    }
    $cmdlog see end
  }
}

### mv -f from to, log it
proc mvlog { from to } {
  global cmdlog cmdsonlyid debugcommands
  set ret [catch { exec mv -f "$from" "$to" } err]
  $cmdlog insert end "mv -f \"$from\" \"$to\"\n"
  if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "mv -f \"$from\" \"$to\"" }
  if {$debugcommands} { puts "\nmv -f \"$from\" \"$to\"" }
  if {$ret} {
    $cmdlog insert end "unix error: ### $err\n"
    if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "### err: $err" }
    if {$debugcommands} { puts "\n### error: $err" }
  }
  $cmdlog see end
}

### cp -f from to, log it
proc cplog { from to } {
  global cmdlog cmdsonlyid debugcommands
  set ret [catch { exec cp -f "$from" "$to" } err]
  $cmdlog insert end "cp -f \"$from\" \"$to\"\n"
  if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "cp -f \"$from\" \"$to\"" }
  if {$debugcommands} { puts "\ncp -f \"$from\" \"$to\"" }
  if {$ret} {
    $cmdlog insert end "unix error: ### $err\n"
    if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "### err: $err" }
    if {$debugcommands} { puts "\n### error: $err" }
  }
  $cmdlog see end
}

### ln -s from to, log it
proc lnslog { from to } {
  global cmdlog cmdsonlyid debugcommands
  set ret [catch { exec ln -s "$from" "$to" } err]
  $cmdlog insert end "ln -s \"$from\" \"$to\"\n"
  if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "ln -s \"$from\" \"$to\"" }
  if {$debugcommands} { puts "\nln -s \"$from\" \"$to\"" }
  if {$ret} {
    $cmdlog insert end "unix error: ### $err\n"
    if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "### err: $err" }
    if {$debugcommands} { puts "\n### error: $err" }
  }
  $cmdlog see end
}

### write msg to log
proc putlog { message } {
  global cmdlog cmdsonlyid debugcommands program

  $cmdlog insert end "$message\n"
  if {$cmdsonlyid != "fileNONE"} { puts $cmdsonlyid "# message: $message" }
  if {$debugcommands} { puts "\n### message: $message" }
  $cmdlog see end
}

### re-press current button if doing BOTH hemispheres
proc repeatifboth { bu } {
  global otherhemi hemi origext medsurfflag bindir
  if {$otherhemi} {
    if {"$hemi" == "rh"} {
      set hemi lh; set hemitype 1
    } else {
      set hemi rh; set hemitype 0
    }
    if {$medsurfflag} {
      catch {send $bindir/tkmedit \
         "setfile insurf $hemi.$origext; read_binary_surface; redraw"}
    }
    set otherhemi 0
    if [winfo exists $bu] { $bu invoke }
  }
}

### popup warns if only one hemi selected, allow reselect
proc selecthemi { msg } {
  global userok hemi
  global pfont ffontbb bgcol entbgcol
  if [winfo exists .progress] { return }
  if {$hemi == "both"} { return }
  set nm .hemidialog
  while {[info commands $nm] == "$nm"} {set nm ${nm}x}
  set f [toplevel $nm -borderwidth 10]
  positionpopup $f
  wm protocol $f WM_DELETE_WINDOW killboxOK
  label $f.la -text ALERT -font $ffontbb -bd 2 -relief groove -padx 7 -pady 7
  set msg "$msg\n\n  (can Cancel next panel)"
  message $f.msg -text $msg -font $pfont -width 370 -padx 30 -pady 20
  set b [frame $f.buttons -borderwidth 10]
  pack $f.la -side top -anchor w
  pack $f.msg $f.buttons -side top -fill x
  #set hemi both   ;# trace resets patch if lh and rh not both there
  button $b.rh -text "  RH  " -font $pfont -highlightbackground $bgcol \
    -command { set hemi rh; set userok 0 }
  button $b.lh -text "  LH  " -font $pfont -highlightbackground $bgcol \
    -command { set hemi lh; set userok 0 }
  button $b.bo -text "BOTH" -font $pfont -highlightbackground $bgcol \
    -command { set hemi both; set userok 0 }
  pack $b.bo $b.lh $b.rh -side right -padx 5 -anchor e
  bind $f <Return> {set userok 0}
  foreach win "$f $f.msg $b" { $win config -background $bgcol }
  foreach win "$f.la $b.rh $b.lh $b.bo" { $win config -background $entbgcol }
  tkwait visibility $f
  wm protocol . WM_DELETE_WINDOW killboxOK
  if { [exec uname] != "Linux" } { raise $f }
  #orig: focus $f, then focus $b.bo
  if {$hemi == "rh"} { focus $b.rh }
  if {$hemi == "lh"} { focus $b.lh }
  if {$hemi == "both"} { focus $b.bo }
  grab $f
  tkwait variable userok
  grab release $f
  destroy $f
  wm protocol . WM_DELETE_WINDOW testclose
  return $userok
}

### main window killbox, Quit menu 
proc testclose { } {
  global surfpid medpid cmdpid cmdsonlyid
  global stmptcl stmptcl2 stmptcl3 mtmptcl etmptcl
  global bindir

  rmlog $stmptcl
  rmlog $stmptcl2
  rmlog $stmptcl3
  rmlog $mtmptcl
  rmlog $etmptcl
  rmlog brain.dat
  if {$medpid != -1}  { catch { exec kill -9 $medpid  } }
  if {$surfpid != -1} { catch { exec kill -9 $surfpid } }
  if {$cmdpid != -1}  { catch { exec kill -9 $cmdpid  } }
  writelog   ;# TODO: whole log now written to last scripts dir
  if {$cmdsonlyid != "fileNONE"} { close $cmdsonlyid }
  exit
}

### write csurf log (overwrites existing)
proc writelog { } {
  global program cmdlog medlog surflog tmpdir
  global ${program}_oldvers  ;# go back: Sep2013

  if ![canwriteormakefile $program.log] { return }
  if { [catch pwd] } { cdlog $tmpdir }   ;# if in deleted dir
  if [catch { open $program.log w 0666 } ret] { return }
  set id $ret
  puts $id "######################################################"
  puts $id " $program[set ${program}_oldvers]: log ending: [exec date]"
  puts $id "######################################################"
  puts $id "\n\n"
  puts $id "#############"
  puts $id " Command Log "
  puts $id "#############"
  puts $id [$cmdlog get 1.0 end]
  puts $id "###########"
  puts $id " Medit Log "
  puts $id "###########"
  puts $id [$medlog get 1.0 end]
  puts $id "############"
  puts $id " Surfer Log "
  puts $id "############"
  puts $id [$surflog get 1.0 end]
  close $id
  catch { puts "$program: logfile: [pwd]/$program.log" }  ;# in bg, shell gone
}

### strip array index if there (so we can global an array given array member)
proc arraynameorname { varname } {
  if { [string first ( $varname] && \
       [string last ) $varname] == [expr [string length $varname] - 1] } {
    return [string range $varname 0 [expr [string first ( $varname] - 1]]
  } else {
    return $varname
  }
}

### delete list member by value
proc ldelete { list value } {
  set i [lsearch -exact $list $value]
  if {$i >= 0} {return [lreplace $list $i $i]} else {return $list}
}

### trim deepest component of path (TODO: unix-specific)
proc trimoneparent { path } {
  return [string range $path [expr [string first / $path] + 1] end]
}

### tclwidgetpaths can't contain init-CAP or "." (non-mangled no "&" or "?")
proc manglepath { path } {
  if [string match \[A-Z\]* $path] { set path ?${path} } ;# preappend quest
  return [replchar $path "." "&"]   ;# was "." -> "*" but broke some tix config
}

### undo path-mangled-to-tcl-acceptable
proc demanglepath { path } {
  set path [replchar $path "&" "."] ;# was "*" -> ".", see above
  if [string match \\?* $path] { set path [string range $path 1 end] }
  return $path
}

### block semicolons in scandir (tcl crash at -raisecmd)
proc badscandirname { dir } {
  if [string match "*;*" $dir] {
    confirmalert "Get Funct ScanDirs: skip scandir with a semicolon:\
                  \n\n    \"[file tail $dir]\"\n\n\
                  to fix, rename dir (use mv w/quotes or backslash)"
    return 1
  } elseif [string match "* *" $dir] {
    confirmalert "Get Funct ScanDirs: skip scandir with a space:\
                  \n\n    \"[file tail $dir]\"\n\n\
                  to fix, rename dir (use mv w/quotes or backslash)"
    return 1
  } else { return 0 }
}

### hide 3 logs
proc hidelogs { } {
  set wlist { .cmd .med.lg .sur.lg }
  foreach w $wlist { pack forget $w }
  pack .med .sur -fill x
  foreach w { .setuppopup .progress .reconalldialog .sphavgdialog } {
    if [winfo exists $w] { raise $w; positionpopup $w }
  }
}

### show 3 logs
proc showlogs { } {
  global smallscreenflag
  pack .cmd -after .main -fill x
  pack .med .sur .med.lg .sur.lg
  pack .med.lg.log -side left -fill both -expand true
  pack .sur.lg.log -side left -fill both -expand true
  tkwait visibility .sur.lg.log
  if {!$smallscreenflag} { putpopbelowlog }
  raise .  ;# for multiple csurf's
}

### clear 3 logs
proc clearlogs { } {
  global cmdlog medlog surflog
  $cmdlog delete 1.0 end
  $medlog delete 1.0 end
  $surflog delete 1.0 end
}

### move popup down to uncover logs when they are shown
proc putpopbelowlog { } {
  if { ![winfo exists .] } { return }
  foreach w { .progress .setuppopup .reconalldialog .sphavgdialog } {
    if ![winfo exists $w] { continue }
    set wx [expr [winfo rootx .] + 45]                   ;# was 0
    set wy [expr [winfo rooty .] + [winfo height .] + 8] ;# was 32
    wm geometry $w +${wx}+${wy}
  }
}

### open current subject or session NOTES file
proc editnotes { } {
  global notesfile userdefnotesfile sysdefnotesfile
  if ![file exists $notesfile] {
    if ![canwriteormakefile $notesfile] {
      confirmalert "Copy Default NOTES: $notesfile not writable"
      return
    }
    if [file exists [glob -nocomplain ~/$userdefnotesfile]] {
      cplog [glob -nocomplain ~/$userdefnotesfile] $notesfile
    } elseif [file exists $sysdefnotesfile] {
      cplog $sysdefnotesfile $notesfile
    } else {
      exec touch "$notesfile"
    }
  }
  editfile [pwd]/$notesfile
}

##########################################################################
# begin procedures containing tix calls
##########################################################################
### shrink all panels (here: breaks new pkg8.4.3, at end: breaks older tixwish)
# tix colors:TK,Gray,Blue,Bisque,SGIGray,TixGray fonts:TK,12Point,14Point
# tix default: tix resetoptions TixGray 14Point
# [tix option get bold_font] => helvetica -12 bold
# [tix option get italic_font] => helvetica -12 bold italic
# wish8.5 nothing:      -bd ->1      entry -bg ->ffffff (white)
# wish8.5 classic:      -bd ->2      entry -bg ->d9d9d9 (dark)
# wish8.5 resetoptions: -bd ->1 (!)  entry -bg ->gray95 (OK; e9e9e9 better)

### New Subject menu command
proc mknewsubject { } {
  global env name datfile fullname
  global surfdir labeldir
  global volumedir origdir t1dir pddir pdbraindir braindir wmdir filleddir
  global makingnewsubject usercanceldir

  set makingnewsubject 1
  set fullname $env(SUBJECTS_DIR)
  set mustexist 0
  choosedir fullname "Enter new single subject directory:" $mustexist
  tkwait variable fullname
  if {$usercanceldir} { set makingnewsubject 0; return }
  if [string match "* *" $fullname] {
    confirmalert "Can't create subjectdir containing a space:\
                  \n\n    \"$fullname\"\n\n\Remove space and try again"
    set makingnewsubject 0
    return
  }
  if [string match "*;*" $fullname] {
    confirmalert "Can't create subjectdir containing a semicolon:\
                  \n\n    \"$fullname\"\n\n\Remove semicolon and try again"
    set makingnewsubject 0
    return
  }

  set newsubjectsdir [file dirname $fullname]
  set newsubjtail [file tail $fullname]
  if { ![file writable $newsubjectsdir] } {
    confirmalert "Subjects dir:\
              \n\n    $newsubjectsdir\
              \n\nnot writable, so Subject:\
              \n\n    $newsubjtail\
              \n\ncould not be made"
    set makingnewsubject 0
    return
  }
  if {"$newsubjectsdir" != $env(SUBJECTS_DIR)} {
    confirmalert "Resetting subjects directory to: $newsubjectsdir"
    set env(SUBJECTS_DIR) $newsubjectsdir
  }
  set name $newsubjtail
  set home $env(SUBJECTS_DIR)
  if { [file exists $home/$name] } {
    if { ![file exists $home/$name/$surfdir] || \
         ![file exists $home/$name/$volumedir] || \
         ![file exists $home/$name/scripts] } {
      confirmalert "Subject dir: $home/$name already exists\
                    but doesn't look like a valid subject\n ...not altered"
      after 500 "set makingnewsubject 0"
      return
    }
    if [okreplace $name "subject $name exists--move aside?" "Move Aside"] {
      set savsuff ~
      while { [file exists $home/$name$savsuff] } { set savsuff $savsuff~ }
      mvlog $home/$name $home/$name$savsuff
      confirmalert "Subject dir: $home/$name moved aside: $home/$name$savsuff"
    } else {
      confirmalert "Subject dir: $home/$name not altered"
      after 500 "set makingnewsubject 0"
      return
    }
  }
  update idletasks
  mkdirlog $home/$name
  # skip old COR dirs: $pdbraindir,$braindir,$wmdir,$filleddir
  foreach dir "$volumedir $surfdir scripts rgb mpg bem tmp $labeldir \
      $volumedir/$origdir $volumedir/tmp $volumedir/transforms" {
    if ![file exists $home/$name/$dir] { mkdirlog $home/$name/$dir }
  }
  confirmalert "made new subject dir: $home/$name"
  cdsubjectscripts
  cleararrays struct
  writearrayparms $datfile struct
  set makingnewsubject 0
}

### New Functional menu command
proc mknewfunct { type { mkonedir 0 } } {
  global env name datfile
  global session fullsession fullname functdirstyle
  global makingnewsession usercanceldir
  global sessionscombo

  set makingnewsession 1
  set fullsession $env(FUNCTIONALS_DIR)
  set mustexist 0

  if {$type == "session"} {
    confirmalert "Suggested name format (sorts chronologically):\
              \n\n   <2year> <2month> <2day> <2,3initials>\
              \n\nExample:\
              \n\n   For a 21 June 2019 scan on John Smith,\
                \n   use functional directory name -> 190621JS"
  } elseif {$type == "sphavg"} {
    confirmalert "Make (pseudo) Session for Cross Subject Average\
              \n\n     -------------------------------------------------------\
              \n\nSuggested name format (sorts chronologically):\
              \n\n   <2year> <2month> <2day> <XS-exptname>\
              \n\n\Example:\
              \n\n   For a polar map avg (24subj, vers. a) made 21 June 2019,\
                \n   use cross-session \"session\" -> 190621XS-polar24a,\
                \n   (\"XS\" for \"cross subject\")"
  } else { return }

  choosedir fullsession \
    "Enter new single functional session directory:" $mustexist
  tkwait variable fullsession
  if {$usercanceldir} { set makingnewsession 0; return }
  if [string match "* *" $fullsession] {
    confirmalert "Can't create session containing a space:\
              \n\n    \"$fullsession\"\n\n\Remove space and try again"
    set makingnewsession 0
    return
  }
  if [string match "*;*" $fullsession] {
    confirmalert "Can't create session  containing a semicolon:\
                  \n\n    \"$fullsession\"\n\n\Remove semicolon and try again"
    set makingnewsession 0
    return
  }

  set newfspacedir [file dirname $fullsession]
  set newsesstail [file tail newfspacedir]
  if { ![file writable $newfspacedir] } {
    confirmalert \
      "Session dir: $newfspacedir not writable--session $newsesstail not made"
    set makingnewsession 0
    return
  }
  if {"$newfspacedir" != $env(FUNCTIONALS_DIR)} {
    confirmalert "Resetting functional sessions directory to: $newfspacedir"
    set env(FUNCTIONALS_DIR) $newfspacedir
  }

  set session [file tail $fullsession]
  set home $env(FUNCTIONALS_DIR)
  set dirtype notmade
  if { [file exists $home/$session] } { ;# guess type existing
    if { [file exists $home/$session/mri] && \
         [file exists $home/$session/surf] && \
         [file exists $home/$session/scripts] } {
      set dirtype subjdir
    } elseif { [file exists $home/$session/name] && \
         [file exists $home/$session/image/scripts] && \
         [file exists $home/$session/image/rgb] && \
         [file exists $home/$session/image/mpg] } {
      set dirtype csurffunctdir
    } else {
      set dirtype unknown
    }

    # bail, move aside funct, or put funct inside subj
    if { $dirtype == "unknown" } {
      confirmalert " Make New Session: $home/$session already exists\n\
                     but doesn't look like session or subject dir\n\
                     \n    ...not altered"
      after 500 "set makingnewsession 0" ;# stop select_session cdfunctscripts
      return
    }
    if { $dirtype == "subjdir" } {
      if [okreplace $session \
          " Subjectdir $session exists\n\
            A session can be put inside it\n\n\
            OK to do this? (all-in-one)" \
          "Put New Session Inside Subject"] {
      } else {
        confirmalert "Make New Session: $home/$session not altered"
        after 500 "set makingnewsession 0"
        return
      }
    }
    if { $dirtype == "csurffunctdir" } {
      if [okreplace $session \
          "session $session exists--move aside?" "Move Aside"] {
        set savsuff ~
        while { [file exists $home/$session$savsuff] } { set savsuff $savsuff~ }
        mvlog $home/$session $home/$session$savsuff
        confirmalert \
          "Session dir: $home/$session moved aside: $home/$session$savsuff"
        set dirtype notmade
      } else {
        confirmalert "Session dir: $home/$session not altered"
        after 500 "set makingnewsession 0"
        return
      }
    }
  }
  set fullname $env(SUBJECTS_DIR)
  #choosesubjectname   ;# TODO: allow choose manual name entry if subj nonexist

  if { $dirtype == "notmade" } {
    if {$type == "session"} {
      confirmalert "Now, locate single subject directory containing\
                  \nsurface for this functional scan\
                \n\n(if subject doesn't exist, cancel and first do recon)"
    }
    if {$type == "sphavg"} {
      confirmalert "Now, locate single subject on which to render\
                    average data (easy to change later in\
                    Cross Session Spherical Avg panel)"
    }
    choosedir fullname "Choose matching subject directory:" $mustexist
    tkwait variable fullname
    if {$usercanceldir} { after 500 "set makingnewsession 0"; return }
  
    if { ![file exists $fullname] } {
      confirmalert "Subject dir: $fullname not found  ...session not created"
      after 500 "set makingnewsession 0"
      return
    }
    if { ![file exists $fullname/scripts] || ![file exists $fullname/surf] } {
      confirmalert " Subject dir: $fullname\n\
                     no scripts,surf subdirs  ...session not created"
      after 500 "set makingnewsession 0"
      return
    }
    set newsubjectsdir [file dirname $fullname]
    if {"$newsubjectsdir" != $env(SUBJECTS_DIR)} {
      confirmalert "Resetting subjects directory to: $newsubjectsdir"
      set env(SUBJECTS_DIR) $newsubjectsdir
    }
  } else {  ;# put session inside subject
    #next done above if needed, here redefs sess from 2nd fixsessions callback
    #set env(FUNCTIONALS_DIR) $env(SUBJECTS_DIR)
    set fullname $env(SUBJECTS_DIR)/$session
  }

  # finally: make dir, subdirs, write def csurf.dat
  update idletasks
  if {$dirtype == "notmade"} { mkdirlog $home/$session }
  if {$functdirstyle == "imagesubdir"} {
    set dirlist "image image/scripts image/rgb image/mpg"
    if {$mkonedir} { set dirlist "$dirlist image/scan1" }
    set slog $home/$session/image/scripts/surfer.log
  }
  if {$functdirstyle == "flat"} { 
    set dirlist "scripts rgb mpg"
    if {$mkonedir} { set dirlist "$dirlist scan1" }
    set slog $home/$session/scripts/surfer.log
  }
  foreach dir $dirlist {
    if ![file exists $home/$session/$dir] { mkdirlog $home/$session/$dir }
  }
  set id [open $home/$session/name w 0644]
  puts $id "[file tail $fullname]"
  close $id
  # hack: allow older tksurfer run by another user to write surfer.log
  exec touch "$slog"
  putlog "touch \"$slog\""
  exec chmod go+w "$slog"
  putlog "chmod go+w $slog"

  confirmalert " Made new functional session dir:\n\
                 $home/$session\n\n\
                 Matching subject dir:\n\
                 $fullname"
  cdfunctscripts
  setdefaultarrays
  writearrayparms $datfile alignfunct
  $sessionscombo invoke
  set makingnewsession 0
}

### Change Subj for Curr Session menu item
proc changenamefile { } {
  global env name session
  global fullname makingnewsubject usercanceldir

  if ![file exists $env(FUNCTIONALS_DIR)/$session] {
    confirmalert "Change Subj: Session:\n\n    $session\n\n...doesn't exist"
    return
  }
  set namefile $env(FUNCTIONALS_DIR)/$session/name
  if ![file exists $namefile] {
    confirmalert "Change Subj: namefile:\n\n    $namefile\n\n...doesn't exist"
    return
  }
  cdfunctscripts
  set session $session  ;# refresh (maybe subject changed)
  if ![okreplace "" \
           "OK to change subject dir associated with this session?\
          \n(this will edit \"name\" file)\n\
          \n    session:  $session\
          \n    subject:  $name\n\
          \nN.B.: ALL SCANDIRS in this session will have to be\
          \nre-registered and re-painted!!  (curr wfiles -> stale)\
          \n(only non-stale if orig surfaces have same num vertices)\
          \nN.B.: Only choose brain from DIFFERENT person if\
          \nyou want to perform a cross-subject registration\
          \nfor 3D brainstem retinotopy (not for surface data!)" \
         "Choose New Subject Dir"] {
    confirmalert "Namefile: $namefile not altered"
    return
  } else {
    if ![canwriteormakefile $namefile] {
      confirmalert "Display Subject: can't modify namefile:\n\n  $namefile"
      return
    } else {
      set makeingnewsubject 1
      set fullname $env(SUBJECTS_DIR)
      confirmalert "Now, locate NEW single subject directory\
                    \nto associate with this functional scan\
                    \n(subject dir must already exist)"
      set mustexist 0    ;# allow enter non-exist, warn after
      choosedir fullname "Choose matching subject directory:" $mustexist
      tkwait variable fullname
      if {$usercanceldir} { after 500 "set makingnewsubject 0"; return }
      if ![file exists $fullname] {
        confirmalert "Subject dir: $fullname not found  ...namefile not altered"
        after 500 "set makingnewsubject 0"
        return
      }
      if { ![file exists $fullname/scripts] || ![file exists $fullname/surf] } {
        confirmalert " Subject dir: $fullname\n\
                       no scripts,surf subdirs  ...namefile not altered"
        after 500 "set makingnewsubject 0"
        return
      }
      set newsubjectsdir [file dirname $fullname]
      if {"$newsubjectsdir" != $env(SUBJECTS_DIR)} {
        confirmalert "Resetting subjects directory to: $newsubjectsdir"
        set env(SUBJECTS_DIR) $newsubjectsdir
      }
      set newname [file tail $fullname]
      set id [open $namefile w 0644]
      puts $id "$newname"
      close $id
      confirmalert " New subject associated with this session:\n\
           \n    session:    $session\
           \n    orig subject:  $name\
           \n    new subject:  $newname\n\
           \n N.B.: ALL SCANDIRS in this session must now be\
           \n re-registered and re-painted!!"
    }
  }
  set name $newname
  set makingnewsubject 0
  cdfunctscripts
}

### File -> Open Subject menu command
proc choosesubjectdir { } {
  global env name fullname choosingsubjectdir usercanceldir

  set choosingsubjectdir 1
  set fullname $env(SUBJECTS_DIR)
  choosedir fullname "Choose single subject directory:"
  tkwait variable fullname
  if {$usercanceldir} { set choosingsubjectdir 0; return }
  set newsubjectsdir [file dirname $fullname]
  if {"$newsubjectsdir" != $env(SUBJECTS_DIR)} {
    confirmalert "Resetting subjects directory to: $newsubjectsdir"
  }
  if { ![file writable $newsubjectsdir] } {
    confirmalert \
      "Subjects dir: $newsubjectsdir not writable  ...configs won't be saved"
  }
  set env(SUBJECTS_DIR) $newsubjectsdir
  set name [file tail $fullname]
  set choosingsubjectdir 0
}

### File -> Open Functional menu command
proc choosefunctdir { } {
  global env session fullsession choosingfunctdir usercanceldir matchsubject

  if {$matchsubject} { set matchsubject 0; fixsessions 0 0 0 }
  set choosingfunctdir 1
  set fullsession $env(FUNCTIONALS_DIR)
  choosedir fullsession "Choose single functional session directory:"
  tkwait variable fullsession
  if {$usercanceldir} { set choosingfunctdir 0; return }
  set newfspacedir [file dirname $fullsession]
  if {"$newfspacedir" != $env(FUNCTIONALS_DIR)} {
    confirmalert "Reset functionals directory to: $newfspacedir"
  }
  if { ![file writable $newfspacedir] } {
    confirmalert \
      "Session dir: $newfspacedir not writable  ...configs won't be saved"
  }
  set env(FUNCTIONALS_DIR) $newfspacedir
  set session [file tail $fullsession]
  set choosingfunctdir 0
}

### File -> "Copy Subject/Functional" menu commands
proc cpdir { type } {
  global env fullsourcename fulltargname usercanceldir functdirstyle tmpdir

  if {$type == "Subject"} {
    set fullsourcename $env(SUBJECTS_DIR)
    set endslog scripts/surfer.log
  } elseif {$type == "Functional"} { 
    set fullsourcename $env(FUNCTIONALS_DIR)
    if {$functdirstyle == "imagesubdir"} {set endslog image/scripts/surfer.log}
    if {$functdirstyle == "flat"}        {set endslog scripts/surfer.log}
  } else { return }
  set mustexist 1
  choosedir fullsourcename "Choose single $type to copy:" $mustexist
  tkwait variable fullsourcename
  if {$usercanceldir} { return }

  set fulltargname [file dirname $fullsourcename]
  set mustexist 0
  choosedir fulltargname "Enter full name of copy:" $mustexist
  tkwait variable fulltargname
  if {$usercanceldir} { return }

  if {$fullsourcename == $fulltargname} {
    confirmalert "Copy $type: can't copy to self"
    return
  }
  if [file exists $fulltargname] {
    confirmalert "Copy $type: target: $fulltargname already exists"
    return
  }
  if ![canwriteormakefile $fulltargname] {
    confirmalert "Copy $type: can't create $fulltargname"
    return
  }
  if [okreplace "" \
    "Copy $type:\n\nfrom:\n\n   $fullsourcename\n\nto:\n\n   $fulltargname"\
    "Copy $type"] {
  } else { confirmalert "$type not copied"; return }

  # hack workaround for surfer.log bug: (create)/make-writable when bg cp done
  set tmpcsh $tmpdir/TmpCsh.[pid]
  if ![canwriteormakefile $tmpcsh] {confirmalert "can't make $tmpcsh"; return}
  set id [open $tmpcsh w 0644]
  puts $id "cp -r $fullsourcename $fulltargname"
  puts $id "touch $fulltargname/$endslog; chmod go+w $fulltargname/$endslog"
  puts $id "sleep 1; rm -f $tmpcsh"
  close $id
  set command "csh -f $tmpcsh"

  #set command "cp -r $fullsourcename $fulltargname"
  set cppid [pid [open "|$command"]]
  confirmalert "Copying $type in background\n(to interrupt: kill $cppid)"
}

### make choose *or* create, dir *or* file popup
proc choosedir { absdirvarname elabel {mustexist 1}} {
  global dtree_dir fulldtree usercanceldir tmpdir
  global bgcol selbgcol entbgcol
  global [arraynameorname $absdirvarname]

  set w .choosedir
  set usercanceldir 0
  if { [info commands $w] != ""} {return}
  toplevel $w
  ::tk::classic::restore    ;# newpkgtix
  configtixbookcbxent $w
  wm title $w $elabel       ;# was: not always appropriate "Choose Directory"
  positionpopup $w 550x480  ;# was: 455x253, 520x400, 520x480
  frame $w.top -border 1 -relief raised -background $bgcol
  set dtree_dir [set $absdirvarname]
  if { [catch pwd] } { cdlog $tmpdir }   ;# if in deleted dir
  if ![file exists $dtree_dir] {set dtree_dir [pwd]}
  if [string match "//*" $dtree_dir] {  ;# exists but tix can't see, crashes
    set dtree_dir [string range $dtree_dir 1 end]
  }
  if {$fulldtree} {
    tixDirTree $w.top.dir -browsecmd "dtree:browse $w.top.ent" -bg $bgcol \
      -value "$dtree_dir"
  } else {
    tixDirList $w.top.dir -browsecmd "dtree:browse $w.top.ent" -bg $bgcol \
      -value "$dtree_dir"
  }
  $w.top.dir config -scrollbar auto  ;# newpkgtix
  $w.top.dir subwidget hlist config -selectbackground $selbgcol -pady 0
  ### width left dirtree col: window width (pix) minus entry width (chars)
  tixLabelEntry $w.top.ent -label "$elabel" -labelside top \
     -options "label.anchor w
               entry.width 44
               entry.textVariable dtree_dir"  ;# was: width=40
  bind [$w.top.ent subwidget entry] \
    <Return> "dtree:okcmd $w $absdirvarname $mustexist"
  pack $w.top.dir -side left -expand yes -fill both -padx 4 -pady 4
  pack $w.top.ent -side left -fill x -anchor c -padx 4 -pady 4
  tixButtonBox $w.box -orientation horizontal -background $bgcol
  $w.box add ok -text OK -background $entbgcol -width 6 -command \
    "dtree:okcmd $w $absdirvarname $mustexist" -highlightbackground $bgcol
  $w.box add cancel -text Cancel -background $entbgcol -width 6 -command \
    "dtree:cancelcmd $w $absdirvarname" -highlightbackground $bgcol
  $w.box config -pady 20  ;# newpgktix
  pack $w.box -side bottom -fill x
  pack $w.top -side top -fill both -expand yes
}

### on choose directory browse
proc dtree:browse { ent filename } {   ;# browsecmd called w/curr fullpath
  if [string match "* *" $filename] {
### link doesn't help b/c tix choose eventually resolves linkpath to spacespath
#    confirmalert " Can't use following directory because\n\
#                   it or its path contains at least one space:\
#                   \n\n    \"$filename\"\n\n\
#                   Do one of the following:\n\
#                   \n    (1) rename directory to remove space\
#                   \n    (2) copy contents to directory without spaces\
#                   \n    (3) make symbolic link without spaces, e.g.:\
#             \n\n ln -s \"/path/with spaces\" /alias/path/without/spaces\
#               \n ln -s \"/Volumes/Macintosh HD/usr0/subjects\" ~/subjects\n\n\
#                   and try again using newdir/link"
#    return
### omit even short warning b/c can get behind modal panel
#    confirmalert "N.B.: path contains spaces:\
#              \n\n    $filename\
#              \n\n(avoid/remove if possible)"
    ;
  }
  if [string match "*;*" $filename] {
    confirmalert " Can't use following directory because\n\
                   it or its path contains at least one semicolon:\
                   \n\n    \"$filename\"\n\n\
                   Do one of the following:\n\
                   \n    (1) rename directory to remove semicolon\
                   \n    (2) copy contents to directory without semicolons\
                   \n    (3) ln -s \"dir with semicolon\" dir_without_one\n\n\
                   and try again using newdir/link"
    return
  }
  uplevel #0 set dtree_dir \"$filename\" ;# $ent is coupled entry (not yet used)
}

### on choose directory select
proc dtree:okcmd { w absdirvarname mustexist } {
  global dtree_dir
  global [arraynameorname $absdirvarname]   ;# e.g., absdirvarname="fullname"

  if {$mustexist} {
    if ![file exists "$dtree_dir"] { ;#quotes here else fail w/backslash,quotes
      confirmalert "Bad path: $dtree_dir doesn't exist"
      return
    }
  } else {
    if ![file exists [file dirname "$dtree_dir"]] {
      confirmalert \
         "Bad parent directory: [file dirname $dtree_dir] doesn't exist"
      return
    }
  }
  set dtail [file tail "$dtree_dir"]
  ## N.B. glob in next (for ~user, ~/*) curly-braces path-with-space! must rm!
  set dparent [glob [file dirname "$dtree_dir"]]
  set dparent [replchar $dparent "{" ""]
  set dparent [replchar $dparent "}" ""]
  set $absdirvarname $dparent/$dtail
  #set $absdirvarname [replchar [set $absdirvarname] "{" ""] ;# deref: more cplx
  #set $absdirvarname [replchar [set $absdirvarname] "}" ""]
  update idletasks
  destroy $w
}

### on choose directory cancel
proc dtree:cancelcmd { w absdirvarname } {
  global usercanceldir
  global [arraynameorname $absdirvarname]
  set $absdirvarname [set $absdirvarname]  ;# end tkwait
  set usercanceldir 1                      ;# for interrupt
  update idletasks
  destroy $w
}

### make extended choose file popup
proc choosefile { absfilevarname {initrelfile ""}} {
  global efdlg_filename bgcol selcol selbgcol entbgcol
  global [arraynameorname $absfilevarname]

  ::tk::classic::restore  ;# newpkgtix
  set f [tix filedialog tixExFileSelectDialog]
  positionpopup $f 600x500  ;# newpkgtix: bigger padx w/subdir icon lines
  set efdlg_filename [set $absfilevarname]
  if ![file exists $efdlg_filename] {set efdlg_filename [pwd]}
  $f config -command "efdlg:select_file $absfilevarname"
  if ![string match "" $initrelfile] { ;# N.B.: only appears 2nd call to dialog
    $f subwidget fsbox subwidget file config -value $initrelfile
  }

  # touch varname anyway because we're tkwaiting
  set cancelbu [$f subwidget fsbox subwidget cancel]
  bind $cancelbu <ButtonPress-1> "set $absfilevarname \"\""
  #bind $cancelbu <Alt-c> "set $absfilevarname \"\""  ;# Mac-reserved

  $f subwidget fsbox config -directory $efdlg_filename
  $f subwidget fsbox config -filetypes {
    {{*}        {*             -- All files}}
    {{*.dat}    {*.dat        -- ASCII parms}}
    {{*.bshort} {*.bshort    -- 2-byte}}
    {{*.bfloat} {*.bfloat      -- 4-byte}}
    {{COR-???}  {COR-??? -- COR byte images }}
    {{i.???}    {i.???        -- GE}}
    {{*.ima}    {*.ima        -- Siemens}}
    {{*.BRIK}   {*.BRIK      -- AFNI}}
    {{*.HEAD}   {*.HEAD     -- AFNI}}
    {{*.brik}   {*.brik       -- brik no header}}
    {{*.gz}     {*.gz         -- compressed}}
    {{*.rgb}    {*.rgb        -- SGI images}}
    {{*.mpg}    {*.mpg       -- MPEG movies}}
    {{*.tiff}   {*.tiff          -- tiff images}}
  }
  foreach subw { file dir types } {
    $f subwidget fsbox subwidget $subw subwidget entry \
      config -selectbackground $selbgcol -state normal ;# normal: newpkgtix
    $f subwidget fsbox subwidget $subw subwidget listbox \
      config -selectbackground $selbgcol
  }
  $f subwidget fsbox subwidget dirlist subwidget hlist \
     config -selectbackground $selbgcol
  $f subwidget fsbox subwidget filelist subwidget listbox \
     config -selectbackground $selbgcol
  $f subwidget fsbox subwidget hidden config -selectcolor $selcol

  # newpkgtix: label pack left not fixed (orig: top)
  $f subwidget fsbox subwidget dirlist config -scrollbar auto
  $f subwidget fsbox subwidget filelist config -scrollbar auto
  $f subwidget fsbox subwidget dirlist subwidget hlist config -pady 0
  $f subwidget fsbox subwidget filelist subwidget listbox config -bg $entbgcol
  $f subwidget fsbox subwidget dir subwidget label config -text "Directories:"
  $f subwidget fsbox subwidget file subwidget label config -text "Files:"
  $f subwidget fsbox subwidget types subwidget label config -text \
    "List Files of Type:"
  $f.fsbox.lf.pane paneconfig 1 -size 200 ;# internal ugh (widen for padx+)

  foreach w [info commands $f.*] {  ;# internal ugh
    if [string match *__* $w] { continue }  
    if [string match *dirlist* $w] { continue }  
    if [string match *entry* $w] { continue }  
    if [string match *listbox* $w] { continue }  
    $w config -background $bgcol
  }
  $f popup
  return $f
}

### on select file extended choosefile 
proc efdlg:select_file { absfilevarname filename } {
  global [arraynameorname $absfilevarname]
  set $absfilevarname $filename
}

### select from list popup -- selmode: single, multiple, else $selectparm label
proc selectfromlist { msgtext hlisttitle hlistlist {selmode single} \
    {width 160} {height 250} } {
  global userok selectmemb bgcol entbgcol selbgcol selectparm
  global pfont ffontbb tfont hfont xcmd

  if [winfo exists .selectdialog] { return }
  set f [toplevel .selectdialog -borderwidth 10]
  positionpopup $f
  set selectmemb ""
  wm protocol $f WM_DELETE_WINDOW killboxOK
  label $f.la -text SELECT -font $ffontbb -bd 2 -relief groove -padx 7 -pady 7
  message $f.msg -text $msgtext -font $pfont -width 370 -padx 30 -pady 20
  tixScrolledHList $f.shlist -scrollbar auto -height $height -width $width \
     -options "hlist.selectBackground $selbgcol" -background $bgcol \
     -highlightbackground $bgcol
  set hlist4 [$f.shlist subwidget hlist]
  $hlist4 config -font $hfont  ;# newpkgtix: tix options bug
  set parmflag 0
  if {$selmode != "single" && $selmode != "multiple" && \
      $selmode != "extended"} {
    set parmflag 1
    set parmname $selmode
    set selmode single
  }
  $hlist4 config -header true -selectmode $selmode -font $hfont \
    -browsecmd "hlist4:browse $hlist4" -separator "!" -bd 1 -relief groove
  set hstyle [tixDisplayStyle text -refwindow $hlist4 \
    -padx 8 -pady 2 -font $tfont]
  $f.shlist subwidget hsb config -highlightbackground $bgcol ;# vert scrollbar
  $f.shlist subwidget vsb config -highlightbackground $bgcol ;# hori scrollbar
  $hlist4 header create 0 -itemtype text -text $hlisttitle -style $hstyle
  foreach dir $hlistlist { $hlist4 add $dir -text $dir }
  set b [frame $f.buttons -borderwidth 10]
  pack $f.la -side top -anchor w
  pack $f.msg -side top
  pack $f.shlist -side top -fill both -expand yes
  if {$parmflag} {  ;# calling proc should set selectparm to "" when done
    frame $f.f -bg $bgcol
    pack $f.f -side top -pady 10
    label $f.f.la -text "$parmname: " -bg $bgcol
    entry $f.f.e -width 12 -textvariable selectparm \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol
    pack $f.f.la $f.f.e -side left
  }
  pack $b -side top
  button $b.ok -text "OK" -font $pfont -command {set userok 0} \
    -highlightbackground $bgcol
  pack $b.ok -side right -padx 5 -anchor e
  bind $f <Return> {set userok 0}
  if {$selmode == "multiple" || $selmode == "extended"} {
    bind $f <$xcmd-e> \
      "$hlist4 selection set [lindex $hlistlist 0] [lindex $hlistlist end]; \
       $hlist4 yview moveto 1.0; set selectmemb \"$hlistlist\""
  }
  bind $hlist4 <Double-Button-1> {set userok 0}
  foreach win "$f $f.msg $b" { $win config -background $bgcol }
  foreach win "$f.la $b.ok" { $win config -background $entbgcol }
  tkwait visibility $f
  wm protocol . WM_DELETE_WINDOW killboxOK
  if { [exec uname] != "Linux" } { raise $f }
  focus $f
  grab $f
  tkwait variable userok
  grab release $f
  destroy $f
  wm protocol . WM_DELETE_WINDOW testclose
  if { [llength $hlistlist] == 1 && $selectmemb == "" } { ;# less irritating
    set selectmemb $hlistlist
  }
  return $selectmemb
}

### on select from list popup
proc hlist4:browse { hlist mem } {
  global selectmemb

  #set selectmemb $mem
  set selectmemb [$hlist info selection]
}

### File -> "Terminal -> Subject/Functional Scripts" menu command
proc openterm { type } {
  global  env name session functdirstyle

  if {$type != "Subject" && $type != "Functional"} { return }
  if {$type == "Subject"} {
    cdsubjectscripts
    set dir $env(SUBJECTS_DIR)/$name
  }
  if {$type == "Functional"} {
    cdfunctscripts
    # N.B.: this (local) isession unrelated/unconnected to tksurfer $isession
    if {$functdirstyle == "imagesubdir"} { set isession $session/image }
    if {$functdirstyle == "flat"}        { set isession $session }
    set dir $env(FUNCTIONALS_DIR)/$isession
  }
  set termprog xterm
  if [foundbywhich gnome-terminal] { set termprog gnome-terminal }
  #TODO: check on Ubuntu
  if [file exists $dir] {
    #set geom [positionpopup justgetposition]
    set geom +[expr [winfo rootx .] + 110]+[expr [winfo rooty .] + 620]
    exec $termprog -geom $geom >& /dev/null & ;#curr dir/shell, null else huptk
  } else { confirmalert "directory:\n\n    $dir\n\nnot found" }
}

### Subject/Session/CrossSessTools -> "View Saved Funct Bitmaps" menu commands
proc viewbitmaps { {type session} } {
  global env session iscandir name hemi
  global bindir bitmapdir selbitpixhigh cmdlog cmdkey

  set savewd [pwd]
  set hemicurr $hemi
  if {$type == "session"} {
    set subdir [file dirname $iscandir]
    while { [string match */* $subdir] } { set subdir [file dirname $subdir] }
    set fullbitmapdir $env(FUNCTIONALS_DIR)/$session/$subdir/$bitmapdir
  } elseif {$type == "subject"} {
    set fullbitmapdir $env(SUBJECTS_DIR)/$name/$bitmapdir
    set hemi both
  } else { return }
  if ![file exists $fullbitmapdir] { return }
  cdlog $fullbitmapdir

  set selimlist [selectfromlist \
    "RGB image files:\
      \n    pick every:  <$cmdkey-e>\n    pick one:  <Ctrl-click>" \
    "Select Bitmaps to View" [getsortedbyviewlist] extended 330 $selbitpixhigh]
  set hemi $hemicurr
  if ![llength $selimlist] { cdlog $savewd; return }
  set x0 [expr [winfo rootx .]+25]
  set y0 [expr [winfo rooty .]+25]

  if [file exists $bindir/nmovie] {
    #eval exec $bindir/nmovie $selimlist &   ;# writes to csurf cmdline
    set command "$bindir/nmovie $selimlist"
    runahiddencmd $command
  } elseif { [foundbywhich xv] } {
    #eval exec $bindir/xv -geom +$x0-$y0 $selimlist &  ;# writes csurf cmdline
    set command "$bindir/xv -geom +$x0-$y0 $selimlist"
    runahiddencmd $command
  } else { 
    confirmalert "View Saved Bitmaps:  Requires 'xv'\n(or $bindir/nmovie)"
  }
  cdlog $savewd
}

### Session/CrossSessTools -> "Convert Funct Bitmaps to Mpeg" menu command
proc convert2mpg { } {
  global env session iscandir
  global bindir bitmapdir moviedir selbitpixhigh
  global cmdlog mpgoutfile tmpmpg
  global processkill cmdkey

  set savewd [pwd]
  set subdir [file dirname $iscandir]
  while { [string match */* $subdir] } { set subdir [file dirname $subdir] }
  set fullmoviedir $env(FUNCTIONALS_DIR)/$session/$subdir/$moviedir
  set fullbitmapdir $env(FUNCTIONALS_DIR)/$session/$subdir/$bitmapdir
  if ![file exists $fullmoviedir] { return }
  cdlog $fullbitmapdir

  set selimlist [selectfromlist \
    "Convert RGB/TIFF files to MPEG:\
      \n  pick every:  <$cmdkey-e>\n  pick one:  <Ctrl-click>" \
    "CONVERT selected -> mpg (optional DELETE orig)" \
    [getsortedbyviewlist] extended 360 $selbitpixhigh]
  if ![llength $selimlist] { cdlog $savewd; return }
  if ![canwriteormakefile $tmpmpg.parm] {
    confirmalert "Make mpeg: can't write tmp parmfile in [pwd]"
    cdlog $savewd; return
  }

  set mpgoutfile $fullmoviedir/
  #set f [choosefile mpgoutfile]  ;# orig vs. next 8
  set firststem [file rootname [lindex $selimlist 0]]
  if { [string match *???,ph=+?.?? $firststem] || \
       [string match *???,of=+?.?? $firststem] } {
    set firststem \
      [string range $firststem 0 [expr [string length $firststem] - 14]]
  }
  set f [choosefile mpgoutfile $firststem.mpg]  ;# always only 1 dialog panel
  set f [choosefile mpgoutfile $firststem.mpg]  ;# lastval only visble 2nd call

  wm title $f "Select Name for Mpeg Output File"
  tkwait variable mpgoutfile
  if {$mpgoutfile == ""} { cdlog $savewd; return }

  set cnt [expr [llength $selimlist]-1]
  set quality 1    ;# higher -> more compression
  set gamma 1.0    ;# or 0.70
  set id [open $tmpmpg.parm w 0644]
  puts $id "IQSCALE $quality"
  puts $id "PQSCALE $quality"
  puts $id "BQSCALE $quality"
  puts $id "PSEARCH_ALG LOGARITHMIC"
  puts $id "BSEARCH_ALG SIMPLE"
  puts $id "GOP_SIZE 41"
  puts $id "SLICES_PER_FRAME 1"
  puts $id "PIXEL FULL"
  puts $id "RANGE 10"
  puts $id "PATTERN IBBPBBPBBPBBPB"
  puts $id "FORCE_ENCODE_LAST_FRAME"
  puts $id "BASE_FILE_FORMAT PPM"
  # pnm is pbm, pgm, and ppm
  if { [exec uname] == "Linux"} { puts $id "BASE_FILE_FORMAT PNM" }
  puts $id "INPUT_DIR ."
  puts $id "INPUT"
  foreach file $selimlist { puts $id "$file" }
  puts $id "END_INPUT"
  puts $id "INPUT_CONVERT $bindir/mytoppm *"  ;# writes ppm to stdout
  puts $id "OUTPUT $mpgoutfile"
  puts $id "REFERENCE_FRAME ORIGINAL"
  puts $id "GAMMA $gamma"
  close $id

  bgsequencewin "CONVERT TO MPEG" MakeMpeg { "mpeg encode" } { mpegencode }
  rmlog $tmpmpg.parm
  if {$processkill} { cdlog $savewd; return }

  #confirmalert "Made mpeg: $mpgoutfile" ;# finish bgproc already puts up panel
  set firstim [lindex $selimlist 0]
  if [okreplace $firstim \
      "Delete converted images?\n\n$firstim\n($cnt more)" "Delete Converted"] {
    foreach rgb $selimlist { rmlog $rgb }
  }
  cdlog $savewd
}

### Convert to Mpeg step 1 command
proc mpegencode { subjectsdir name } {
  global bindir cmdlog processbu tmpmpg
  set command "$bindir/mpeg_encode $tmpmpg.parm"
  runacmd "$command" $processbu MAKEMPEGintr cmdinput $cmdlog cmdpid
  tkwait variable cmdpid
}

### sort list of bitmaps by view of brain (if BOTH, then hemi outer loop)
proc getsortedbyviewlist { } {
  global env hemi bitmapsufflist
  global foldedext inflatedext inflatedext2 oldinflatedext patchlist
 
  # sort by view for contiguous select (tiff first, then rgb)
  if {$hemi == "both"} { set hemilist "rh lh" } else { set hemilist $hemi }

  set imlist ""
  foreach bitmapsuff $bitmapsufflist {
    set smoothlist ""
    set inflatedlist ""
    set oldinflatedlist ""
    set flatlist ""
    set flatinfixlist ""
    foreach hem $hemilist {  ;# ??=phmov,offmov
      foreach view { lat med ven pos dor cus ?? ??,??=??.?? } {
        set smoothlist "$smoothlist \
          [lsort [glob -nocomplain *-$hem-$foldedext-$view.$bitmapsuff]]"
        set inflatedlist "$inflatedlist \
          [lsort [glob -nocomplain *-$hem-$inflatedext-$view.$bitmapsuff]] \
          [lsort [glob -nocomplain *-$hem-$inflatedext2-$view.$bitmapsuff]]"
        set oldinflatedlist "$oldinflatedlist \
          [lsort [glob -nocomplain *-$hem-$oldinflatedext-$view.$bitmapsuff]]"
      }
    }
    foreach patchpref $patchlist {
      set flatinfixlist "$flatinfixlist $patchpref.patch.flat"
    }
    set flatinfixlist "$flatinfixlist flat flat-??,??=??.?? nomid" ;#old,ph/off
    foreach hem $hemilist {
      foreach flatinfix $flatinfixlist {
        set flatlist "$flatlist \
          [lsort [glob -nocomplain *-$hem-$flatinfix.$bitmapsuff]]"
      }
    }
    set imlist \
      "$imlist [concat $smoothlist $inflatedlist $oldinflatedlist $flatlist]"
    ### extras: if "both", get more (e.g., subject w/o hemi in name), rm dups
    set subjrgb 0
    set parentparent [file tail [file dirname [file dirname [pwd]]]]
    if {$parentparent == "[file tail $env(SUBJECTS_DIR)]"} { set subjrgb 1 }
    if {$hemi == "both"} {
      set expatt *.$bitmapsuff
    } else {
      if {$subjrgb} {
        set expatt *$hemi*.$bitmapsuff  ;# more permissive
      } else {
        set expatt *-$hemi-*.$bitmapsuff
      }
    }
    foreach bitmap [lsort [glob -nocomplain $expatt]] {
      if {[lsearch -exact $imlist $bitmap] == -1} {set imlist "$imlist $bitmap"}
    }
  }
  return $imlist
}

### Subject/Session/CrossSessTools -> "Run Mpeg Movie" menu commands
proc runmpeg { {type session} } {
  global env session iscandir name selectparm
  global bindir moviedir movie1suff movie4sufflist

  set savewd [pwd]
  if {$type == "session"} {
    set subdir [file dirname $iscandir]
    while { [string match */* $subdir] } { set subdir [file dirname $subdir] }
    set fullmoviedir $env(FUNCTIONALS_DIR)/$session/$subdir/$moviedir
  } elseif {$type == "subject"} {
    set fullmoviedir $env(SUBJECTS_DIR)/$name/$moviedir
  } else { return }
  if ![file exists $fullmoviedir] { return }
  cdlog $fullmoviedir
  set mpeglist [glob -nocomplain *.$movie1suff]
  if { [exec uname] == "Darwin" } {
    foreach suff $movie4sufflist {
      set mpeglist [concat $mpeglist [glob -nocomplain *.$suff]]
    }
  }
  set selectparm 15
  set mpeg [selectfromlist \
    "MPEG movies:" "Select to Start Movie" $mpeglist "frames per sec" 250 350]
  if ![llength $mpeg] {cdlog $savewd; confirmalert "no movie selected"; return}
  set command ""
  if [string match *.$movie1suff $mpeg] {
    set fps 15   ;# 0 (=fastest) is too fast on modern machines
    if [isnum $selectparm] { set fps $selectparm }
    set opts "-dither color -quiet -loop -controls off -framerate $fps"
    #eval exec $bindir/mpeg_play $opts $mpeg &   ;# writes to csurf cmdline
    set command "$bindir/mpeg_play $opts $mpeg"
  } else {  ;# not *.mpg
    if {[exec uname] == "Darwin"} {
      set command "open -a \"QuickTime Player\" $mpeg"  ;# assume there
    } else {
      if [foundbywhich vlc] {
        set command "vlc $mpeg"
      } else {
        putlog "csurf: ### vlc not found on path"
        confirmalert "Can't play mp4/m4v:\n\nvlc not found on \$PATH"
      }
    }
  }
  if {"$command" == ""} { return }
  runahiddencmd $command
  set selectparm ""
  cdlog $savewd
}

### View All Scandirs menu command
proc viewallscandirs { } {
  global userok pfont ffontbb sfont tfont hfont
  global bgcol entbgcol selcol selbgcol runbgcol
  global env session sessionscombo subjectscombo norenderpanelflag

  set nm .viewallscandirs
  while {[info commands $nm] == "$nm"} {set nm "${nm}x"}
  set f [toplevel $nm -borderwidth 10 -bg $bgcol]
  bind $f <ButtonRelease-3> { helpwin viewscandirs 50 $helpwinlines }
  ::tk::classic::restore  ;# newpkgtix
  positionpopup $f
  #wm protocol $f WM_DELETE_WINDOW killboxOK

  set maxtitle 43
  set wt $env(FUNCTIONALS_DIR)
  if { [string length $wt] > $maxtitle } {
    set wt ...[string range $wt [expr [string length $wt] - $maxtitle + 2] end]
  }
  label $f.la -text "$wt" -font $ffontbb -bd 2 -relief groove -padx 7 -pady 7
  pack $f.la -side top -anchor w
  frame $f.ti -bg $bgcol
  pack $f.ti -side top
  label $f.ti.la2 -text "Double-Click Scandir To Open/Render" \
    -font $tfont -bg $bgcol
  pack $f.ti.la2 -side left
  #xxxxx -- omit broken surftestrendernopanel till fixed
  #checkbutton $f.ti.ck -text "no panel" -variable norenderpanelflag \
  #  -bg $bgcol -font $sfont -selectcolor $selcol -highlightbackground $bgcol
  #pack $f.ti.ck -side left -padx 10
  label $f.la3 -text "\[2 double-clicks to change if tksurfer up\]" \
    -font $sfont -bg $bgcol
  pack $f.la3 -side top

  frame $f.to -bg $bgcol
  pack $f.to -side top -expand true -fill y

  tixMeter $f.to.me -value 0.0 -bg $bgcol -highlightbackground $bgcol \
    -fillcolor $runbgcol -width 270 -bd 2 -relief sunken ;# 8.5: need -width
  pack $f.to.me -side top

  tixTree $f.to.tr -options { separator "!" } -scrollbar auto ;# newpkgtix:auto
  set hlist [$f.to.tr subwidget hlist]
  $hlist config -width 36 -height 2 -selectbackground $selbgcol
  $hlist config -pady 0 -padx 25 -font $hfont  ;# newpkgtix: defs chngd
  $f.to.tr autosetmode
  pack $f.to.tr -expand yes -fill both -side left

  set currsess $session
  set namelist {}
  set namesesslist {}
  set namesessscanlist {}
  set sesslist [$sessionscombo subwidget listbox get 0 end]
  set sesscnt [llength $sesslist]
  set i 0
  foreach sess $sesslist {  ;# first pass: find subject name, scandir lists
    set namefile $env(FUNCTIONALS_DIR)/$sess/name
    if [file exists $namefile] {
      set id [open $namefile r]
      set name [string trim [read $id]]
      close $id
      if [file exists $env(SUBJECTS_DIR)/$name] {
        # found subject
      } else {
        set name \[subject_\"$name\"_not_found\]
      }
    } else {
      set name \[missing_name_file\]
    }
    if { [lsearch -exact $namelist $name] == -1 }  { lappend namelist $name }
    $subjectscombo config -disablecallback true  ;# no fixsubj trace
    $sessionscombo config -disablecallback true  ;# no set session callback
    set session $sess   ;# use getfunctiscandirslist
    $sessionscombo config -disablecallback false
    $subjectscombo config -disablecallback false
    set scandirlist [getfunctiscandirslist]
    lappend namesesslist ${name}!${sess}
    foreach iscandir $scandirlist {
      lappend namesessscanlist ${name}!${sess}!${iscandir}
    }
    $f.to.me config -value [expr $i.0/$sesscnt.0]
    update idletasks
    incr i
  }
  destroy $f.to.me
  set namelist [lsort $namelist]
  set namesesslist [lsort $namesesslist]
  set namesessscanlist [lsort $namesessscanlist]

  $hlist config -width 36 -selectbackground $selbgcol ;# -height 57
  foreach name $namelist {  ;# second pass: display sorted tree
    $hlist add $name -itemtype text -text $name -style \
      [tixDisplayStyle text -font $tfont -bg $bgcol]
  }
  foreach namesess $namesesslist {
    set sess [string range $namesess [expr [string last ! $namesess] + 1] end]
    $hlist add $namesess -itemtype imagetext -text $sess
  }
  foreach namesessscan $namesessscanlist {
    set scan \
      [string range $namesessscan [expr [string last ! $namesessscan] + 1] end]
    $hlist add $namesessscan -itemtype imagetext -text $scan
  }
  $sessionscombo config -disablecallback true
  set session $currsess
  $sessionscombo config -disablecallback false

  set b [frame $f.but -borderwidth 1 -bg $bgcol]
  pack $b -side right
  button $b.ok -text "OK" -font $pfont -command "destroy $f" \
    -highlightbackground $bgcol
  #bind $f <Control-c> "destroy $f"  ;# Mac-reserved
  pack $b.ok -side right -padx 5 -anchor e
  foreach win "$f.la $b.ok" { $win config -background $entbgcol }
  $hlist config -command "hlist6:select" -selectmode single -font $hfont
  bind $hlist <Double-Button-1> { killtestrender } ;# because hlist6 tkwait'ing
  set height [expr [lindex [getxydsp] 1] - 110]
  wm geometry $f [winfo width $f]x${height}  ;# just set height
  wm resizable $f 0 0
  focus $f
}

### checkdestroy just render, no error
proc killtestrender { } {
  global surfrenderbu medrenderbu
  if { [info exists surfrenderbu] && [info commands $surfrenderbu] != ""} {
    if {[$surfrenderbu cget -text] == "QuitSURFACE-STA"} {
      $surfrenderbu invoke
    }
  }
  if { [info exists medrenderbu] && [info commands $medrenderbu] != ""} {
    if {[$surfrenderbu cget -text] == "QuitVOLUME-STA"} {
      $medrenderbu invoke
    }
  }
}

### on double-click-select viewallscandirs hlist entry
proc hlist6:select { select } {
  global name session datfile surfrenderbu norenderpanelflag sessionscanlists

  set pathlist [split $select !]
  set cnt [llength $pathlist]
  if {$cnt == 1} { set name [lindex $pathlist 0] }
  if {$cnt == 2 || $cnt == 3} {
    set initsession $session
    set session [lindex $pathlist 1]
    if [file exists $datfile] {
      readarrayparms $datfile alignfunct  ;# reads all non-struct aspects
    } else {
      cleararrays alignfunct  ;# clears all non-struct aspects
    }
    set panel .setuppopup
    set nbwin $panel.to.no
    if { $session != $initsession && [winfo exists $panel] } { destroy $panel }
    if { $norenderpanelflag && [winfo exists $panel] } { destroy $panel }
    if { ![winfo exists $panel] && !$norenderpanelflag } { setupscans render }
    set page [lindex $pathlist 2]
    if [info exists sessionscanlists($page,type)] {  ;# existing dir config'd
      if {$cnt == 3 && !$norenderpanelflag} {
        $nbwin raise [manglepath $page]
        $surfrenderbu invoke        ;# tkwaits in here till purple kill
        #TODO:new hlist select lost after killtestrender bind to bypass tkwait
      } else {
        surftestrendernopanel $page ;# no tkwait
      }
    }
  }
}

###########################################################################
### open tksurfer using curr sess/scandir w/o render panel (multiple OK)
###########################################################################
#xxxxx -- broken/not-maintained (TODO: convert to mostly opts, new flag mess)
proc surftestrendernopanel { page } {  ;# viewscandirs "no panel" only
  global surflog surfpid
  global name hemi surfext patchext viewtype surfdir
  global env session etmptcl
  global renderscanlists surfparms postclparms lightparms
  global bindir savergbflag exitrenderflag
  global doublebufferflag smallscreenflag minglxdepthflag
  global tiffoutflag black2transparentflag tksurferlogflag 
  global realname complexname amprealname ampcomplexname

  if ![info exists renderscanlists($page,rgbname)] { return }
  if { [checknamefile] != "match" } { return }
  if {$viewtype == "folded"} { set libscript $renderscanlists($page,viewstcl) }
  if {$viewtype == "inflated"} {set libscript $renderscanlists($page,viewstcl)}
  if {$viewtype == "viewcuts"} {
    set viewtype inflated; set libscript $renderscanlists($page,viewstcl)
  }
  if {$viewtype == "flattened"} {set libscript $renderscanlists($page,flattcl)}
  if ![file exists $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$surfext] { return }
  if {$viewtype == "viewcuts" || $viewtype == "flattened"} {
   if ![file exists $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$patchext] {return}
  }
  set vlist ""  ;# non-std views
  set llist ""  ;# lighting
  foreach light { 0 1 2 3 } {
    foreach lparm { "" x y z } {
      set llist "$llist light$light$lparm=$lightparms(light$light$lparm)"
    }
  }
  set dir [trimoneparent $page]   ;# tksurfer's sessiondir child of $session

  ### floatstem (TODO: expand to one/curr/all)
  if {$renderscanlists($page,bfloatstem) == "-multiple-"} {
    confirmalert "multiple paintfiles -- not yet implemented"
    return
  }
  set floatstemlist floatstem=$renderscanlists($page,bfloatstem)

  ### removed old statflag mess

  ### new flag mess: set non-global flags passed to tksurfer at button press
  if { ![info exists renderscanlists($page,colscaletype)] } {
    colscaletypefromrendertype $page  ;# bak compat: don't redef config'd
  }
  if {$renderscanlists($page,colscaletype) == "cplx"} {
    set complexvalflag 1; set fieldsignflag 0; set fstatflag 0; set tstatflag 0
  }
  if {$renderscanlists($page,colscaletype) == "fs"} {
    set complexvalflag 0; set fieldsignflag 1; set fstatflag 0; set tstatflag 0
  }
  if {$renderscanlists($page,colscaletype) == "vstat"} { ;# old -> guess tstat
    set complexvalflag 0; set fieldsignflag 1; set fstatflag 0; set tstatflag 1
  }
  #xxx -- next 2 passed via env (til use tksurfer -stat, cf. medtestrender)
  if {$renderscanlists($page,colscaletype) == "fstat"} {
    set complexvalflag 0; set fieldsignflag 1; set fstatflag 1; set tstatflag 0
  }
  if {$renderscanlists($page,colscaletype) == "tstat"} {
    set complexvalflag 0; set fieldsignflag 1; set fstatflag 0; set tstatflag 1
  }
  if {$renderscanlists($page,colscaletype) == "real"} {
    set complexvalflag 0; set fieldsignflag 0; set fstatflag 0; set tstatflag 0
  }
  set rname $realname
  set iname $complexname
  if {$renderscanlists($page,fourierampflag)} {
    set rname $amprealname
    set iname $ampcomplexname
  }
  ### real: non-global flags to name, for now passed to real-{views,flat}.tcl
  set bfloatstem $renderscanlists($page,bfloatstem)
  set sbfloatstem "-no_mask-"
  set statreplampflag 0
  set statmaskampflag 0
  set statmultampflag 0
  if {$fstatflag || $tstatflag} {
    set tlistver1 { _coef-thresh+orig _t-st-clust+orig } ;# could use wasbrak
    set flistver1 { _LC@0@_coef-thresh+orig _F-stat-clust+orig }
    set tlistver2 { _GLT@0_Coef-clust+orig _GLT@0_Tstat-clust+orig }
    set flistver2 { _GLT@0_Coef-clust+orig _GLT_Fstat-clust+orig }
    if {$tstatflag} { set verlist [list $tlistver1 $tlistver2]}
    if {$fstatflag} { set verlist [list $flistver1 $flistver2]}
    foreach pair $verlist {
      set coefsuff [lindex $pair 0]
      set clustsuff [lindex $pair 1]
      if [string match *$coefsuff $bfloatstem] {
        set sbfloatstem [string range $bfloatstem 0 \
                          [expr [string length $bfloatstem] - 1 - \
                          [string length $coefsuff]]]${clustsuff}
      }
    }
    set fullscandir $env(FUNCTIONALS_DIR)/$session/$page ;#May2014:scandir->page
    if {$sbfloatstem != "-unset-"} {
      set statfile $fullscandir/${sbfloatstem}-$hemi.w
      set renderscanlists($page,sbfloatstem) $sbfloatstem
    }
  }

  ### TODO: make surftestrendernopanel do complexampmodtypes
  set tmpcplxstatname none
  ### TODO: make surftestrendernopanel work w/xsubj averages (or ignore!)
  ### TODO: make surftestrenderpanel default missing like surftestrender
  ### TODO: pass -normdfracflag and -normdsamp or -normdfracsamp
  ### TODO: pass -normdsampsearchflag and -normddstep

  ### make tksurfer cmdline (TODO: options version)
  set glxdeptharg ""
  if {$minglxdepthflag} { set glxdeptharg "glxdepth=12" }
  set tclenv " \
    tksurferinterface=mini \
    patchname=$patchext \
    dir=$dir \
    scandir=$dir \
    $floatstemlist \
    maskfloatstem=$sbfloatstem \
    realname=$rname \
    complexname=$iname \
    cplxstatname=$tmpcplxstatname \
    smoothsteps=$renderscanlists($page,smoothstepsrend) \
    smoothstepsstat=$renderscanlists($page,smoothstepsstat) \
    rgbname=$renderscanlists($page,rgbname) \
    $vlist \
    $llist \
    \
    overlayflag=1 \
    regdat=$functscanlists($page,regdat) \
    rawdata=$functscanlists($page,imagepatt) \
    stimcycles=$functscanlists($page,stimcycles) \
    dividequadsflag=$surfparms(dividequadsflag) \
    undividequadsflag=$surfparms(undividequadsflag) \
    newquadoutputflag=$surfparms(newquadoutputflag) \
    newcurvareaoutputflag=$surfparms(newcurvareaoutputflag) \
    cslope=3.0 \
    cmid=0.0 \
    colscale=$renderscanlists($page,colscale) \
    interpolatelutflag=$renderscanlists($page,interpolatelutflag) \
    complexvalflag=$renderscanlists($page,complexvalflag) \
    fieldsignflag=$fieldsignflag \
    invphaseflag=$renderscanlists($page,invphaseflag) \
    revphaseflag=$renderscanlists($page,$hemi,revphaseflag) \
    truncphaseflag=$renderscanlists($page,truncphaseflag) \
    softtruncphaseflag=$renderscanlists($page,softtruncphaseflag) \
    truncphasemin=$renderscanlists($page,$hemi,truncphasemin) \
    truncphasemax=$renderscanlists($page,$hemi,truncphasemax) \
    nonbinaryfsflag=$renderscanlists($page,nonbinaryfsflag) \
    statreplampflag=$statreplampflag \
    statmaskampflag=$statmaskampflag \
    statmultampflag=$statmultampflag \
    fthresh=$renderscanlists($page,fthresh) \
    fslope=$renderscanlists($page,fslope) \
    fmid=$renderscanlists($page,fmid) \
    angle_offset=$renderscanlists($page,$hemi,angle_offset) \
    angle_cycles=$renderscanlists($page,angle_cycles) \
    fadef=$renderscanlists($page,fadef) \
    ipsiyellowfact=$renderscanlists($page,ipsiyellowfact) \
    surfcolor=$renderscanlists($page,surfcolor) \
    offset=$lightparms(offset) \
    cvfact=$lightparms(cvfact) \
    avgflag=$renderscanlists($page,avgflag) \
    fullpolrectflag=$postclparms(fullpolrectflag) \
    noninteccendiskflag=0 \
    scalebarflag=$renderscanlists($page,scalebarflag) \
    colscalebarflag=$renderscanlists($page,colscalebarflag) \
    smallscreenflag=$smallscreenflag \
    doublebufferflag=$doublebufferflag \
    $glxdeptharg \
    tiffoutflag=$tiffoutflag \
    tksurferlogflag=$tksurferlogflag \
    black2transparentflag=$black2transparentflag \
    renderoffscreen=0 \
  "
  #offset=$renderscanlists($page,offset) -> now subj-specific ExpertParms
  #cvfact=$renderscanlists($page,cvfact) -> now subj-specific ExpertParms
  if {!$exitrenderflag} { set tclenv "$tclenv noexit=1" }
  if {!$savergbflag} { set tclenv "$tclenv nosave=1" }
  #set nm .dummybu
  #while {[info commands $nm] == "$nm"} {set nm ${nm}x}
  #set dummybu [button $nm -text ZZZZ]
  #set command \
  #  "env $tclenv $bindir/tksurfer -$name $hemi $surfext -tcl $libscript"
  #runacmd "$command" $dummybu "ZZZZ  " surfinput $surflog surfpid
#xxx -- next MacOSX 10.11 fail: can't use env: PATH/DYLD not passed to subshell
  #set command \
  #  "env $tclenv $bindir/tksurfer -$name $hemi $surfext -tcl $libscript"
  set id [open $etmptcl w 0666]
  foreach line $tclenv { puts $id $line }  ;# bypass Mac 10.11+ env block
  close $id
  set command "$bindir/tksurfer -$name $hemi $surfext -tcl $libscript \
    -csurftclenv $etmptcl"
  runahiddencmd $command
  # N.B.: *don't* save parms in datfile
}

### make ListNoteBook w/pickdir,action buttons (SessionTools menu items)
### widgets on individual notebook pages made by add<paneltype>scan procs
### get curr page in global context: [demanglepath [.setuppopup.to.no raised]]
proc setupscans { aspect } {
  global env name hemi session iscandir datfile volumedir origdir
  global rawavgdir newrawavgdir sigavgdir newsigavgdir fsdir newfsdir
  global surfavgdir newsurfavgdir
  global structscanlists sessionscanlists functscanlists renderscanlists
  global sessionscombo subjectscombo scandirscombo patchescombo surfacescombo
  global surfacescombo2 patchescombo2
  global stripcopybu convertstructbu convertfunctbu
  global rawaveragebu sigaveragebu surfaveragebu calcfourbu
  global calcrandbu calcfieldbu bordersbu paintbu surfrenderbu medrenderbu
  global currpage prevpage
  global ffontb ffont sfont tfont hfont
  global bgcol entbgcol selbgcol hilbgcol hilcol actbgcol selcol
  global savergbflag viewtype makingsetupscan logflag
  global sing2fsavgflag oppfsavghemiflag mac_appnap_hack helpwinlines xcmd

  set w .setuppopup
  if { [info commands $w] != ""} {
    raise $w
    confirmalert "Close current panel first"
    return
  }
  if {$aspect == "struct"} {
    if {$name == ""} { return }
  } else {
    if {$session == ""} { return }
  }

  ### get scandirslist ahead of time and maybe bail, just for these two
  if {$aspect == "mkorigdirs" || $aspect == "mkscandirs"} {
    if {$aspect == "mkorigdirs"} {
      set scandirslist [getstructscandirslist]
      set currdir $env(SUBJECTS_DIR)/$name/$volumedir/$origdir
    }
    if {$aspect == "mkscandirs"} {
      set scandirslist [getfunctiscandirslist]
      set currdir $env(FUNCTIONALS_DIR)/$session
    }
    set formatlist "    "
    set i 0
    foreach sdir $scandirslist {
      set formatlist "${formatlist}\n    ${sdir}"
      incr i
      if {$i > 15} { set formatlist "${formatlist}\n    . . ."; break }
    }
    if {"$scandirslist" != "" } {
      confirmalert "N.B.: these dirs already exist in:\n\n$currdir\
          \n$formatlist\
          \n\nmanually delete them to start over.\
          \n\n----------------------------------------\
          \n\nIf instead, you want to create a new\
          \nfunctional session, first do:\n\n    File -> New Functional"
      if [winfo exists $w] { destroy $w }
      return
    }
  }

  ### make/config window
  toplevel $w -background $bgcol
  ::tk::classic::restore  ;# newpkgtix
  configtixbookcbxent $w
  set makingsetupscan 1

  ### set titles
  if {$aspect == "struct" || $aspect == "mkorigdirs"} {
    $subjectscombo invoke  
    if {$aspect == "struct"} {set wmt "Setup Structural Scan Parameters"}
    if {$aspect == "mkorigdirs"} \
           {set wmt "Make Origdirs, Find/Link Raw Scans, Copy/Rename"}
    wm title $w $wmt
    set wtitletext "Subject Dir:  $name"
    set htitletext "mri/orig Directories"
    set geom [positionpopup $w]
  } elseif {$aspect == "mkscandirs" || \
            $aspect == "alignfunct" || $aspect == "rawavg" || \
            $aspect == "calcfour" || $aspect == "calcrand" || \
            $aspect == "sigavg" || $aspect == "surfavg" || \
            $aspect == "calcfield" || $aspect == "extstat" || \
            $aspect == "render" || $aspect == "rendersphavg"} {
    # N.B.: no aspect=sphavg here (used by setupsphavgcx, not setupscans)
    set saveviewtype $viewtype  ;# session trace must select_surface
    $sessionscombo invoke
    set viewtype $saveviewtype
    set geom [positionpopup $w]
    if {$aspect == "mkorigdirs"} \
           {set wmt "Make Origdirs, Find/Link Raw Scans, Copy/Rename"}
    if {$aspect == "mkscandirs"} \
           {set wmt "Make Scandirs, Find/Link Raw Scans, Copy/Rename/StripTRs"}
    if {$aspect == "alignfunct"} {set wmt "Setup Functional Scan Parameters"}
    if {$aspect == "rawavg"}    {set wmt "Combine 3D Raw Images (x-y-z-t)"}
    if {$aspect == "calcfour"}  {set wmt "Calculate/Paint Fourier Statistics"}
    if {$aspect == "calcrand"} \
                            {set wmt "Calculate Random Block Statistics"}
    if {$aspect == "sigavg"} \
      {set wmt "Combine 3D Phase Statistics (x-y-z {real,imag or condition} )"}
    if {$aspect == "surfavg"}   {set wmt "Setup Average Stats on Surface"}
    if {$aspect == "calcfield"} \
        {set wmt "Setup Calculate Fieldsign, Borders (combine surface stats)"}
    if {$aspect == "extstat"}   {set wmt "Import External 3D Statistics"}
    if {$aspect == "render"}    {set wmt "View Functional Data"}
    if {$aspect == "rendersphavg"} {set wmt "View SphereAvg Data"}
    wm title $w $wmt
    set wtitletext "Session:  $session"
    set htitletext "Session Scandirs"
  } else { return }

  ### horrible tmp hack gives 20x draw speed if AppNap (Yosemite+ 14sec->700ms)
  if {$mac_appnap_hack} {
    set pid [exec xterm -geom 105x50${geom} -bg $bgcol -e bash --norc &]
  }

  ### top panel: title + pickdir buttons + action buttons
  set title $w.ti
  frame $title -background $bgcol
  pack $title -side top -fill x -padx 10
  label $title.la -text "$wtitletext" -borderwidth 2 \
     -background $bgcol -relief groove -padx 7 -pady 7
  tixButtonBox $title.bu -bd 1 -background $bgcol -relief flat
  $title.bu config -pady 10  ;# newpkgtix

  ### render only: insert linked copy of main panel buttons
  if {$aspect == "render" || $aspect == "rendersphavg"} {
    set div $w.div
    frame $div -bd 2 -height 2 -relief groove
    set dup $w.dup
    frame $dup -background $bgcol
    pack $div $dup -side top -fill both -expand yes
  }

  ### make main window containing notebook
  set top $w.to
  frame $top -bd 1 -relief raised -background $bgcol
  pack $top -side top -fill both -expand yes

  ### notebook win name--used by config/action procs to find current n.b. page
  set nbwin $w.to.no  ;# currently constant (.setuppopup.to.no) for all panels

  ### make declare-or-unset-dir-to-be-this buttons (pkg Tix -width =tixwish+1)
  if {$aspect == "mkorigdirs"} {
    $title.bu add addmkdirs -text "Find Raw Structs" -width 14 \
       -command "addmkdirs $nbwin origdirs" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin mkorigdirs 50 $helpwinlines }
  }
  if {$aspect == "struct"} {
    $title.bu add addstruct -text "Structural Scan Dir" -width 16 \
       -command "addstructscan $nbwin" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setupstruct 50 $helpwinlines }
  }
  if {$aspect == "mkscandirs"} {
    $title.bu add addmkdirs -text "Find Raw Scans" -width 13 \
       -command "addmkdirs $nbwin scandirs" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin mkscandirs 50 $helpwinlines }
  }
  if {$aspect == "alignfunct"} {
    $title.bu add addfunct -text "Funct Scan Dir" -width 12 \
       -command "addfunctscan $nbwin 1; fixfocus \$currpage $title" \
       -highlightbackground $bgcol
    $title.bu add addalign -text "Align Scan Dir" -width 12 \
       -command "addalignscan $nbwin 1; fixfocus \$currpage $title" \
       -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setupfunct 50 $helpwinlines }
  }
  if {$aspect == "rawavg"} {
    $title.bu add makerawavgdir -text "Make Avg/Concat Dir" -width 16 \
       -command "addrawavgscan $nbwin 1" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setuprawavg 50 $helpwinlines }
    entry $title.bu.e -width 18 -textvariable newrawavgdir -font $hfont \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol
    bind $title.bu.e <Return> "[$title.bu subwidget makerawavgdir] invoke"
    set newrawavgdir [expandnewsessdir $rawavgdir]
  }
  if {$aspect == "calcfour"} {
    $title.bu add addfour -text "Fourier Dir" -width 10 \
       -command "addfourscan $nbwin" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setupfour 50 $helpwinlines }
  }
  if {$aspect == "calcrand"} {
    $title.bu add addrand -text "Rand Block Dir" -width 13 \
       -command "addrandscan $nbwin" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setuprand 50 $helpwinlines }
  }
  if {$aspect == "sigavg"} {
    $title.bu add makesigavgdir -text "Make CombineDir" -width 13 \
      -command "addsigavgscan $nbwin 1" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setupsigavg 50 $helpwinlines }
    entry $title.bu.e -width 18 -textvariable newsigavgdir -font $hfont \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol
    bind $title.bu.e <Return> "[$title.bu subwidget makesigavgdir] invoke"
    set newsigavgdir [expandnewsessdir $sigavgdir]
  }
  if {$aspect == "surfavg"} {
    $title.bu add makesurfavgdir -text "Make SurfAvg Dir" -width 14 \
       -command "addsurfavgscan $nbwin 1" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setupsurfavg 50 $helpwinlines }
    entry $title.bu.e -width 18 -textvariable newsurfavgdir -font $hfont \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol
    bind $title.bu.e <Return> "[$title.bu subwidget makesurfavgdir] invoke"
    set newsurfavgdir [expandnewsessdir $surfavgdir]
  }
  if {$aspect == "calcfield"} {
    $title.bu add makefsdir -text "Make FSign Dir" -width 11 \
       -command "addfieldscan $nbwin 1" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setupfield 50 $helpwinlines }
    entry $title.bu.e -width 12 -textvariable newfsdir -font $hfont \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol
    bind $title.bu.e <Return> "[$title.bu subwidget makefsdir] invoke"
    set newfsdir [expandnewsessdir $fsdir]
  }
  if {$aspect == "extstat"} {
    $title.bu add addextstat -text "Extern Stats Dir" -width 13 \
       -command "addextstatscan $nbwin" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setupimport 50 $helpwinlines }
  }
  if {$aspect == "render"} {
    $title.bu add addrender -text "Render Stats Dir" -width 14 \
       -command "addrenderscan $nbwin" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> { helpwin setuprender 50 $helpwinlines }
  }
  if {$aspect == "rendersphavg"} {
    $title.bu add addrender -text "Render SphAvg Dir" -width 15 \
       -command "addrenderscan $nbwin sphavgdir" -highlightbackground $bgcol
    bind $w <ButtonRelease-3> {
      helpwin setuprendersphavg 50 $helpwinlines
      after 2500 { helpwin setuprender 50 $helpwinlines }
    }
  }

  ### make Unset Dir button (was Ignore)
  $title.bu add unsetdir -text "Unset Dir" -width 6 \
     -command "unsetscan $nbwin $aspect" -highlightbackground $bgcol

  ### make action buttons (perform action on current notebook page)
  if {$aspect == "mkorigdirs"} {  ;# exception: perform action on origdir
    $title.bu add makeorigdirs -text "MAKE ORIGDIRS" -width 14 -font $ffontb \
       -command "mkdirscmd $nbwin origdirs" -highlightbackground $bgcol
    $title.bu add copy -text "COPY-RAW" -width 11 -font $ffontb \
       -command "stripinitTRscopyrawcmd origdirs" -highlightbackground $bgcol
    set stripcopybu [$title.bu subwidget copy]
  }
  if {$aspect == "struct"} {
    $title.bu add convertstruct -text "CONVERT/AVERAGE" -width 17 \
       -command "averagestructscmd" -font $ffontb \
       -highlightbackground $bgcol
    set convertstructbu [$title.bu subwidget convertstruct]
    $title.bu add afni -text "AFNI" -width 4 -font $ffontb \
       -command "afnicmdstruct $nbwin" -highlightbackground $bgcol
  }
  if {$aspect == "mkscandirs"} {  ;# exception: perform action on sessiondir
    $title.bu add makescandirs -text "MAKE SCANDIRS" -width 14 -font $ffontb \
       -command "mkdirscmd $nbwin scandirs" -highlightbackground $bgcol
    $title.bu add striptrscopy -text "STRIP/COPY-RAW" -width 14 -font $ffontb \
       -command "stripinitTRscopyrawcmd scandirs" -highlightbackground $bgcol
    set stripcopybu [$title.bu subwidget striptrscopy]
  }
  if {$aspect == "alignfunct"} {
    $title.bu add afni -text "AFNI" -width 4 -font $ffontb \
       -command "afnicmd $nbwin" -highlightbackground $bgcol
    $title.bu add afniall -text "AFNI-ALL" -width 7 -font $ffontb \
       -command "afniallcmd $nbwin" -highlightbackground $bgcol
  }
  if {$aspect == "rawavg"} {
    $title.bu add rawaverage -text "COMBINE" -width 7 -font $ffontb \
       -command "rawaveragecmd $nbwin" -highlightbackground $bgcol
    set rawaveragebu [$title.bu subwidget rawaverage]
    $title.bu add afni -text "AFNI" -width 4 -font $ffontb \
       -command "afnicmd $nbwin" -highlightbackground $bgcol
  }
  if {$aspect == "calcfour"} {
    $title.bu add addcalcfour -text "FOURIER" -width 9 -font $ffontb \
       -command "fouriercmd $nbwin" -highlightbackground $bgcol
    set calcfourbu [$title.bu subwidget addcalcfour]
    $title.bu add addpaint -text "PAINT" -width 7 -font $ffontb \
       -command "paintcmd $nbwin" -highlightbackground $bgcol
    set paintbu [$title.bu subwidget addpaint]
    $title.bu add afni -text "AFNI" -width 4 -font $ffontb \
       -command "afnicmd $nbwin" -highlightbackground $bgcol
  }
  if {$aspect == "calcrand"} {
    $title.bu add addcalcrand -text "DECONVOLVE" -width 11 -font $ffontb \
       -command "deconvcmd $nbwin" -highlightbackground $bgcol
    set calcrandbu [$title.bu subwidget addcalcrand]
    $title.bu add afni -text "AFNI" -width 4 -font $ffontb \
       -command "afnicmd $nbwin" -highlightbackground $bgcol
  }
  if {$aspect == "sigavg"} {
    $title.bu add sigaverage -text "COMBINE" -width 7 -font $ffontb \
       -command "sigaveragecmd $nbwin" -highlightbackground $bgcol
    set sigaveragebu [$title.bu subwidget sigaverage]
    $title.bu add addpaint -text "PAINT" -width 5 -font $ffontb \
       -command "paintcmd $nbwin" -highlightbackground $bgcol
    set paintbu [$title.bu subwidget addpaint]
  }
  if {$aspect == "surfavg"} {
    $title.bu add surfaverage -text "SURFCOMBINE" -width 12 -font $ffontb \
      -command "surfaveragecmd $nbwin" -highlightbackground $bgcol
    set surfaveragebu [$title.bu subwidget surfaverage]
  }
  if {$aspect == "calcfield"} {
    $title.bu add addcalcfield -text "FIELDSIGN" -width 8 -font $ffontb \
       -command "fieldsigncmd $nbwin" -highlightbackground $bgcol
    set calcfieldbu [$title.bu subwidget addcalcfield]
    $title.bu add addborders -text "GROWBORD" -width 9 -font $ffontb \
       -command "findretinborderscmd $nbwin" -highlightbackground $bgcol
    set bordersbu [$title.bu subwidget addborders]
  }
  if {$aspect == "extstat"} {
    $title.bu add convertfunct -text "EXTRACT/CONVERT" -width 15 -font $ffontb \
       -command "convertfunctcmd $nbwin" -highlightbackground $bgcol
    set convertfunctbu [$title.bu subwidget convertfunct]
    $title.bu add addpaint -text "PAINT" -width 6 -font $ffontb \
       -command "paintcmd $nbwin" -highlightbackground $bgcol
    set paintbu [$title.bu subwidget addpaint]
    $title.bu add afni -text "AFNI" -width 4 -font $ffontb \
       -command "afnicmd $nbwin" -highlightbackground $bgcol
  }
  if {$aspect == "render" || $aspect == "rendersphavg"} { ;# special case
    tixButtonBox $title.bu2 -bd 1 -background $bgcol -relief flat \
      -padx 5 -pady 0 -orientation vertical
    $title.bu2 add medtest -text "VOLUME-STATS" -width 14 -font $ffontb \
       -command "medtestrender $nbwin" -highlightbackground $bgcol
    set medrenderbu [$title.bu2 subwidget medtest]
    $medrenderbu config -padx 6 -pady 3  ;# newpkgtix
    $title.bu2 add surftest -text "SURFACE-STATS" -width 14 -font $ffontb \
       -command "surftestrender $nbwin" -highlightbackground $bgcol
    set surfrenderbu [$title.bu2 subwidget surftest]
    $surfrenderbu config -padx 6 -pady 3  ;# newpkgtix
    tixSelect $title.se -allowzero false -radio true -orientation vertical \
      -options "label.background $bgcol"
    $title.se add 0 -text test -font $hfont -width 1 -bg $bgcol -pady 0 \
      -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
    $title.se add 1 -text save -font $hfont -width 1 -bg $bgcol -pady 0 \
       -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
    $title.se config -variable savergbflag
    tixButtonBox $title.bu3 -bd 1 -background $bgcol -relief flat \
      -padx 5 -pady 0 -orientation horizontal
    $title.bu3 add afni -text "AFNI" -width 2 -pady 2 -font $ffontb \
       -command "afnicmd $nbwin" -highlightbackground $bgcol
    ### linked copy of main panel buttons (render only)
    ## linked copy hemi
    tixSelect $dup.hem -allowzero false -radio true -label " hemi:" \
      -orientation horizontal -options "label.width 6"
    $dup.hem subwidget label config -bg $bgcol -font $tfont  ;# tix options bug
    $dup.hem add rh \
      -text RIGHT -font $sfont -width 3 -bg $bgcol -padx 9 -pady 3 \
      -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
    $dup.hem add lh \
      -text LEFT -font $sfont -width 3 -bg $bgcol -padx 9 -pady 3 \
      -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
    $dup.hem add both \
      -text BOTH -font $sfont -width 3 -bg $bgcol -padx 9 -pady 3 \
      -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
    $dup.hem config -variable hemi  ;# BOTH valid renders successively
    ## HOWTO fullconfig tixComboBox options (most defs in configtixbookcbxent)
    # tixComboBox ... 
    #   -options "frame.background $bgcol
    #             label.width 6
    #             label.font $tfont
    #             label.background $bgcol
    #             entry.width 16
    #             entry.font $hfont
    #             entry.selectBackground $selbgcol
    #             entry.highlightBackground $bgcol
    #             arrow.highlightBackground $bgcol
    #             listbox.height 10
    #             listbox.width 10
    #             listbox.font $hfont
    #             listbox.selectBackground $selbgcol"
    ## linked copy surface
    tixComboBox $dup.surfcbx -label "surface:" -dropdown true \
      -command cbx:select_surface2 -editable true \
      -variable surfext -listwidth 208 \
      -options "label.width 7 listbox.height 18" ;# listbox.width 20 -> 25
    $dup.surfcbx subwidget entry config -width 11  ;# tix options bug
    $dup.surfcbx subwidget listbox config -font $hfont  ;# tix options bug
    set surflist [$surfacescombo subwidget listbox get 0 end]
    foreach surf [lsort $surflist] { $dup.surfcbx insert end $surf }
    set surfacescombo2 $dup.surfcbx
    ## linked copy patch
    tixComboBox $dup.patchcbx -label "patch:" -dropdown true \
      -command cbx:select_patch2 -editable true \
      -variable patchext -listwidth 208 \
      -options "label.width 6 listbox.height 18" ;# listbox.width 20 -> 25
    $dup.patchcbx subwidget entry config -width 16  ;# tix options bug
    $dup.patchcbx subwidget listbox config -font $hfont  ;# tix options bug
    set patchlist [$patchescombo subwidget listbox get 0 end]
    foreach patch [lsort $patchlist] { $dup.patchcbx insert end $patch }
    pack $dup.hem $dup.surfcbx $dup.patchcbx -side left -padx 5 -pady 5
    set patchescombo2 $dup.patchcbx
    ## one-time single-subj-only render to fsaverage checkbutton
    if {$aspect == "render" || $aspect == "rendersphavg"} {
      checkbutton $dup.ck -font $ffont -text "fsavg" \
        -selectcolor $selcol -bg $bgcol -highlightbackground $bgcol \
        -variable sing2fsavgflag  ;# -command reloadsurfcombos
      pack $dup.ck -side left -padx 0
#xxxxxxxx -- opphemi: unfinished
      bind $dup.ck <ButtonRelease-2> {  ;# overload, also set main check
        if {$hemi == "rh"} { set opphemi lh }
        if {$hemi == "lh"} { set opphemi rh }
        set oppfsavghemiflag 0
        if ![okreplace "" \
             "OK to display following SURFACE-STATS overlay\
            \non *opposite* hemi ($opphemi) of fsaverage?" \
             "Display on Opposite"] {
          confirmalert "Not displaying on opposite hemisphere"
        } else { set sing2fsavgflag 1; set oppfsavghemiflag 1 }
      }
      bind $dup.ck <Shift-ButtonRelease-2> {  ;# 2nd overload, fix others
        set oppfsavghemiflag 0
        set sing2fsavgflag 1
        set sing2singflag 1
        # TODO: modal control w/combobox loaded from curr SUBJECTS_DIR
        modalcontrols "ENTER ANOTHER SUBJECT TO RESAMPLE TO" anothersub1time 25
      }
      bind $dup.ck <ButtonRelease-3> {
        helpwin fsavg 50 $helpwinlines  ;# hack: only subpanel-specific help
      }
      bindtags $dup.ck "$dup.ck Checkbutton all"  ;# rm $w (.setuppopup)
    }
  }

  ### pack/config action buttons
  pack $title.la -side left -anchor w
  # newpkgtix: mods
  pack $title.bu -side left -ipadx 13
  if {$aspect == "rendersphavg"} {  ;# squish for long xsub session names
    pack $title -padx 3
    pack $title.bu -ipadx 5    ;# newpkgtix: ipadx (vs. padx)
    $title.bu2 config -padx 3
    $medrenderbu config -padx 3
    $title.bu3 config -padx 3
    $surfrenderbu config -padx 3
  }
  # newpkgtix: butt box butt size defaults -padx 3m, -pady 1m bigger
  foreach bu [info commands $title.bu.*] {
    if ![string match *.e $bu] { $bu config -padx 6 -pady 3 }
  }

  ### insert extras into top-of-page actions (mkdir entry, non-std render)
  if {$aspect == "rawavg" || $aspect == "sigavg" || \
      $aspect == "surfavg" || $aspect == "calcfield"} {
    if {$aspect == "rawavg"}    { set subwidgetname makerawavgdir }
    if {$aspect == "sigavg"}    { set subwidgetname makesigavgdir }
    if {$aspect == "surfavg"}   { set subwidgetname makesurfavgdir }
    if {$aspect == "calcfield"} { set subwidgetname makefsdir }
    pack [$title.bu subwidget $subwidgetname] -padx 0
    pack $title.bu.e -before [$title.bu subwidget unsetdir] -side left -padx 0
    frame $title.bu.sp1 -width 6 -bg $bgcol
    pack $title.bu.sp1 -before [$title.bu subwidget unsetdir] -side left
  }
  if {$aspect == "render" || $aspect == "rendersphavg"} {
    pack $title.bu2 $title.se $title.bu3 -side left  ;# incl. test/sv + AFNI
    #pack $title.bu2 $title.se -side left  ;# incl. test/sv
    #pack $title.bu2 -side left
  }

  ### make list notebook
  tixListNoteBook $nbwin -ipadx 6 -ipady 6 -background $bgcol \
    -options "pane.orientation horizontal shlist.scrollbar auto"
  $nbwin subwidget hlist config -font $hfont  ;# newpkgtix: tix options bug
  set hlist [$nbwin subwidget hlist]
  #$hlist config -header true -separator "!"   ;# -width 23 (default 20)
  $hlist config -header true -separator "!" -width 23  ;# (default 20)
  set hstyle [tixDisplayStyle text -refwindow $hlist \
    -padx 8 -pady 2 -font $tfont]
  $hlist header create 0 -itemtype text -text "$htitletext" -style $hstyle

  ### first read datfile (may contain configs for no-longer-existing dirs)
  if [file exists $datfile] {
    readarrayparms $datfile $aspect
  } else {
    cleararrays $aspect
  }
  if {$aspect == "mkorigdirs"} { cleararrays $aspect } ;# clear prev mkorigdirs
  if {$aspect == "mkscandirs"} { cleararrays $aspect } ;# clear prev mkscandirs

  ### then find existing dirs for listbox (check/warn *,? in dirname)
  if {$aspect == "mkorigdirs"} { ; }  ;# test above excludes existing dirs
  if {$aspect == "struct"} { set scandirslist [getstructscandirslist] }
  if {$aspect == "mkscandirs"} { ; }  ;# test above excludes existing dirs
  if {$aspect == "alignfunct" || $aspect == "rawavg" || \
      $aspect == "calcfour" || $aspect == "calcrand" || \
      $aspect == "sigavg" || $aspect == "surfavg" || \
      $aspect == "calcfield" || $aspect == "extstat" || \
      $aspect == "render" || $aspect == "rendersphavg"} {
    set scandirslist [getfunctiscandirslist]
  }
  if { [string match *\\** $scandirslist] || \
       [string match *\\?* $scandirslist] } {
    set formatlist ""
    foreach sdir $scandirslist {
      if { [string match *\\** $sdir] || [string match *\\?* $sdir ]} {
        set formatlist "${formatlist}\n${sdir}   =>   remove * or ?"
      } else {
        set formatlist "${formatlist}\n${sdir}   =>   OK"
      }
    }
    confirmalert "Can't have asterisks or question marks in scan dir names:\n\
       $formatlist\n\n ...then re-select session"
    if [winfo exists $w] { destroy $w }
    return
  }

  ### make nb pages (empty page for all existdirs: $mpage=mangleddir,$page=dir)
  # get curr page in global context: [demanglepath [.setuppopup.to.no raised]]
  foreach page $scandirslist {
    set mpage [manglepath $page] ;# period,initCAP: hlist->OK, nbpageframe->bad
    if [badscandirname $mpage] { continue }
    $nbwin subwidget hlist add $mpage -text $page

    if {$aspect == "mkorigdirs"} { } ;# no pages to make (widgets in main pane)
    if {$aspect == "struct"} {
      $nbwin add $mpage
    }
    if {$aspect == "mkscandirs"} { } ;# no pages to make (widgets in main pane)
    if {$aspect == "alignfunct"} {  ;# subst only currpage at cmdtime
      $nbwin add $mpage -raisecmd "set iscandir $page; fixfocus $page $title; \
        set prevpage \$currpage; set currpage $page; findaligns $page; \
        findvregtargs $page"
#xxxxxxxxxxxxx -- if surely 1st time, auto-clk Funct/Align Scan + READ HEADER??
#TODO: might be just Unset (which unsets this var), and we shouldn't reinstate
#     if ![info exists sessionscanlists($page,type)] {
#       if { [string match "image/?-*" $mpage] ||
#            [string match "image/align" $mpage] } {
#         set sessionscanlists($page,type) alignfunct
#         set clickreadheaderflag 1
#       }
#     }
    }
    # next: iscandir visible in global execution context
    if {$aspect == "rawavg"} {
      $nbwin add $mpage -raisecmd "set iscandir $page; \
        set prevpage \$currpage; set currpage $page; findrawavgfuncts $page"
    }
    if {$aspect == "calcfour"} {
      $nbwin add $mpage -raisecmd "set iscandir $page; \
        set prevpage \$currpage; set currpage $page"
    }
    if {$aspect == "calcrand"} {
      $nbwin add $mpage -raisecmd "set iscandir $page; \
        set prevpage \$currpage; set currpage $page"
    }
    if {$aspect == "sigavg"} {
      $nbwin add $mpage -raisecmd "set iscandir $page; \
        set prevpage \$currpage; set currpage $page; findsigavgfuncts $page"
    }
    if {$aspect == "surfavg"} {
      $nbwin add $mpage -raisecmd "set iscandir $page; \
        set prevpage \$currpage; set currpage $page; findsurfavgfuncts $page"
    }
    if {$aspect == "calcfield"} {
      $nbwin add $mpage -raisecmd "set iscandir $page; \
        set prevpage \$currpage; set currpage $page; findretins $page"
    }
    if {$aspect == "extstat"} {
      $nbwin add $mpage -raisecmd "set iscandir $page;
        set prevpage \$currpage; set currpage $page"
    }
    if {$aspect == "render" || $aspect == "rendersphavg"} { 
      $nbwin add $mpage -raisecmd "set iscandir $page; \
        set prevpage \$currpage; set currpage $page"
    }
    set f [$nbwin subwidget $mpage]
    $f config -background $bgcol
  }
  pack $nbwin -expand yes -fill both -padx 5 -pady 5

  ### make bottom panel buttons
  set box $w.bo
  tixButtonBox $box -bd 1 -relief raised -background $bgcol
  $box config -pady 10  ;# newpkgtix
  pack $box -side top -fill both
  $box add ok -text "Save/Close" -width 12 -highlightbackground $bgcol \
     -command "writearrayparms $datfile $aspect; checkdestroy $w $nbwin"
  $box add save -text "Save" -width 12 -highlightbackground $bgcol \
     -command "writearrayparms $datfile $aspect"
  $box add cancel -text "Cancel" -width 12 -highlightbackground $bgcol \
     -command "checkdestroy $w $nbwin"
  # newpkgtix: new butt box def -pady 1m is thicker
  foreach sw "ok save cancel" { $box subwidget $sw config -pady 3 }
  if {$aspect == "mkorigdirs" || $aspect == "mkscandirs" } { ;# hack std panel
    pack forget [$box subwidget save] [$box subwidget ok]
    pack forget [$title.bu subwidget unsetdir]
    $box subwidget cancel config -text "Close"
  }

  ### horrible tmp hack gives 20x draw speed if AppNap (moved to earlier above)
  #if {$mac_appnap_hack} {
  #  set pid [exec xterm -geom 100x50${geom} -bg $bgcol -e bash --norc &]
  #}

  ### make widgets for existing dirs that are config'd in datfile
  set currpage def
  set prevpage  def
  if { [file exists $datfile] && [$nbwin pages] != "" } {
    foreach mpage [$nbwin pages] {
      $nbwin raise $mpage
      tkwait visibility [$nbwin subwidget $mpage]
      set page [demanglepath $mpage]

      # skip unconfig'd (new dirs made after dat left unconfig'd)
      if {$aspect == "struct"} {
        if ![info exists structscanlists($page,type)] { continue }
      }
      if {$aspect == "alignfunct" || $aspect == "rawavg" || \
          $aspect == "calcfour" || $aspect == "calcrand" || \
          $aspect == "sigavg" || $aspect == "surfavg" || \
          $aspect == "calcfield" || $aspect == "extstat" || \
          $aspect == "render" || $aspect == "rendersphavg"} {
        if ![info exists sessionscanlists($page,type)] { continue }
      }

      # show config'd (config'd-no-longer-there dirs ignored--not in pagelist)
      if {$aspect == "mkorigdirs"} { } ;# no origdirs to make widgets for
      if {$aspect == "struct"} {
        if {$structscanlists($page,type) == "structscan"} \
                                                         {addstructscan $nbwin}
      }
      if {$aspect == "mkscandirs"} { } ;# no scandirs to make widgets for
      if {$aspect == "alignfunct"} {
        if {$sessionscanlists($page,type) == "alignscan"} \
                                                        {addalignscan $nbwin 0}
        if {$sessionscanlists($page,type) == "functscan"} \
                                                        {addfunctscan $nbwin 0}
        if [info exists functscanlists($page,extstatfunctims)] {
          if {$sessionscanlists($page,type) == "extstatscan" && \
              $functscanlists($page,extstatfunctims)}   {addfunctscan $nbwin 0}
        }
      }
      if {$aspect == "calcfield"} {
        if {$sessionscanlists($page,type) == "fsscan"}  {addfieldscan $nbwin 0}
      }
      if {$aspect == "extstat"} {
        if {$sessionscanlists($page,type) == "extstatscan"} \
                                                        {addextstatscan $nbwin}
      }
      # functscantypes:rawavg/calcfour/calcrand/sigavg/surfavg/render
      if {$aspect == "rawavg"} {     ;# (re-config'd as notfunct ignored)
        if [info exists functscanlists($page,rawavgflag)] {
          if {$sessionscanlists($page,type) == "functscan" && \
              $functscanlists($page,rawavgflag)}       {addrawavgscan $nbwin 0}
          if {$sessionscanlists($page,type) == "extstatscan" && \
              $functscanlists($page,rawavgflag)}       {addrawavgscan $nbwin 0}
        }
      }
      if {$aspect == "calcfour"} {
        if [info exists functscanlists($page,fourflag)] {
          if {$sessionscanlists($page,type) == "functscan" && \
              $functscanlists($page,fourflag)}          {addfourscan $nbwin}
        }
      }
      if {$aspect == "calcrand"} {
        if [info exists functscanlists($page,randflag)] {
          if {$sessionscanlists($page,type) == "functscan" && \
              $functscanlists($page,randflag)}          {addrandscan $nbwin}
          if {$sessionscanlists($page,type) == "extstatscan" && \
              $functscanlists($page,randflag)}          {addrandscan $nbwin}
        }
      }
      if {$aspect == "sigavg"} {
        if [info exists functscanlists($page,sigavgflag)] {
          if {$sessionscanlists($page,type) == "functscan" && \
              $functscanlists($page,sigavgflag)}       {addsigavgscan $nbwin 0}
        }
      }
      if {$aspect == "surfavg"} {
        if [info exists functscanlists($page,surfavgflag)] {
          if {$sessionscanlists($page,type) == "functscan" && \
              $functscanlists($page,surfavgflag)}     {addsurfavgscan $nbwin 0}
        }
      }
      if {$aspect == "render"} {
        if [info exists functscanlists($page,renderflag)] {
          if {$sessionscanlists($page,type) == "functscan" || \
              $sessionscanlists($page,type) == "fsscan" || \
              $sessionscanlists($page,type) == "extstatscan"} {
            if {$functscanlists($page,renderflag)}      {addrenderscan $nbwin}
          }
        }
      }
      if {$aspect == "rendersphavg"} {
        if [info exists functscanlists($page,renderflag)] {
          if {$sessionscanlists($page,type) == "sphavgscan"} {
            if {$functscanlists($page,renderflag)} { \
                                                addrenderscan $nbwin sphavgdir}
          }
        }
      }
    } ;# for each notebook page
    # go back and show first page, update scandir entry
    set mpage [lindex [$nbwin pages] 0]
    $nbwin raise $mpage
    if {$aspect == "struct"} {  ;# avoid scandir not found from touch iscandir
      $scandirscombo config -disablecallback true
    }
    set iscandir [demanglepath $mpage]
  }
  if {$mac_appnap_hack} { exec kill $pid }  ;# done w/horrible tmp hack
  wm protocol $w WM_DELETE_WINDOW "checkdestroy $w $nbwin"
  $subjectscombo config -state disabled
  $sessionscombo config -state disabled
  $scandirscombo config -state disabled
  wm resizable $w 0 0

  # logs,bitmaps bindings also avail from toplevel panels
  bind $w <$xcmd-l> {
    if {$logflag} {set logflag 0; hidelogs} else {set logflag 1; showlogs}
  }
  bind $w <$xcmd-b> { viewbitmaps }

  # auto-click the (useless) "Find Raw Scans/Structs" button to make the panel
  if {$aspect == "mkscandirs"} { $title.bu.addmkdirs invoke }
  if {$aspect == "mkorigdirs"} { $title.bu.addmkdirs invoke }

  # earlier warn wrong rendertype (also blocked at set Render Stats/SphAvg Dir)
  set page [lindex [$nbwin pages] 0]
  if { $aspect == "render" } {
    if { [info exists sessionscanlists($page,type)] &&
         $sessionscanlists($page,type) == "sphavgscan" } {
      confirmalert "View Functional Data: first scandir:\
                \n\n    $page\
                \n\ncurrently config'd as Cross Sess Average Dir\
                  \n(not Align or Funct Scan)\
              \n\nViewing with \"CrossSessTools -> View Sphavg Data\" instead"
      #tkwait visibility $box  ;# N.B.: hangs if already visible
      set makingsetupscan 0    ;# else cancel cancelled
      $box invoke cancel
      setupscans rendersphavg
    }
  }
  if { $aspect == "rendersphavg" } {
    if { [info exists sessionscanlists($page,type)] &&
         $sessionscanlists($page,type) == "functscan" } {
      confirmalert "View SphereAvg Data: first scandir:\
                \n\n    $page\
                \n\ncurrently config'd Align or Funct Scan Dir\
                  \n(not Cross Sess Average)\
              \n\nViewing with \"SessionTools -> View Functional Data\" instead"
      #tkwait visibility $box  ;# N.B.: hangs if already visible
      set makingsetupscan 0
      $box invoke cancel
      setupscans render
    }
  }
  #bind $w.ti.la <Double-Button-1> { raise . }  ;# awk b/c gets in csurf entries
  bind $w.ti.la <Double-Button-1> {
    confirmalert "CURRENT LOCATION\
              \n\n    subj:  $env(SUBJECTS_DIR)/$name\
              \n\n    sess:  $env(FUNCTIONALS_DIR)/$session"
  }
  bind $w.bo <Double-Button-1> { raise . }

  set makingsetupscan 0
}

### check for running background processes (active buttons) at panel close
proc checkdestroy { w nbwin } {
  global medrenderbu surfrenderbu
  global rawaveragebu calcfourbu calcrandbu
  global sigaveragebu surfaveragebu calcfieldbu bordersbu paintbu
  global align2subjbu funct2subjbu
  global vregall2selbu vregcurr2selbu
  global subjectscombo sessionscombo scandirscombo selbgcol makingsetupscan

  if {$makingsetupscan} { return }  ;# don't destroy tkwaiting visibility

  set mrendrunning 0
  set srendrunning 0
  set 3dvolregrunning 0
  set rawaveragerunning 0
  set calcfieldrunning 0
  set sigaveragerunning 0
  set surfaveragerunning 0
  set calcfourrunning 0
  set calcrandrunning 0
  set paintrunning 0
  set registerrunning 0
  set all2selrunning 0
  set curr2selrunning 0

  ### strings here assume 2 spaces appended to buttonlabel arg to runacmd
  # 2 label chars trimmed: runacmd truncs 4 for "Quit", 2 spaces added to arg
  if { [info exists medrenderbu] && [info commands $medrenderbu] != ""} {
    if {[$medrenderbu cget -text] == "QuitVOLUME-STA"} { set mrendrunning 1 }
  }
  if { [info exists surfrenderbu] && [info commands $surfrenderbu] != ""} {
    if {[$surfrenderbu cget -text] == "QuitSURFACE-STA"} { set srendrunning 1 }
  }
  if { [info exists rawaveragebu] && [info commands $rawaveragebu] != ""} {
    if {[$rawaveragebu cget -text] == "QuitCOMBI"} { set rawaveragerunning 1 }
  }
  if { [info exists calcfourbu] && [info commands $calcfourbu] != ""} {
    if {[$calcfourbu cget -text] == "QuitFOURI"} { set calcfourrunning 1 }
  }
  if { [info exists calcrandbu] && [info commands $calcrandbu] != ""} {
    if {[$calcrandbu cget -text] == "QuitDECONVOL"} { set calcrandrunning 1 }
  }
  if { [info exists sigaveragebu] && [info commands $sigaveragebu] != ""} {
    if {[$sigaveragebu cget -text] == "QuitCOMBI"} \
                                                 { set sigaveragerunning 1 }
  }
  if { [info exists surfaveragebu] && [info commands $surfaveragebu] != ""} {
    if {[$surfaveragebu cget -text] == "QuitSURFCOMBI"} \
                                                 { set surfaveragerunning 1 }
  }
  if { [info exists calcfieldbu] && [info commands $calcfieldbu] != ""} {
    if {[$calcfieldbu cget -text] == "QuitFIELDSI"} { set calcfieldrunning 1 }
  }
  if { [info exists bordersbu] && [info commands $bordersbu] != ""} {
    if {[$bordersbu cget -text] == "QuitFIELDSI"} { set calcfieldrunning 1 }
  }
  if { [info exists paintbu] && [info commands $paintbu] != ""} {
    if {[$paintbu cget -text] == "QuitPAI"} { set paintrunning 1 }
  }
  set mpages [$nbwin pages]
  foreach mpage $mpages {
    set page [demanglepath $mpage]
    # 4 label chars trimmed since no spaces added to small buttonlabel arg
    if { [info exists align2subjbu($page)] && \
         [info commands align2subjbu($page)] != ""} {
      if {[$align2subjbu($page) cget -text] == "QuitALIGN=>"} \
                                                     { set registerrunning 1 }
    }
    if { [info exists funct2subjbu($page)] && \
         [info commands $funct2subjbu($page)] != ""} {
      if {[$funct2subjbu($page) cget -text] == "QuitFUNCT=>"} \
                                                     { set registerrunning 1 }
    }
    if { [info exists vregall2selbu($page)] && \
         [info commands $vregall2selbu($page)] != ""} {
      if { [$vregall2selbu($page) cget -text] == "QuitAL"} \
                                                     { set all2selrunning 1 }
    }
    if { [info exists vregcurr2selbu($page)] && \
         [info commands $vregcurr2selbu($page)] != ""} {
      if { [$vregcurr2selbu($page) cget -text] == "QuitCUR"} \
                                                     { set curr2selrunning 1 }
    }
  }

  if {$mrendrunning || $srendrunning} {
    confirmalert "Quit test render(s) first"
  } elseif {$3dvolregrunning} {
    confirmalert "Quit 3d volume register first"
  } elseif {$rawaveragerunning} {
    confirmalert "Quit raw average scans first"
  } elseif {$calcfourrunning} {
    confirmalert "Quit calc fourier stats first"
  } elseif {$calcrandrunning} {
    confirmalert "Quit calc random block stats first"
  } elseif {$sigaveragerunning} {
    confirmalert "Quit phase combine scans first"
  } elseif {$surfaveragerunning} {
    confirmalert "Quit surface average scans first"
  } elseif {$calcfieldrunning} {
    confirmalert "Quit calc fieldsign first"
  } elseif {$paintrunning} {
    confirmalert "Quit paint first"
  } elseif {$registerrunning} {
    confirmalert "Quit register first (may be on another page)"
  } elseif {$all2selrunning} {
    confirmalert "Quit 3dvolreg all->selected first (may be on another page)"
  } elseif {$curr2selrunning} {
    confirmalert "Quit 3dvolreg curr->selected first (may be on another page)"
  } else {
    destroy $w
    foreach cbx "$subjectscombo $sessionscombo $scandirscombo" {
      $cbx config -state normal
      $cbx subwidget entry config -selectbackground $selbgcol   ;# tix8.4+
      $cbx subwidget listbox config -selectbackground $selbgcol ;# tix8.4+
    }

    if [info exists medrenderbu]  { unset medrenderbu }
    if [info exists surfrenderbu] { unset surfrenderbu }
    if [info exists rawaveragebu] { unset rawaveragebu }
    if [info exists calcfourbu]   { unset calcfourbu }
    if [info exists calcrandbu]   { unset calcrandbu }
    if [info exists sigaveragebu] { unset sigaveragebu }
    if [info exists surfaveragebu] { unset surfaveragebu }
    if [info exists calcfieldbu]  { unset calcfieldbu }
    if [info exists bordersbu]    { unset bordersbu }
    if [info exists paintbu]      { unset paintbu }
    foreach mpage $mpages {
      set page [demanglepath $mpage]
      if [info exists align2subjbu($page)]   { unset align2subjbu($page) }
      if [info exists funct2subjbu($page)]   { unset funct2subjbu($page) }
      if [info exists vregall2selbu($page)]  { unset vregall2selbu($page) }
      if [info exists vregcurr2selbu($page)] { unset vregcurr2selbu($page) }
    }
  }
}

### config bg/border colors tixListNoteBook/tixComboBox/tixLabelEntry's
proc configtixbookcbxent { w } {
  global selbgcol bgcol entbgcol tfont hfont ffont

  set name [tixOptionName $w]
  # ListNoteBook
  #option add *$name*TixListNoteBook*.background $bgcol   ;# works but blinks
  option add *$name*TixListNoteBook*p1.background $bgcol  ;# vs. kinda internal
  option add *$name*TixListNoteBook*p2.background $bgcol  ;# vs. kinda internal
  option add *$name*TixListNoteBook*hlist.selectBackground $selbgcol
  # ComboBox
  option add *$name*TixComboBox*frame.background $bgcol
  option add *$name*TixComboBox*label.background $bgcol
  option add *$name*TixComboBox*label.font $tfont
  # next 2: newpkgtix
  option add *$name*TixComboBox*entry.font $hfont
  option add *$name*TixComboBox*listbox.font $hfont
  option add *$name*TixComboBox*entry.background $entbgcol
  option add *$name*TixComboBox*entry.highlightBackground $bgcol
  option add *$name*TixComboBox*entry.selectBackground $selbgcol
  option add *$name*TixComboBox*entry.selectForeground black    ;# linux
  option add *$name*TixComboBox*entry.disabledForeground #555555
  option add *$name*TixComboBox*arrow.highlightBackground $bgcol
  option add *$name*TixComboBox*listbox.selectBackground $selbgcol
  option add *$name*TixComboBox*listbox.selectForeground black  ;# linux
  # TixLabelEntry
  option add *$name*TixLabelEntry*label.width 27
  option add *$name*TixLabelEntry*label.anchor e
  option add *$name*TixLabelEntry*label.background $bgcol
  option add *$name*TixLabelEntry*label.font $tfont
  option add *$name*TixLabelEntry*entry.font $ffont
  option add *$name*TixLabelEntry*entry.background $entbgcol
  option add *$name*TixLabelEntry*entry.width 14
  option add *$name*TixLabelEntry*entry.highlightBackground $bgcol
  option add *$name*TixLabelEntry*entry.selectBackground $selbgcol
  option add *$name*TixLabelEntry*entry.selectForeground black  ;# linux
  # TixButtonBox, TixLabelFrame, TixSelect
  # next 2: newpkgtix
  option add *$name*TixButtonBox*font $hfont
  option add *$name*TixLabelFrame*label.font $tfont
}

### update black focus border onto appropriate pickdir button
proc fixfocus { page title } {
  global sessionscanlists
  if [info exists sessionscanlists($page,type)] {
   if {$sessionscanlists($page,type) == "functscan"} {focus $title.bu.addfunct}
   if {$sessionscanlists($page,type) == "alignscan"} {focus $title.bu.addalign}
  }
}

### reset name (traces update surfaces/patches) after change fsavg button state
proc reloadsurfcombos { } {  ;# currently: NOT USED
  global name sing2fsavgflag singname fsaverage
  if ![info exists singname] { set singname $name } ;# 1sttime: create/getcurr
  # callbacks reload orig/dup combos, but req's too many hacks in surftestrend
  if {$sing2fsavgflag} { set name $fsaverage } else { set name $singname }
}

### re-lookup surfaces after select hemi (rh/lh surfs may not all be there yet)
proc updatesurfaces { butitle buval } {
  global surfacescombo patchescombo
  $surfacescombo config -disablecallback true
  $patchescombo config -disablecallback true
  fixsurfaces 0 0 0
  fixpatches 0 0 0
  $surfacescombo config -disablecallback false
  $patchescombo config -disablecallback false
}

### Struct Scan Dir button command--make one notebook page of widgets
proc addstructscan { nbwin } {
  global env name volumedir origdir origsubdir
  global bgcol selcol ffontb ffont
  global structscanlists imagescombo

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set origsubdir $page   ;# global, like iscandir

  set structscanlists($page,type) structscan

  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la -label "Structural Scan Directory" -labelside acrosstop \
    -background $bgcol -padx 10 -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2    ;# newpkgtix internal ugh
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  set imagescombo($page) $f.cbx
  tixComboBox $f.cbx -label "Image File:" -dropdown true \
    -command cbx:select_structimage -editable true -listwidth 208 \
    -variable structscanlists($page,modelimage)
  # width fail w/-options
  $f.cbx subwidget label config -width 10
  $f.cbx subwidget entry config -width 15
  $f.cbx subwidget listbox config -width 10

  fiximages $page structscan

  foreach parm { flipx flipy flipz extraopts mgzout } {
    if ![info exists structscanlists($page,$parm)] {
      set structscanlists($page,$parm) $structscanlists(def,$parm)
    }
  }
  set fullsubdir $env(SUBJECTS_DIR)/$name/$volumedir/$origdir/$page
  set selectedimage $fullsubdir/\$structscanlists($page,modelimage) ;# wait
  button $f.cbx.bu -text "READ HEADER" -font $ffontb -pady 2 -padx 11 \
   -command "readheader $selectedimage $page structscan" \
   -highlightbackground $bgcol
  pack $f.cbx $f.cbx.bu -padx 11
  $f.cbx config -background $bgcol

  # why? (separate config lines fix => if mangle: entries not updated)
  #tixLabelEntry $f.a -label "Image Name Format: " -labelside left \
  #  -options "entry.textVariable structscanlists($page,imagepatt)"
  tixLabelEntry $f.a -label "Image Name Format: " -labelside left
  $f.a subwidget entry config -textvariable structscanlists($page,imagepatt)
  tixLabelEntry $f.b -label "Scan Type: " -labelside left
  $f.b subwidget entry config -textvariable structscanlists($page,imtype)
  tixLabelEntry $f.c -label "Slice Count: " -labelside left
  $f.c subwidget entry config -textvariable structscanlists($page,slices)
  tixLabelEntry $f.d -label "Image X Size: " -labelside left
  $f.d subwidget entry config -textvariable structscanlists($page,xres)
  tixLabelEntry $f.e -label "Image Y Size: " -labelside left
  $f.e subwidget entry config -textvariable structscanlists($page,yres)
  tixLabelEntry $f.f -label "In Plane (mm): " -labelside left
  $f.f subwidget entry config -textvariable structscanlists($page,inplane)
  tixLabelEntry $f.g -label "Thickness (mm): " -labelside left
  $f.g subwidget entry config -textvariable structscanlists($page,thickness)
  tixLabelEntry $f.h0 -label "Other Options: " -labelside left
  $f.h0 subwidget entry config -textvariable structscanlists($page,extraopts)
  $f.h0 subwidget entry config -width 30
  $f.h0 subwidget label config -width 13 
  label $f.la -font $ffont -bg $bgcol \
    -text "-floatfac <f>      => multiply by this                     \
         \n-prescale <f>    => divide by this                       \
         \n-hires              => resample to 512^3/0.5mm       \
         \n-noresamp        => assume 1mm (-hres: 0.5mm)    \
         \n-zeropixwidth    => mgz spaceXYZ=0 for freeview\
         \n(additional: see brik2cor)                         "
  frame $f.h -bg $bgcol
  label $f.h.la -text "Flip (from COR View):" -bg $bgcol -width 18
  # why? (separate config lines fix => if mangle: entries not updated)
  tixLabelEntry $f.h.x -label "x=>" -bg $bgcol -labelside left
  $f.h.x subwidget entry config -textvariable structscanlists($page,flipx)
  tixLabelEntry $f.h.y -label "y=>" -bg $bgcol -labelside left
  $f.h.y subwidget entry config -textvariable structscanlists($page,flipy)
  tixLabelEntry $f.h.z -label "z=>" -bg $bgcol -labelside left
  $f.h.z subwidget entry config -textvariable structscanlists($page,flipz)
  foreach wi "$f.h.x $f.h.y $f.h.z" { $wi subwidget label config -width 4 }
  foreach wi "$f.h.x $f.h.y $f.h.z" { $wi subwidget entry config -width 3 }

  checkbutton $f.i -selectcolor $selcol -bg $bgcol \
    -text "Adjust Targ Scan Before Align Other Scans to It (COR only)" \
    -variable convparms(adjusttargflag) -highlightbackground $bgcol
  checkbutton $f.j -selectcolor $selcol -bg $bgcol \
    -text "Generate .mgz output (vs. COR dir) -- BRIK input only" \
    -variable structscanlists($page,mgzout) -highlightbackground $bgcol

  pack $f.a $f.b $f.c $f.d $f.e $f.f $f.g -side top -padx 10 -pady 2
  pack $f.h0 $f.la $f.h -side top -padx 10 -pady 2
  pack $f.h.la $f.h.x $f.h.y $f.h.z -side left -pady 2
  pack $f.i $f.j -side top -pady 2
  update idletasks
}

### start chooserawscan from parent dir of last-selected raw scan
proc chooserawscan { index rawfileentry } {
  global mkdrawscanfiles lastrawscandir

  if [info exists lastrawscandir] {set mkdrawscanfiles($index) $lastrawscandir}
  choosefile mkdrawscanfiles($index)
  tkwait variable mkdrawscanfiles($index)
  set lastrawscandir [file dirname $mkdrawscanfiles($index)]/
  $rawfileentry xview moveto 1   ;# show tail of long path
}

### create/destroy line of widgets/vars/defvals for one proposed orig/scandir
proc scandirwline { action enswin type } {
  global mkdscandirnames mkdrawscanfiles mkdstripinitTRs mkdnewscannames
  global defnumTRstostrip bgcol selbgcol entbgcol ffontb hfont

  set scandirlinelist [lsort [info commands $enswin.li??]]
  if {$action == "add"} { 
    set num [format "%02d" [llength $scandirlinelist]]
    frame $enswin.li$num -bg $bgcol
    if [info exists mkdscandirnames($num)]  { unset mkdscandirnames($num) }
    if [info exists mkdrawscanfiles($num)]  { unset mkdrawscanfiles($num) }
    if [info exists mkdstripinitTRs($num)]  { unset mkdstripinitTRs($num) }
    if [info exists mkdnewscannames($num)]  { unset mkdnewscannames($num) }
    entry $enswin.li$num.e0 -textvariable mkdscandirnames($num) -width 15 \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
      -selectforeground black -font $hfont ;# black: linux, font: newpkgtix
    entry $enswin.li$num.e1 -textvariable mkdrawscanfiles($num) -width 27 \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
      -selectforeground black -font $hfont  ;# font: newpkgtix
    entry $enswin.li$num.e2 -textvariable mkdstripinitTRs($num) -width 2 \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
      -selectforeground black -font $hfont  ;# font: newpkgtix
    entry $enswin.li$num.e3 -textvariable mkdnewscannames($num) -width 25 \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
      -selectforeground black -font $hfont  ;# font: newpkgtix
    set mkdstripinitTRs($num) $defnumTRstostrip
    if {$type == "origdirs"} {
      set n $num
      while { [string match 0* $n] } { set n [string range $n 1 end] } ;#fixhex
      set onebased [expr $n + 1]    ;# empty n OK
      set defscandir mprage$onebased
    }
    if {$type == "scandirs"} {
      set defscandir ${num}-
      if [string match 0* $defscandir] { ;# strip leading zero for name
        set defscandir [string range $defscandir 1 end]
      } 
      if {$defscandir == "0-"} {    ;# zero'th is alignscan
        set defscandir alignscan    ;# was "mprage"
        set mkdstripinitTRs($num) 0
      }
    }
    set mkdscandirnames($num) $defscandir
    button $enswin.li$num.bu -text FIND -font $ffontb -pady 0 -padx 5 \
     -highlightbackground $bgcol -command "chooserawscan $num $enswin.li$num.e1"
    pack $enswin.li$num -side top
    pack $enswin.li$num.e0 -side left -padx 10
    pack $enswin.li$num.e1 $enswin.li$num.bu -side left
    if {$type == "scandirs"} { pack $enswin.li$num.e2 -side left -padx 10 }
    pack $enswin.li$num.e3 -side left
  }
  if {$action == "delete" && "$scandirlinelist" != ""} {
    set lastnum [format "%02d" [expr [llength $scandirlinelist] - 1]]
    destroy [lindex $scandirlinelist end]
    unset mkdscandirnames($lastnum) mkdrawscanfiles($lastnum)
    unset mkdstripinitTRs($lastnum) mkdnewscannames($lastnum)
  }
}

### make mkscandir panel (only add- proc that makes stuff in base notebk pane)
proc addmkdirs { nbwin type } {
  global env session name
  global bgcol selcol ffontb tfont
  global sessionscanlists functscanlists makingsetupscan
 
  set f $nbwin.pane.p2  
  if {[info command $f.bus] != ""} { return }
  if {$type == "origdirs" && $name == "__nobody__"} {
    confirmalert " Can't make origdirs in subject:\n\n    __nobody__\n\n\
                   Close panel and select newly-made (empty) subject"
    return
  }
  if {$type == "scandirs" && $session == "__nosession__"} {
    confirmalert "Can't make scandirs in session:\n\n    __nosession__\
              \n\nFirst make new functional\
                \nscan session with:\
              \n\n    File -> New Functional\
              \n\nselect that new session,\
                \nand try again"
    if [winfo exists .setuppopup] {
      after 250 { .setuppopup.bo subwidget cancel invoke }
    }
    return
  }

  if {$type == "origdirs"} { 
    set msg "First, SETUP NEW ORIGDIR(s), FIND raw scans => MAKE ORIGDIRS\n\
             Second, COPY-RAW"
    set makebu "SETUP NEW ORIGDIR"
    set deletebu "DELETE LAST ORIGDIR"
  } elseif {$type == "scandirs"} {
    set makebu "SETUP NEW SCANDIR"
    set deletebu "DELETE LAST SCANDIR"
    set msg \
  "First, SETUP NEW SCANDIR(s), enter names, FIND raw scans => MAKE SCANDIRS\n\
   Second, confirm TRs-to-remove and new scan name defaults => STRIP/COPY-RAW"
  } else { return }
  
  label $f.la -bg $bgcol -font $tfont -text $msg
  pack $f.la -pady 7

  frame $f.bus -bg $bgcol -height 195
  pack $f.bus -side top -padx 25

  button $f.bus.bu1 -text $makebu -font $ffontb -pady 2 -padx 11 \
    -command "scandirwline add $f.ens $type" -highlightbackground $bgcol
  button $f.bus.bu2 -text $deletebu -font $ffontb -pady 2 -padx 11 \
    -command "scandirwline delete $f.ens $type" -highlightbackground $bgcol
  pack $f.bus.bu1 $f.bus.bu2 -side left -pady 5

  frame $f.tis -bg $bgcol
  pack $f.tis -side top
  if {$type == "origdirs"} {  ;# omit rmTRs column
    label $f.tis.la1 -text "Orig Subdirs" -bg $bgcol -font $tfont
    label $f.tis.la2 -text "Raw Scan Names" -bg $bgcol -font $tfont
    label $f.tis.la4 -text "New Scan Names" -bg $bgcol -font $tfont
    pack $f.tis.la1 -side left -padx 16
    pack $f.tis.la2 -side left -padx 76
    pack $f.tis.la4 -side left -padx 36
  }
  if {$type == "scandirs"} {
    label $f.tis.la1 -text "Scan Dirs" -bg $bgcol -font $tfont
    label $f.tis.la2 -text "Raw Scan Names" -bg $bgcol -font $tfont
    label $f.tis.la3 -text "rmTRs"   -bg $bgcol -font $tfont
    label $f.tis.la4 -text "New Scan Names" -bg $bgcol -font $tfont
    pack $f.tis.la1 -side left -padx 18
    pack $f.tis.la2 -side left -padx 78
    pack $f.tis.la3 -side left -padx 15
    pack $f.tis.la4 -side left -padx 22
  }

  frame $f.ens -bg $bgcol
  pack $f.ens -side top

  # make a few lines of entries without asking
  tkwait visibility $f
  $f.bus.bu1 invoke
  $f.bus.bu1 invoke
  update idletasks
}

### if regdat there, read it to set initroundflag, else default for new INIT
proc setinitroundflag { page type } {
  global env session iscandir functscanlists alignscanparms

  set iscandir $page
  set initroundflag $functscanlists(def,initroundflag)
  set sdir $env(FUNCTIONALS_DIR)/$session/$iscandir
  if {$type == "alignscan"}   { set regdat $sdir/$alignscanparms(regdat) }
  if {$type == "functscan"}   { set regdat $sdir/$functscanlists($page,regdat)}
  if [file exists $regdat] {
    set initroundflag 0
    set id [open $regdat r]
    foreach line [split [read $id] "\n"] {
      if {$line == "round"} { set initroundflag 1 }
    }
    close $id
  }
  if {$initroundflag} {
    if {$type == "alignscan"}   { set alignscanparms(initroundflag) 1 }
    if {$type == "functscan"}   { set functscanlists($page,initroundflag) 1 }
  } else {
    if {$type == "alignscan"}   { set alignscanparms(initroundflag) 0 }
    if {$type == "functscan"}   { set functscanlists($page,initroundflag) 0 }
  }
}

### Align Scan Dir button command--make one notebook page of widgets
proc addalignscan { nbwin warnflag } {
  global session env iscandir
  global bgcol selcol selbgcol ffontb ffont tfont
  global imagescombo
  global sessionscanlists alignscanparms
  global align2subjbu

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page

  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "sphavgscan" } {
    confirmalert "this is a Cross Session Spherical Avg:\n\nuse CrossSessTools"
    return
  }
  if ![info exists sessionscanlists($page,type)] { set warnflag 0 }
  set sessionscanlists($page,type) alignscan

  if { [info commands $f.la] != "" } { destroy $f.la } ;# fnct->align
  tixLabelFrame $f.la \
    -label "Same-Plane Structural Scan (ALIGN scan)" -labelside acrosstop \
    -background $bgcol -padx 10 -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol  ;# internal ugh
  $f.la.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  $f.la subwidget label config -bd 1 -bg gray -relief sunken -pady 2
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  set imagescombo($page) $f.cbx
  tixComboBox $f.cbx -label "Image File:" -dropdown true \
    -command cbx:select_alignimage -editable true \
    -variable alignscanparms(modelimage) -listwidth 315 \
    -options "label.width 10 label.anchor e
              entry.width 20
              listbox.height 10" ;# listbox.width 10 -> 40
  fiximages $page alignscan

  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  set selectedimage $fullscandir/\$alignscanparms(modelimage)  ;# wait subst
  button $f.cbx.bu -text "READ HEADER" -font $ffontb -pady 1 -padx 5 \
    -command "readheader $selectedimage $page alignscan" \
    -highlightbackground $bgcol
  $f.cbx config -background $bgcol
  setinitroundflag $page alignscan  ;# read reg (override saved) 10% addscan

  #TODO: can only save 1 align imagepatt per var/sess
  tixLabelEntry $f.a -label "Image Name Format: " -labelside left \
    -options "entry.textVariable alignscanparms(imagepatt)"
  tixLabelEntry $f.a2 -label "Scan Type: " -labelside left \
    -options "entry.textVariable alignscanparms(imtype)"
  tixLabelEntry $f.b -label "Slice Count: " -labelside left \
    -options "entry.textVariable alignscanparms(slices)"
  tixLabelEntry $f.c -label "Image X Size: " -labelside left \
    -options "entry.textVariable alignscanparms(xres)"
  tixLabelEntry $f.d -label "Image Y Size: " -labelside left \
    -options "entry.textVariable alignscanparms(yres)"
  tixLabelEntry $f.e -label "In Plane Pixel (mm): " -labelside left \
    -options "entry.textVariable alignscanparms(inplane)"
  tixLabelEntry $f.f -label "Slice Thickness (mm): " -labelside left \
    -options "entry.textVariable alignscanparms(thickness)"
  tixLabelEntry $f.g -label "Brightness (frac): " -labelside left \
    -options "entry.textVariable alignscanparms(brightness)"
  if ![info exists alignscanparms(regdat)] {
    set alignscanparms(regdat) register.dat
  }
  frame $f.h -bg $bgcol
  tixLabelEntry $f.h.le -label "Funct->Struct: " \
    -labelside left -options "entry.textVariable alignscanparms(regdat)"
  $f.h.le subwidget label config -width 13
  $f.h.le subwidget entry config -width 13
  button $f.h.bu -text "INIT" -font $ffontb -command "writedefregdat $page" \
    -highlightbackground $bgcol -pady 1 -padx 2
  button $f.h.bu1 -text "INIT/FLIP" -font $ffontb \
    -command "writedefregdat $page standardflip" \
    -highlightbackground $bgcol -pady 1 -padx 2
  checkbutton $f.h.ck -font $ffont \
    -text "init round" -selectcolor $selcol -bg $bgcol \
    -variable alignscanparms(initroundflag) \
    -highlightbackground $bgcol

  frame $f.i -bg $bgcol
  label $f.i.la -text "Register:  " -bg $bgcol -font $tfont

  tixLabelEntry $f.h2 -label "SubjectsDir Target ImageSet: " -labelside left \
    -options "entry.textVariable alignscanparms(tkregtargdir)"

  button $f.i.bu1 -text "COPY ALIGN TO ALL FUNCTS" -font $ffontb -command \
    "cpregcmd $page cpalign2all" -highlightbackground $bgcol -pady 1 -padx 6
  set align2subjbu($page) $f.i.bu2
  button $f.i.bu2 -text "ALIGN=>SUBJ" -font $ffontb -command \
    "regfunctcmd $page align2subj" -highlightbackground $bgcol -pady 1 -padx 6

  tixLabelEntry $f.j -label "Block Center Offset (mm): " -labelside left \
    -options "entry.textVariable alignscanparms(blockcenteroffset)"

  $f.b subwidget label config -width 27   ;# why?
  $f.d subwidget label config -width 27   ;# why?
  $f.f subwidget label config -width 27   ;# why?

  pack $f.cbx $f.a $f.a2 $f.b $f.c $f.d $f.e $f.f $f.g $f.h $f.h2 $f.i $f.j \
    -side top -padx 10 -pady 2
  pack $f.cbx.bu -padx 10 -pady 2  ;# was -pady 0 w/CONVERT=>COR
  pack $f.h.le -side left
  pack $f.h.bu $f.h.bu1 -side left
  pack $f.h.ck -side left -padx 0
  pack $f.i.la $f.i.bu1 $f.i.bu2 -side left
  if {$warnflag} {
    confirmalert "Directory:    $page\n\n(re)configured as Alignment Scan"
  }
  update idletasks
}

### Funct Scan Dir button command--make one notebook page of widgets
proc addfunctscan { nbwin warnflag } {
  global session env iscandir
  global ffont ffontb tfont hfont
  global bgcol selbgcol hilbgcol hilcol actbgcol selcol
  global imagescombo alignscombo vregtargscombo
  global currpage prevpage
  global sessionscanlists functscanlists initround
  global funct2subjbu vregall2selbu vregcurr2selbu
  global makingfunctscan

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page

  ## if (already) sphavg: ask change to funct (single), else bail
  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "sphavgscan" } {
    #confirmalert "this is a Cross Session Spherical Avg:\n\nuse CrossSessTools"
    #return
    #TODO: test -- below added Feb 2012: test OK to reconfig sphavg -> singlsub
    if ![okreplace "" \
         " This is a Cross Sess Spherical Avg:\n\nReconfig as Single Subject? \
           N.B.: this will destroy cross-subj avg panel configs" \
         "Reconfig"] {
      confirmalert "Cross Sess Scandir not altered"
      return
    } else { set sessionscanlists($page,type) functscan }
  }

  ## if firstopen (or extstat scan) set flag to firstload aligns,vregs
  set findalignsflag 0  ;# only needed for newly config'd pages (else:raisecmd)
  set findvregtargsflag 0
  if { ![info exists sessionscanlists($page,type)] || \
       $sessionscanlists($page,type) != "functscan"} {
         set findalignsflag 1
         set findvregtargsflag 1
  }

  ## if (already) extstatscan set extstatfunctims, else set functscan
  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "extstatscan"} {
    if {!$functscanlists($page,extstatfunctims)} {
      confirmalert "Funct Scan: config raw functimages for extern stats\
                \n\n    N.B.: For register only\
                \n\nTo calculate intern stats instead:\
                \n\n    Import 3D Stats -> Unset Dir\
                  \n    Setup Align/Funct Scans -> Funct Scan Dir"
      set functscanlists($page,extstatfunctims) 1
    }
    # don't allow reset extstatscan to functscan here
  } else {  ;# not extstatscan (or sphavgscan), always reset to functscan
    if ![info exists sessionscanlists($page,type)] { set warnflag 0 }
    set sessionscanlists($page,type) functscan
  }

  set makingfunctscan 1

  # start new page
  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la -label "Functional Scan Directory" -labelside acrosstop \
    -bg $bgcol -padx 10 -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2   ;# newpkgtix internal ugh
  $f.la subwidget label config -bd 1 -bg gray -relief sunken -pady 2
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  # backward compat: update if defunct parm read from csurf.dat
  if { [info exists functscanlists($page,alignfunctcentoffset)] && \
      ![info exists functscanlists($page,blockcenteroffset)] } {
    set functscanlists($page,blockcenteroffset) \
            [expr -$functscanlists($page,alignfunctcentoffset)]
    unset functscanlists($page,alignfunctcentoffset)
  }
  # backward fix: old addsigavgscan wasn't setting brightness
  if { [info exists functscanlists($page,brightness)] && \
       $functscanlists($page,brightness) == ""} {
    set functscanlists($page,brightness) $functscanlists(def,brightness)
  }
  # create/copy from defs any non-readheader parms that don't exist
  foreach parm { regdat tkregtargdir blockcenteroffset initroundflag \
                 vregtargTR vreg2passflag \
                 paintdmin paintdmax paintdstep paintnormop paintnormtype \
                 clonesuff sliceorder brightness allverticesflag \
                 normdsampsearchflag samevtxthickflag normdsampuniqvoxflag \
                 normdsampuniqvtxflag normdsampallflag paintext } {
    if ![info exists functscanlists($page,$parm)] {  ;#def
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }
  if ![info exists functscanlists($page,aligndir)] { ;# propagate aligndir
    if [info exists functscanlists($prevpage,aligndir)] {
      set functscanlists($page,aligndir) $functscanlists($prevpage,aligndir)
    }
  }
  setinitroundflag $page functscan  ;# read reg (override saved) 10% addscan

  set imagescombo($page) $f.cbx
  tixComboBox $f.cbx -label "Image File:" -dropdown true \
    -command "cbx:select_functimage $page" -editable true \
    -variable functscanlists($page,modelimage) -listwidth 315 \
    -options "label.width 9 label.anchor e
              entry.width 24
              listbox.height 10" ;# listbox.width 40

  fiximages $page functscan

  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  set selectedimage $fullscandir/\$functscanlists($page,modelimage) ;# wait2sub
  button $f.cbx.bu -text "READ HEADER" -font $ffontb -pady 2 -padx 2 \
    -command "readheader $selectedimage $page functscan" \
    -highlightbackground $bgcol
  pack $f.cbx.bu
  $f.cbx config -background $bgcol

  # next caused surfdiff condname combos yoking after addfunctscan (tix bug)
  #tixLabelEntry $f.a -label "Image Name Format: " -labelside left \
  #  -options "entry.textVariable functscanlists($page,imagepatt)"
#xxx -- fixed imagepatt corrupt? (avoid -option, bak->a, unoverlap others)
  tixLabelEntry $f.a -label "Image Name Format: " -labelside left
  $f.a subwidget entry config -textvariable functscanlists($page,imagepatt)
  # next causes rawavg "Select to Add" entry to display slice cnt (tix bug)
  #tixLabelEntry $f.b -label "Slice Count: " -labelside left \
  #  -options "entry.textVariable functscanlists($page,slices)"
  tixLabelEntry $f.b -label "Slice Count: " -labelside left
  $f.b subwidget entry config -textvariable functscanlists($page,slices)
  tixLabelEntry $f.c -label "Image X Size: " -labelside left \
    -options "entry.textVariable functscanlists($page,xres)"
  # next causes addrand condname ($f.d.*) combos yoking after addfunctscan (tx)
  #tixLabelEntry $f.d -label "Image Y Size: " -labelside left \
  #  -options "entry.textVariable functscanlists($page,yres)"
  tixLabelEntry $f.d -label "Image Y Size: " -labelside left
  $f.d subwidget entry config -textvariable functscanlists($page,yres)
  tixLabelEntry $f.e -label "Images Per Slice: " -labelside left -options \
    "entry.textVariable functscanlists($page,reps)
     entry.highlightBackground $bgcol"
  tixLabelEntry $f.f -label "In Plane Pixel (mm): " -labelside left \
    -options "entry.textVariable functscanlists($page,inplane)"
  tixLabelEntry $f.g -label "Slice Thickness (mm): " -labelside left \
    -options "entry.textVariable functscanlists($page,thickness)"
  tixLabelEntry $f.h -label "Brightness (frac): " -labelside left \
    -options "entry.textVariable functscanlists($page,brightness)"
  #use alternate syntax just in case
  tixLabelEntry $f.h2 -label "Multiband Accel Factor: " -labelside left
  $f.h2 subwidget entry config -textvariable functscanlists($page,mbaccel)
  tixLabelEntry $f.h3 -label "Slice Time Offsets List (sec): " -labelside left
  $f.h3 subwidget entry config -textvariable functscanlists($page,taxisoffsets)
  tixSelect $f.h4 -allowzero true -radio true -label "Slice Ord:" \
    -orientation horizontal -options "label.width 8"
  foreach but "simul odev evod odevr evodr asc desc" {
    $f.h4 add $but -text $but -font $hfont -width 2 -bg $bgcol -pady 1 -padx 11
  }
  $f.h4 config -variable functscanlists($page,sliceorder)

  ### Volreg
  frame $f.i -bg $bgcol
  label $f.i.la -text "Volreg: " -bg $bgcol -font $tfont
  set vregall2selbu($page) $f.i.bu1   ;# save in array
  button $f.i.bu1 -text "ALL=>T" -font $ffontb -highlightbackground $bgcol \
    -command "3dvolregcmd $page vregall2sel" -pady 1 -padx 3
  set vregcurr2selbu($page) $f.i.bu2   ;# save in array
  button $f.i.bu2 -text "CURR=>T" -font $ffontb -highlightbackground $bgcol \
    -command "3dvolregcmd $page vregcurr2sel" -pady 1 -padx 3
  set vregtargscombo($page) $f.i.cbx2   ;# save in array
  tixComboBox $f.i.cbx2 -label "Targ:" -dropdown true \
    -command cbx:select_vregtarg -editable false \
    -variable functscanlists($page,vregtargdir) -listwidth 201 \
    -options "label.width 4 label.anchor e
              entry.width 10
              listbox.height 15" ;# listbox.width 23 -> 24
  if {$findvregtargsflag} { findvregtargs $page }
  #checkbutton $f.i.ck1 -text "Two Pass: Smooth/Fine" -selectcolor $selcol \
  #  -bg $bgcol -variable functscanlists($page,vreg2passflag) \
  #  -highlightbackground $bgcol
  tixLabelEntry $f.i.le -label "TR:" -labelside left \
    -options "entry.textVariable functscanlists($page,vregtargTR)"
  $f.i.le subwidget entry config -width 3
  $f.i.le subwidget label config -width 3

  ### register.dat
  frame $f.j -bg $bgcol
  tixLabelEntry $f.j.le -label "Funct->Struct: " -labelside \
    left -options "entry.textVariable functscanlists($page,regdat)"
  $f.j.le subwidget label config -width 13
  $f.j.le subwidget entry config -width 13
  button $f.j.bu -text "INIT" -font $ffontb -command "writedefregdat $page" \
    -highlightbackground $bgcol -pady 1 -padx 2
  button $f.j.bu1 -text "INIT/FLIP" -font $ffontb \
    -command "writedefregdat $page standardflip" \
    -highlightbackground $bgcol -pady 1 -padx 2
  checkbutton $f.j.ck -font $ffont \
    -text "init round" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,initroundflag) \
    -highlightbackground $bgcol

  ### target/underlay image set
  tixLabelEntry $f.j2 -label "SubjectsDir Target ImageSet: " -labelside left \
    -options "entry.textVariable functscanlists($page,tkregtargdir)"

  ### copy register.dat
  frame $f.k -bg $bgcol
  label $f.k.la -text "Register: " -bg $bgcol -font $tfont
  button $f.k.bu0 -text "CP TO OTHERS" -font $ffontb -pady 1 -padx 6 \
    -highlightbackground $bgcol -command "cpregcmd $page cpcurr2all"
  button $f.k.bu1 -text "CP PREV" -font $ffontb -pady 1 -padx 6 \
    -highlightbackground $bgcol -command "cpregcmd $page cpfromprev"
  frame $f.k.sp1 -width 4 -bg $bgcol
  set funct2subjbu($page) $f.k.bu2   ;# save in array
  button $f.k.bu2 -text "FUNCT=>SUBJ" -font $ffontb -pady 1 -padx 6 \
    -highlightbackground $bgcol -command "regfunctcmd $page funct2subj"

  ### Same-Plane
  frame $f.l -bg $bgcol
  set alignscombo($page) $f.l.cbx3   ;# save in array
  tixComboBox $f.l.cbx3 -label "SamePlane AlignDir:" -dropdown true\
    -command cbx:select_alignimage -editable false \
    -variable functscanlists($page,aligndir) -listwidth 201 \
    -options "label.width 19 label.anchor e
              entry.width 14
              listbox.height 10" ;# listbox.width 10 -> 24
  if {$findalignsflag} { findaligns $page }
  tixLabelEntry $f.l.e -label "BlkCentOff:" -labelside left \
    -options "entry.textVariable functscanlists($page,blockcenteroffset)"
  $f.l.e subwidget entry config -width 3
  $f.l.e subwidget label config -width 11

  ### visually separate later-used Paint parms
  frame $f.l2 -bg $bgcol -height 4
  frame $f.l3 -bg $bgcol
  label $f.l3.la \
    -text "Sample-to-Surface (PAINT) and Extract Timecourses Options" \
    -bg $bgcol -font $tfont

  ### NormSearch line 1
  frame $f.m -bg $bgcol
  label $f.m.la1 -text "NormSearch:" -bg $bgcol -font $tfont  ;# -width 12
  tixSelect $f.m.s0 -allowzero false -radio true -orientation horizontal \
    -command "select_paintnormtype $page" ;# appends butt,state
  foreach but "mm frac" {
    $f.m.s0 add $but -text $but -font $hfont \
      -width 0 -bg $bgcol -padx 0 -pady 0 \
      -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  }
  $f.m.s0 config -variable functscanlists($page,paintnormtype)
  $f.m.s0 subwidget label config -bd 0 -padx 0 
  tixLabelEntry $f.m.le0 -label "mn/mx: " -labelside left \
    -options "entry.textVariable functscanlists($page,paintdmin)"
  tixLabelEntry $f.m.le1 -label "" -labelside left \
    -options "entry.textVariable functscanlists($page,paintdmax)"
  $f.m.le0 subwidget entry config -width 3
  $f.m.le0 subwidget label config -width 8 -padx 0
  $f.m.le1 subwidget entry config -width 3
  $f.m.le1 subwidget label config -width 0 -padx 0
  tixLabelEntry $f.m.le2 -label "dx:" -labelside left \
    -options "entry.textVariable functscanlists($page,paintdstep)"
  $f.m.le2 subwidget entry config -width 4
  $f.m.le2 subwidget label config -width 3 -padx 0
  tixSelect $f.m.s1 -allowzero false -radio true -orientation horizontal
  foreach but "max avg min" {
    if {$but == "max"} { set btext mx }
    if {$but == "avg"} { set btext av }
    if {$but == "min"} { set btext mn }
    $f.m.s1 add $but -text $btext -font $hfont \
       -width 2 -bg $bgcol -padx 0 -pady 0 \
       -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  }
  $f.m.s1 config -variable functscanlists($page,paintnormop) \
    -command "select_paintnormop $page" ;# appends butt,state

  ### NormSearch line 2
  frame $f.n -bg $bgcol
  checkbutton $f.n.ck2 -font $tfont \
    -text "NormSrch" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,normdsampsearchflag) \
    -highlightbackground $bgcol
  checkbutton $f.n.ck3 -font $tfont \
    -text "Same" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,samevtxthickflag) \
    -highlightbackground $bgcol
  checkbutton $f.n.ck4 -font $tfont \
    -text "UniqVox" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,normdsampuniqvoxflag) \
    -highlightbackground $bgcol
  checkbutton $f.n.ck5 -font $tfont \
    -text "UniqVtx" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,normdsampuniqvtxflag) \
    -highlightbackground $bgcol
  checkbutton $f.n.ck6 -font $tfont \
    -text "Alldx" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,normdsampallflag) \
    -highlightbackground $bgcol
  checkbutton $f.n.ck -font $tfont \
    -text "AllVtxs" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,allverticesflag) -highlightbackground $bgcol

  ### Clone
  frame $f.n2 -bg $bgcol -height 10
  frame $f.o -bg $bgcol
  tixLabelEntry $f.o.le -label "Cloned Dir Suffix (alt render):" -labelside \
    left -options "entry.textVariable functscanlists($page,clonesuff)"
  $f.o.le subwidget entry config -width 10
  button $f.o.bu -text "CLONE FUNCT" -font $ffontb -pady 2 -padx 2 \
    -highlightbackground $bgcol -command "clonefunct $page"

  ### next resets req'd if render panel opened before (rm: b:label,b/d/e:entry)
  $f.c subwidget label config -width 27   ;# why?
  $f.c subwidget entry config -width 14   ;# entry: why?
  $f.d subwidget label config -width 27   ;# why?
  $f.e subwidget label config -width 27   ;# why?
  $f.f subwidget label config -width 27   ;# why?
  $f.g subwidget label config -width 27   ;# why?
  $f.h subwidget label config -width 27   ;# why?

  pack $f.cbx $f.cbx.bu $f.a $f.b $f.c $f.d $f.e $f.f $f.g $f.h $f.h2 $f.h3 \
    $f.h4 $f.i $f.j $f.j2 $f.k $f.l $f.l2 $f.l3 -side top -padx 10 -pady 2
  pack $f.i.la $f.i.bu1 $f.i.bu2 $f.i.cbx2 $f.i.le -side left
  pack $f.j.le -side left
  pack $f.j.bu $f.j.bu1 -side left
  pack $f.j.ck -side left -padx 0
  pack $f.k.la $f.k.bu0 $f.k.bu1 $f.k.sp1 $f.k.bu2 -side left
  pack $f.l.cbx3 $f.l.e -side left
  pack $f.l3.la -side left
  pack $f.m -side top -padx 10 -pady 2
  pack $f.m.la1 $f.m.s0 $f.m.le0 $f.m.le1 $f.m.le2 $f.m.s1 -side left
  pack $f.n $f.n2 -side top
  pack $f.n.ck2 $f.n.ck3 $f.n.ck4 $f.n.ck5 $f.n.ck6 $f.n.ck -side left -padx 0
  pack $f.o -side top
  pack $f.o.le $f.o.bu -side left

  set prevpage $currpage
  set currpage $page

  if {$warnflag && $sessionscanlists($page,type) == "functscan"} {
    confirmalert "Directory:    $page\n\n(re)configured as Functional Scan"
  }
  set makingfunctscan 0
  update idletasks
}

### on change paint norm type
proc select_paintnormtype { page type selected } {
  global env name hemi functscanlists makingfunctscan makingextstatscan
  if {$selected} {
    if {$type == "frac"} {
      if {$hemi == "both"} {
        set thkfile $env(SUBJECTS_DIR)/$name/surf/rh.thickness
      } else {
        set thkfile $env(SUBJECTS_DIR)/$name/surf/$hemi.thickness
      }
      if ![file exists $thkfile] {
        confirmalert \
            " Paint Norm Type: cortical thickness file:\n\n\  $thkfile\n\n\
              required for vertex normal type \"frac\" is missing.\n\n\
              Create thickness file or use type \"mm\""
        set functscanlists($page,paintnormtype) mm
      } else {
        if {!$makingfunctscan && !$makingextstatscan} {
          set functscanlists($page,paintdmin) 0.0
          set functscanlists($page,paintdmax) 0.8   ;# avg thick ~2.5mm
          set functscanlists($page,paintdstep) 0.10
          set functscanlists($page,normdsampsearchflag) 1
        }
      }
    }
    if {$type == "mm"} {
      if {!$makingfunctscan && !$makingextstatscan} {
        set functscanlists($page,paintdmin) 0.0
        set functscanlists($page,paintdmax) 2.0
        set functscanlists($page,paintdstep) 0.25
        set functscanlists($page,normdsampsearchflag) 1
      }
    }
  }
}

### on change paint norm operation
proc select_paintnormop { page operation selected } {
}

### CLONE FUNCT button command (Align/Funct panels)
proc clonefunct { page } {
  global env session functscanlists datfile

  set fullscandir $env(FUNCTIONALS_DIR)/$session/$page
  set fullclonedir $fullscandir-$functscanlists($page,clonesuff) ;# insert dash 
  if [file exists $fullclonedir] {
    confirmalert "Clone Funct Dir: $fullclonedir exists\n\nuse new suffix"
    return
  }
  cdlog $fullscandir
  set filelist [glob -nocomplain *.bfloat *.hdr *.BRIK *.HEAD register.dat]
  if ![llength $filelist] {
    confirmalert "Clone Funct Dir: no bfloat/BRIK/register.dat files in $page"
    cdfunctscripts
    return
  }

  mkdirlog $fullclonedir
  cdlog $fullscandir
  ## N.B.: originally just make links to big files
  #foreach file [glob *.bfloat *.hdr *.BRIK *.HEAD register.dat] {
  #  cdlog $fullclonedir
  #  if ![file exists $file] {eval exec ln -s ../[file tail $page]/$file $file}
  #}
  ## just copy everything
  foreach file [glob *] { cplog $file $fullclonedir }
  cdfunctscripts

  set mpage [manglepath $page]
  set mpageclone [manglepath [file dirname $page]/[file tail $fullclonedir]]
  foreach index [array names sessionscanlists] {
    if [string match $mpage,* $index] {
      set val $sessionscanlists($index)
      set parm [string range $index [string length $mpage] end] ;# incl comma
      set indexclone ${mpageclone}${parm}
      set sessionscanlists($indexclone) $val
    }
  }
  foreach index [array names functscanlists] {
    if [string match $mpage,* $index] {
      set val $functscanlists($index)
      set parm [string range $index [string length $mpage] end] ;# incl comma
      set indexclone ${mpageclone}${parm}
      set functscanlists($indexclone) $val
    }
  }
  foreach index [array names renderscanlists] {
    if [string match $mpage,* $index] {
      set val $renderscanlists($index)
      set parm [string range $index [string length $mpage] end] ;# incl comma
      set indexclone ${mpageclone}${parm}
      set renderscanlists($indexclone) $val
    }
  }
  writearrayparms $datfile alignfunct

  set panel .setuppopup
  set nbwin $panel.to.no
  if [winfo exists $panel] { destroy $panel }
  setupscans alignfunct
  $nbwin raise [manglepath [file dirname $page]/[file tail $fullclonedir]]
  addfunctscan $nbwin 0
}

### READ HEADER button cmd (Align/Funct panels) -- only BRIK/brik/bshort/bfloat
proc readheader { fullimage page scantype } {
  global structscanlists alignscanparms functscanlists bindir

  set suff [file extension $fullimage]
  set imtail [file tail $fullimage]
  set stem [file rootname $fullimage]

  set imagepatt -unset-
  set imtype    unknown  ;# align:exposed, funct:hidden
  set slices    -unset-
  set reps      -unset-
  set xres      -unset-
  set yres      -unset-
  set inplane   -unset-
  set thickness -unset-
  if {$scantype == "alignscan"} {set brightness 1.0} else {set brightness 0.1}
  if {$scantype == "functscan"} {
    set tr              ""
    set mbaccel         ""
    set taxisoffsets    ""
  }

  if {$suff == ".BRIK"} {         ;# read HEAD
    set header [file rootname $fullimage].HEAD
    set imagepatt $imtail
    set imtype brik
    set slices [getafnislices $header]
    set reps [getafnireps $header]
    set xres [getafnixres $header]
    set yres [getafniyres $header]
    set inplane [getafniinplane $header]
    set thickness [getafnithickness $header]
    if {$scantype == "functscan"} {
      set tr [getafnitr $header]
      set mbaccel [getafnimbaccel $header]
      set taxisoffsets [getafnitaxisoffsets $header]
    }
  } elseif {$suff == ".mgh" || $suff == ".mgz"} {
    set savecwd [pwd]
    cdlog [file dirname $fullimage]
    set command "$bindir/tkmedit [file tail $fullimage] -header"
    if { ![catch { eval exec $command } ret ] } {
      set imagepatt $imtail
      set imtype mgh
      set lines [split $ret "\n"]
      set inplane
      foreach line $lines {
       if [string match "tkmedit: width =*" $line] {set xres [lindex $line 3]}
       if [string match "tkmedit: height =*" $line] {set yres [lindex $line 3]}
       if [string match "tkmedit: depth =*" $line] {set slices [lindex $line 3]}
       if [string match "tkmedit: nframes =*" $line] {set reps [lindex $line 3]}
       # N.B.: mgz default pixel size is 0.0 x 0.0 x 0.0 (!)
       if [string match "tkmedit: spacingX =*" $line] {
         set inplane [lindex $line 3]
         if {$inplane == 0.0} { set inplane 1.0 }
       }
       if [string match "tkmedit: spacingY =*" $line] {
         set inplane2 [lindex $line 3]
         if {$inplane2 == 0.0} { set inplane2 1.0 }
       }
       if [string match "tkmedit: spacingZ =*" $line] {
         set thickness [lindex $line 3]
         if {$thickness == 0.0} { set thickness 1.0 }
       }
       if [string match "tkmedit: type = 0" $line] {set datatype byte }
       if [string match "tkmedit: type = 3" $line] {set datatype float }
      }
      if {$inplane != $inplane2} {
        confirmalert "Read Header: N.B.: in-plane are voxels non-square"
      }
      set brightness 1.0
      cdlog $savecwd
    } else {
      confirmalert "tkmedit failed to read header of:\n\n   $fullimage"
      cdlog $savecwd
      return
    }
  } elseif {$suff == ".brik"} {   ;# unset: slices,reps,xres/yres,inplane,thk
    set imagepatt $imtail
    set imtype brik
  } elseif {$suff == ".bshort"} { ;# unset: xres/yres,inplane,thickness
    set imtype bshort
    set imagepatt [stripbnum $imtail]_%03d.bshort
    set slices [llength [glob -nocomplain [stripbnum $fullimage]_???.bshort]]
    set header [file rootname $fullimage].hdr
    if [file exists $header] {
      set id [open $header r]
      set lines [split [read $id] "\n"]
      close $id
      set firstline [lindex $lines 0]
        if { [llength $firstline] == 4 } {
        set xres [lindex $firstline 0]
        set yres [lindex $firstline 1]
        set reps [lindex $firstline 2]
      }
    }
  } elseif {$suff == ".bfloat"} { ;# unset: xres/yres,inplane,thickness
    set imtype bfloat
    set imagepatt [stripbnum $imtail]_%03d.bfloat
    set slices [llength [glob -nocomplain [stripbnum $fullimage]_???.bfloat]]
    set header [file rootname $fullimage].hdr
    if [file exists $header] {
      set id [open $header r]
      set lines [split [read $id] "\n"]
      close $id
      set firstline [lindex $lines 0]
        if { [llength $firstline] == 4 } {
        set xres [lindex $firstline 0]
        set yres [lindex $firstline 1]
        set reps [lindex $firstline 2]
      }
    }
  } else {
    confirmalert "suffix $suff not recognized:\n\n  ...enter parms manually"
  }

  # create or re-set csurf.dat parms
  if {$scantype == "structscan"} {
    set structscanlists($page,imagepatt)  $imagepatt
    set structscanlists($page,imtype)     $imtype
    set structscanlists($page,slices)     $slices
    set structscanlists($page,reps)       $reps
    set structscanlists($page,xres)       $xres
    set structscanlists($page,yres)       $yres
    set structscanlists($page,inplane)    $inplane
    set structscanlists($page,thickness)  $thickness
  }
  if {$scantype == "alignscan"} {
    set alignscanparms(imagepatt)  $imagepatt
    set alignscanparms(imtype)     $imtype
    set alignscanparms(slices)     $slices
    set alignscanparms(reps)       $reps
    set alignscanparms(xres)       $xres
    set alignscanparms(yres)       $yres
    set alignscanparms(inplane)    $inplane
    set alignscanparms(thickness)  $thickness
    set alignscanparms(brightness) $brightness
  }
  if {$scantype == "functscan"} {
    set functscanlists($page,imagepatt)  $imagepatt
    set functscanlists($page,imtype)     $imtype
    set functscanlists($page,slices)     $slices
    set functscanlists($page,reps)       $reps
    set functscanlists($page,xres)       $xres
    set functscanlists($page,yres)       $yres
    set functscanlists($page,inplane)    $inplane
    set functscanlists($page,thickness)  $thickness
    set functscanlists($page,brightness) $brightness
    set functscanlists($page,TR)         $tr
    set functscanlists($page,mbaccel)    $mbaccel
    # don't biff already-read taxisoffset w/empty (3dvolreg doesn't propagate)
    if { [info exists functscanlists($page,taxisoffsets)] &&
         $functscanlists($page,taxisoffsets) != "" &&
         "$taxisoffsets" == "" } {
      if [okreplace "" "Replace previously read TAXIS_OFFSETS:\
                    \n\n$functscanlists($page,taxisoffsets)\
                    \n\nwith empty string? (N.B.: 3dvolreg doesn't\
                      \npropagate TAXIS_OFFSETS to new vreg HEAD)"\
             "Don't Replace TAXIS_OFFSETS" none "Replace" ] {
          ;  ;# this is right-most button (default) action: *don't* replace
        } else {
          set functscanlists($page,taxisoffsets) $taxisoffsets  ;# non-default
        }
      } else {  ;# new is non-empty, existing empty or doesn't yet exist
        set functscanlists($page,taxisoffsets) $taxisoffsets
      }

    # next only set parms w/o turn on slicetime corr
    fixinterleaved2siemens $page

    # set ahead the 3dvolreg target
    if [info exists functscanlists($page,vregtargTR)] {
      if { [info exists functscanlists($page,reps)] && \
           $functscanlists($page,reps) != "-unset-" && \
           $functscanlists($page,reps) != "" } {
        set functscanlists($page,vregtargTR) \
            [expr $functscanlists($page,reps)/2]
      }
    }
  }
}

proc fixinterleaved2siemens { page } {
  global functscanlists

  # TODO: fix for Siemens *and* CMRR multiband!
  # assume Siemens: even=>2,4,6... 1,3,5...; odd=>1,3,5... 2,4,6...
  if { [info exists functscanlists($page,sliceorder)] && \
       [info exists functscanlists($page,slices)] } {
    if { $functscanlists($page,slices) == "-unset-" } { return }
    set oddslicesflag [expr $functscanlists($page,slices)%2]
    if { $functscanlists($page,sliceorder) == "odev" && !$oddslicesflag } {
      set functscanlists($page,sliceorder) evod
    }
    if { $functscanlists($page,sliceorder) == "evod" && $oddslicesflag } {
      set functscanlists($page,sliceorder) odev
    }
  }
}

### use tkmedit to read mgz header field (like readheader)
proc getmgzslices { fullmgzfile } {
  global bindir

  set slices -1
  set savecwd [pwd]
  cdlog [file dirname $fullmgzfile]
  set command "$bindir/tkmedit [file tail $fullmgzfile] -header"
  if { ![catch { eval exec $command } ret ] } {
    set lines [split $ret "\n"]
    foreach line $lines {
      if [string match "tkmedit: depth =*" $line] {set slices [lindex $line 3]}
    }
    cdlog $savecwd
    if {$slices != -1} { return $slices } else { return 0 }
  } else {
    confirmalert "tkmedit failed to read header of:\n\n   $mgzfile"
    cdlog $savecwd
    return 0
  }
}

### read HEAD, find slice count (3rd arg DATASET_DIMENSIONS)
proc getafnislices { header } {
  set slices -1
  if ![file exists $header] { return $slices }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  foreach line $lines {
    if [string match *DATASET_DIMENSIONS* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set slices [lindex $line 2]
      set i 0
    }
  }
  if {$slices == -1} {
    confirmalert \
      "slices (3nd arg DATASET_DIMENSIONS) not found in:\n\n  $header"
  }
  return $slices
}

### read HEAD, find repetitions (2nd arg DATASET_RANK)
proc getafnireps { header } {
  set reps -1
  if ![file exists $header] { return $reps }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  foreach line $lines {
    #if {[lindex $line 2] == "DATASET_RANK"} { }  ;# chokes on new comments
    if [string match *DATASET_RANK* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set reps [lindex $line 1]
      set i 0
    }
  }
  if {$reps == -1} {
    confirmalert "reps (2nd arg DATASET_RANK) not found in:\n\n  $header"
  }
  return $reps
}

### read HEAD, find x resolution (1st arg DATASET_DIMENSIONS)
proc getafnixres { header } {
  set xres -1
  if ![file exists $header] { return $xres }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  foreach line $lines {
    if [string match *DATASET_DIMENSIONS* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set xres [lindex $line 0]
      set i 0
    }
  }
  if {$xres == -1} {
    confirmalert "xres (1st arg DATASET_DIMENSIONS) not found in:\n\n  $header"
  }
  return $xres
}

### read HEAD, find y resolution (2nd arg DATASET_DIMENSIONS)
proc getafniyres { header } {
  set yres -1
  if ![file exists $header] { return $yres }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  foreach line $lines {
    if [string match *DATASET_DIMENSIONS* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set yres [lindex $line 1]
      set i 0
    }
  }
  if {$yres == -1} {
    confirmalert "yres (2nd arg DATASET_DIMENSIONS) not found in:\n\n  $header"
  }
  return $yres
}

### read HEAD, find inplane voxel size (1st arg DELTA, read/ignore 2nd)
proc getafniinplane { header } {
  set inplane 9999
  if ![file exists $header] { return $inplane }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  foreach line $lines {
    if [string match *DELTA* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set inplane  [expr abs([lindex $line 0])]  ;# DELTA args can be neg
      set inplane2 [expr abs([lindex $line 1])]
      set i 0
    }
  }
  if {$inplane == 9999} {
    confirmalert "inplane (1st arg DELTA) not found in:\n\n  $header"
  } else {
    if {$inplane != $inplane2} {
      confirmalert "non-square inplane (1st!=2nd arg DELTA)\n\n...inplane->1st"
    }
  }
  return $inplane
}

### read HEAD, find thickness (3rd arg DELTA)
proc getafnithickness { header } {
  set thickness 9999
  if ![file exists $header] { return $thickness }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  foreach line $lines {
    if [string match *DELTA* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set thickness [expr abs([lindex $line 2])]  ;# DELTA args can be neg
      set i 0
    }
  }
  if {$thickness == 9999} {
    confirmalert "thickness (3nd arg DELTA) not found in:\n\n  $header"
  }
  return $thickness
}

### read HEAD, find BRICK_FLOAT_FACS
proc getafnifloatfac { header index } {
  set floatfac -1 
  if ![file exists $header] { return $floatfac }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  foreach line $lines {
    if [string match *BRICK_FLOAT_FACS* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set floatfac [lindex $line $index]
      set i 0
    }
  }
  if {$floatfac == -1} {
    confirmalert "float factor (BRICK_FLOAT_FACS) not found in:\n\n  $header"
  }
  return $floatfac
}

### read HEAD, find TR (2nd arg TAXIS_FLOATS)
proc getafnitr { header } {
  set tr 9999
  if ![file exists $header] { return $tr }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  foreach line $lines {
    if [string match *TAXIS_FLOATS* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set tr [expr abs([lindex $line 1])]
      set i 0
    }
  }
  if {$tr == 9999} {
    #confirmalert "TR (2nd arg TAXIS_FLOATS) not found in:\n\n    $header\n\n\
    #...assuming 1 volume"
    putlog "TR (2nd arg TAXIS_FLOATS) not found in $header ...assuming 1 volume"
    set tr 1
  }
  return $tr
}

### read HEAD, return list of TAXIS_OFFSETS (N.B.: 3dvolreg doesn't propagate!)
proc getafnitaxisoffsets { header } {
  set taxisoffsets ""
  if ![file exists $header] {
    putlog "getafnitaxisoffsets: $header not found"
    return $taxisoffsets
  }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set cnt 0
  set i 0
  set j 0
  foreach line $lines {
    if [string match *TAXIS_OFFSETS* $line] { set i 1; continue }
    if {$i == 1 && [lindex $line 0] == "count"} {
      set i 2
      set cnt [lindex $line 2]
      continue
    }
    if {$i == 2} {
      if {$j >= $cnt} { break }  ;# "count" not found returns empty list
      foreach arg $line {
        lappend taxisoffsets $arg
        incr j
      }
    }
  }
  if {$taxisoffsets == ""} {
    putlog "getafnitaxisoffsets: TAXIS_OFFSETS not found in $header"
  }
  return $taxisoffsets
}

### read HEAD, find multiband by count reps of first toffset in TAXIS_OFFSETS
proc getafnimbaccel { header } {
  set mb 0
  set taxisoffsets [getafnitaxisoffsets $header]
  if { [llength $taxisoffsets] == 0 } {
    putlog "getafnimbaccel: TAXIS_OFFSETS not found in $header, assuming mb=1"
    set mb 1
  } else {
    set firstoffset [lindex $taxisoffsets 0]
    foreach arg $taxisoffsets {
      if {"$arg" == "$firstoffset"} { incr mb }
    }
  }
  return $mb
}

### Make Avg/Concat Dir button command--make one notebook page of widgets
proc addrawavgscan { nbwin mkdirflag } {
  global env session iscandir
  global bgcol selbgcol entbgcol tfont ifontb hfont
  global currpage prevpage
  global rawavgdir newrawavgdir
  global sessionscanlists functscanlists
  global rawtoavgcombo rawtoavghlist rawtoavgckwidget rawtoavgimagepatt

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page

  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "sphavgscan" } {
    confirmalert "this is a Cross Session Spherical Avg:\n\nuse CrossSessTools"
    return
  }
  if {$mkdirflag} {
    set rawavgscandir $newrawavgdir
    set fullsess $env(FUNCTIONALS_DIR)/$session
    if [string match "* *" $rawavgscandir] {
      confirmalert " Make Raw Combine Dir: remove spaces\n\
                     from directory name:\n\n    \"$rawavgscandir\"\n\n\
                     and try again"
      return
    }
    if ![file exists $fullsess/$rawavgscandir] {
      if ![canwriteormakefile $fullsess/$rawavgscandir] {
        confirmalert "Make Combine Dir: can't create: $fullsess/$rawavgscandir"
        return
      }
      if [string match "*$rawavgdir" "$newrawavgdir"] {
        if ![okreplace "" \
           " Make Combine Dir: OK to use not-very-informative\n\
             default name ($rawavgdir) for new scandir?\n\n\
             (or Cancel, add informative suffix, try again)" "OK"] { return }
      }
      mkdirlog $fullsess/$rawavgscandir
      set page $rawavgscandir
      set mpage [manglepath $page]
      $nbwin subwidget hlist add $mpage -text $page -at 0   ;# put first
      $nbwin add $mpage -raisecmd "set iscandir $page; findrawavgfuncts $page"
      $nbwin subwidget $mpage config -bg $bgcol
    } else {
      confirmalert \
   "Make Raw Combine Dir: $fullsess/$rawavgscandir already exists  ...using it"
      set page $rawavgscandir
      set mpage [manglepath $page]
    }
    $nbwin raise $mpage
    set iscandir $page
    set f [$nbwin subwidget $mpage]
  }
  set sessionscanlists($page,type) functscan  ;# all needed set here
  set functscanlists($page,rawavgflag) 1

  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la -labelside acrosstop -background $bgcol -padx 10 \
     -label "Raw Combine Scan Directory" \
     -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2   ;# newpkgtix internal ugh
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  if ![info exists functscanlists($page,rawtoavgdirs)] {
    set functscanlists($page,rawtoavgdirs) {}
  }
  if ![info exists functscanlists($page,rawtoavgrevs)] {
    set functscanlists($page,rawtoavgrevs) {}
  }
  if ![info exists functscanlists($page,rawoperation)] {
    set functscanlists($page,rawoperation) average
  }
  if ![info exists functscanlists($page,rawavgfilepatt)] {
    set functscanlists($page,rawavgfilepatt) -runcombine-
  }
  # bakcompat: old addfunctscan didn't yet set these (prob should check all)
  foreach parm { paintdmin paintdmax paintdstep paintnormop paintnormtype \
                 blockcenteroffset revtTRs } {
    if { ![info exists functscanlists($page,$parm)] } {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }

  # available dirs to add (save in array, no textvariable)
  frame $f.sp1 -height 7 -bg $bgcol
  label $f.a1 -bg $bgcol -font $tfont \
    -text "Raw 3D Scan Dirs to Combine (makes new 'scan' in this dir)"
  frame $f.sp2 -height 7 -bg $bgcol

  # operation
  frame $f.a2 -bg $bgcol
  tixSelect $f.a2.op -allowzero false -radio true -label "Operation: " \
    -labelside left -orientation horizontal -bg $bgcol -command \
    "select_rawoperation $page" ;# appends butt,state
  $f.a2.op add average -text "Average Time Series" -font $hfont -width 15 \
    -bg $bgcol -pady 1
  $f.a2.op add concat -text "Concatenate Time Series" -font $hfont -width 18 \
    -bg $bgcol -pady 1
  $f.a2.op config -disablecallback true
  $f.a2.op config -variable functscanlists($page,rawoperation)
  $f.a2.op config -disablecallback false
  frame $f.sp3 -height 7 -bg $bgcol

  frame $f.b -bg $bgcol
  frame $f.b.l -bg $bgcol
  frame $f.b.l.sp4 -height 16 -bg $bgcol
  label $f.b.l.l -bg $bgcol -font $tfont -text "Select to Add:"
  frame $f.b.m -bg $bgcol
  label $f.b.m.l -bg $bgcol -font $ifontb -text "   Scan Directory"
  set rawtoavgcombo($page) $f.b.m.cbx1
  tixComboBox $f.b.m.cbx1 -dropdown true \
    -command "cbx:select_rawtoavgdir $page" -editable true -listwidth 201 \
    -options "label.width 0 label.anchor e
              entry.width 16
              listbox.height 10" ;# listbox.width 20 -> 24
  frame $f.b.r -bg $bgcol
  label $f.b.r.l -bg $bgcol -font $ifontb -text " Image Name Format"
  entry $f.b.r.e -width 18 -textvariable rawtoavgimagepatt \
    -state disabled -background $entbgcol -selectbackground $selbgcol \
    -highlightbackground $bgcol

  # middle part of panel
  frame $f.c -bg $bgcol -pady 5
  frame $f.c.l -bg $bgcol
  frame $f.c.r -bg $bgcol

  # checklist of currently selected dirs-to-average
  label $f.c.l.la -bg $bgcol -font $tfont \
     -text "<Backspace> to Omit Scan \n<Return> to Rev Time (Avg Only)"
  set rawtoavgckwidget($page) $f.c.l.cklist  ;# save in array
  tixCheckList $f.c.l.cklist -scrollbar auto -height 160 -width 230 \
     -options "hlist.selectBackground $selbgcol" -bg $bgcol \
     -highlightbackground $bgcol \
     -command "cklist0:select $rawtoavgckwidget($page) $page" ;# appends sel
  $f.c.l.cklist subwidget hlist config -font $hfont  ;# newpkgtix
  set rawtoavghlist($page) [$f.c.l.cklist subwidget hlist]  ;# save in array
  $rawtoavghlist($page) config -bd 2 -relief groove -highlightbackground $bgcol
  $rawtoavghlist($page) config -header true -indent 17 -font $hfont \
    -selectmode single -browsecmd "cklist0:browse" -separator "!" ;#appends sel
  set hstyle [tixDisplayStyle text -refwindow $rawtoavghlist($page) \
    -padx 8 -pady 2 -font $tfont]
  $f.c.l.cklist subwidget hsb config -highlightbackground $bgcol
  $f.c.l.cklist subwidget vsb config -highlightbackground $bgcol
  $rawtoavghlist($page) header create 0 \
    -itemtype text -text "Rev--ScansToCombine" -style $hstyle
  if [llength $functscanlists($page,rawtoavgdirs)] {
    foreach dir $functscanlists($page,rawtoavgdirs) {
      $rawtoavghlist($page) add $dir -itemtype imagetext -text $dir
      set index [lsearch -exact $functscanlists($page,rawtoavgdirs) $dir]
      set revstate [lindex $functscanlists($page,rawtoavgrevs) $index]
      $rawtoavgckwidget($page) setstatus $dir $revstate
    }
  }
  bind $rawtoavghlist($page) <BackSpace> "omitrawtoavgdir $page"
  bind $rawtoavghlist($page) <Delete>    "omitrawtoavgdir $page"
  # parm applies to all reversed
  tixLabelEntry $f.c.r.a \
  -label "Num TRs to timeshift\neach reversed scan\nbefore averaging\n(positive fixes delay)\n(empties end-padded)" \
  -labelside top -options "entry.textVariable functscanlists($page,revtTRs)"
  $f.c.r.a subwidget label config -width 18

  ## next yokes addrandscan $f.d.* cond combos
  #tixLabelEntry $f.d -label "Combined File Format: " -labelside left \
  #  -options "entry.textVariable functscanlists($page,rawavgfilepatt)"
  tixLabelEntry $f.d -label "Combined File Format: " -labelside left
 $f.d subwidget entry config -textvariable functscanlists($page,rawavgfilepatt)
  $f.d subwidget entry config -width 27
  $f.d subwidget label config -width 19

  pack $f.sp1 $f.a1 $f.sp2 $f.a2 $f.a2.op $f.sp3 $f.b $f.c $f.d \
    -side top -padx 10 -pady 2
  pack $f.b.l $f.b.m $f.b.r -side left
  pack $f.c.l $f.c.r -side left
  pack $f.b.l.sp4 $f.b.l.l $f.b.m.l $f.b.m.cbx1 $f.b.r.l $f.b.r.e \
    -side top -anchor w
  pack $f.c.l.la -side top
  pack $f.c.l.cklist -side top -padx 20
  pack $f.c.r.a -side top

  if {$mkdirflag} { findrawavgfuncts $page }

  set prevpage $currpage
  set currpage $page
  update idletasks   ;# (orig was just this and sigavg panel)
}

### on rawtoavg cklist browse
proc cklist0:browse { dir } {
  global rawtoavgdir
  set rawtoavgdir $dir
}

### on rawtoavg cklist select
proc cklist0:select { cklist page dir } {
  global functscanlists
  set status [$cklist getstatus $dir]
  set index [lsearch -exact $functscanlists($page,rawtoavgdirs) $dir]
  set functscanlists($page,rawtoavgrevs) \
    [lreplace $functscanlists($page,rawtoavgrevs) $index $index $status]
}

### Fourier Dir button command--make one notebook page of widgets
proc addfourscan { nbwin } {
  global env session iscandir
  global bgcol selcol selbgcol entbgcol ffont ffontb tfont hfont
  global currpage prevpage
  global sessionscanlists functscanlists
  global realname complexname

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page

  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "sphavgscan" } {
    confirmalert "this is a Cross Session Spherical Avg:\n\nuse CrossSessTools"
    return
  }
  if ![info exists sessionscanlists($page,type)] {
    confirmalert "Fourier Scan: first do Setup Functional Scan for \"$page\""
    return
  }
  set functscanlists($page,fourflag)   1
  set functscanlists($page,stattype) complex

  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la -labelside acrosstop -background $bgcol -padx 10 \
     -label "Fourier Analysis Scan Directory" \
     -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2   ;# newpkgtix internal ugh
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  # bak compat: for old config'd pre-phasestatformat scan w/1st action FOURIER
  if ![info exists functscanlists($page,phasestatformat)] {
    set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
    if { [glob -nocomplain $fullscandir/*_000.bfloat] != "" } { ;# req done
      set functscanlists($page,phasestatformat) bfloat  ;# def now afnibrik
    }
  }

  # default missing parms
  foreach parm { stimcycles lofreqwin hifreqwin omitfreq permtestcnt \
                 meandelay preclustfthr clustarea \
                 fixileaveflag useTAXISflag inclharm23flag \
                 clusterrad clustervol \
                 smoothfwhm paintext \
                 rh,truncphasemin lh,truncphasemin \
                 rh,truncphasemax lh,truncphasemax \
                 filetruncphaseflag truncslope \
                 phasestattype phasestatformat fullfourierflag \
                 paintdmin paintdmax paintdstep paintnormop paintnormtype \
                 allverticesflag } {
    if ![info exists functscanlists($page,$parm)] {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }
  if ![info exists functscanlists($page,bfloatpattinf)] {
    set functscanlists($page,bfloatpattinf) -runfourier-
  }
  if ![info exists functscanlists($page,bfloatpatt)] {  ;# 35l: add this
    set functscanlists($page,bfloatpatt) -runfourier-
  }
  if ![info exists functscanlists($page,rh,wfile)] {
    set functscanlists($page,rh,wfile) -runpaint-
  }
  if ![info exists functscanlists($page,lh,wfile)] {
    set functscanlists($page,lh,wfile) -runpaint-
  }
  if ![info exists functscanlists($page,angle_offset1sec)] {
    set functscanlists($page,angle_offset1sec) -to_be_calc'd-
  }

#xxx -- fixed imagepatt corrupt? (avoid -options, a->aa)
  ## first attempt to fix corruption of imagepatt (deletion of .BRIK suffix)
  #tixLabelEntry $f.a -label "Image Name Format: " -labelside left \
  #  -options "entry.textVariable functscanlists($page,imagepatt)"
  tixLabelEntry $f.aa -label "Image Name Format: " -labelside left
  $f.aa subwidget entry config -textvariable functscanlists($page,imagepatt)
  ## stimnotes junk insertion noticed at add SurfClust (fixed?)
  #tixLabelEntry $f.b -label "StimProg NOTES: " -labelside left \
  #  -options "entry.textVariable functscanlists($page,stimnotes)"
  tixLabelEntry $f.b -label "StimProg NOTES: " -labelside left
  $f.b subwidget entry config -textvariable functscanlists($page,stimnotes)
  #TODO: stimcycles sometimes written to csurf.dat as first scandir (fixed?)

  frame $f.c -bg $bgcol
  button $f.c.a -text "cp prev" -font $ffont -bg $bgcol -pady 1 -padx 0 \
    -command "cpprevfourierparms" -highlightbackground $bgcol
  frame $f.c.b -bg $bgcol -width 10
  tixLabelEntry $f.c.c -label "Stim Cycles Per Scan: " -labelside left
  $f.c.c subwidget entry config -textvariable functscanlists($page,stimcycles)
  frame $f.c.d -bg $bgcol -width 10

  frame $f.d -bg $bgcol
  checkbutton $f.d.ck0 -font $tfont \
    -text "harm23" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,inclharm23flag) -highlightbackground $bgcol
  checkbutton $f.d.ck -font $tfont \
    -text "UseSliceOrd" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,fixileaveflag) -highlightbackground $bgcol \
    -command "setslicetimetype sliceord $page"
  checkbutton $f.d.ck1 -font $tfont \
    -text "UseTAXIS" -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,useTAXISflag) -highlightbackground $bgcol \
    -command "setslicetimetype taxis $page"
  tixLabelEntry $f.d.e -label "TR:" -labelside left \
    -options "entry.textVariable functscanlists($page,TR)"
  $f.d.e subwidget entry config -width 3
  $f.d.e subwidget label config -width 3

  tixLabelEntry $f.e -label "3D (Pre)Smooth FWHM (mm): " -labelside left \
    -options "entry.textVariable functscanlists($page,smoothfwhm)"
  tixLabelEntry $f.f -label "Lo-Freq Cutoff (cyc/scan): " -labelside left \
    -options "entry.textVariable functscanlists($page,lofreqwin)"
  tixLabelEntry $f.f2 -label "Hi-Freq Cutoff (-1 => Nyquist): " -labelside \
    left -options "entry.textVariable functscanlists($page,hifreqwin)"
  tixLabelEntry $f.f3 -label "Omit Freq (-1 => skip omit): " -labelside left \
    -options "entry.textVariable functscanlists($page,omitfreq)"
  tixLabelEntry $f.f4 -label "Permute Test Count (0=off): " -labelside left \
    -options "entry.textVariable functscanlists($page,permtestcnt)"
  bind [$f.f4 subwidget entry] <Return> "setphasestattype $page"
  #tixLabelEntry $f.g -label "Mean Delay (F-stats: 0-1): " -labelside left \
  #  -options "entry.textVariable functscanlists($page,meandelay)"

  tixLabelEntry $f.g -label "3D and Surf Clust: PreThr (F/p): " -labelside left
  $f.g subwidget entry config -textvariable functscanlists($page,preclustfthr)
  tixLabelEntry $f.g1 -label "SurfCluster: min area (mm^2): " -labelside left
  $f.g1 subwidget entry config -textvariable functscanlists($page,clustarea)

  ### labels if omit -dxyz=1: "3DClust:  connected(mm)=", "  minvol(mm^3)="
  frame $f.g4 -bg $bgcol
  label $f.g4.la1 -text "3DClust (units=vox):  connected=" \
    -bg $bgcol -font $tfont
  entry $f.g4.e1 -width 3 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable functscanlists($page,clusterrad) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.g4.la2 -text "  minvol=" -bg $bgcol -font $tfont
  entry $f.g4.e2 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable functscanlists($page,clustervol) \
    -highlightbackground $bgcol -font $ffont -selectforeground black

  tixSelect $f.g2 -allowzero true -radio true \
    -label "Phase Stat Type (old=sqrt-F): " \
    -orientation horizontal -options "label.width 27"
  foreach but "sqrt-F p-val p-FA" {
    $f.g2 add $but -text $but -font $hfont -width 2 -bg $bgcol -pady 1
  }
  $f.g2 config -variable functscanlists($page,phasestattype)

  frame $f.g3 -bg $bgcol  ;# was "Phase Stat Out Format", width 21
  tixSelect $f.g3.sel -allowzero true -radio true \
    -label "Stat Format: " \
    -orientation horizontal -options "label.width 11"
  foreach but "bfloat afnibrik" {
    $f.g3.sel add $but -text $but -font $hfont -width 3 -bg $bgcol -pady 1
  }
  $f.g3.sel config -variable functscanlists($page,phasestatformat)
  checkbutton $f.g3.ck -font $tfont -text "full FT" -selectcolor $selcol \
    -bg $bgcol -variable functscanlists($page,fullfourierflag) \
    -highlightbackground $bgcol -command "setphasestatformat $page"
  button $f.g3.bu -text "rm full FT" -font $ffontb -bg $bgcol \
    -highlightbackground $bgcol -command "rmfullFTs $page" -pady 1 -padx 3

  tixSelect $f.h -allowzero true -radio true -label "Phase Encode Type: " \
    -orientation horizontal -options "label.width 18"
  foreach but "eccen polar 2cond fstat" {
    $f.h add $but -text $but -font $hfont -width 3 -bg $bgcol -pady 1
  }
  $f.h config -variable functscanlists($page,phasetype)

  frame $f.h2 -bg $bgcol
  checkbutton $f.h2.ck -font $tfont -text "Truncphase " \
    -selectcolor $selcol -bg $bgcol -highlightbackground $bgcol \
    -variable functscanlists($page,filetruncphaseflag)
  label $f.h2.la1 -text "LH:" -bg $bgcol -font $tfont
  entry $f.h2.e1 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable functscanlists($page,lh,truncphasemin) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.h2.la2 -text "to" -bg $bgcol -font $tfont
  entry $f.h2.e2 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable functscanlists($page,lh,truncphasemax) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.h2.la3 -text "  RH:" -bg $bgcol -font $tfont
  entry $f.h2.e3 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable functscanlists($page,rh,truncphasemin) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.h2.la4 -text "to" -bg $bgcol -font $tfont
  entry $f.h2.e4 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable functscanlists($page,rh,truncphasemax) \
    -highlightbackground $bgcol -font $ffont -selectforeground black

  #35l: bfloatpattinf (bfloatpatt w/bracketted infixes) *not* packed
  tixLabelEntry $f.i -label "Fourier Stat Image Sets: " -labelside left \
    -options "entry.textVariable functscanlists($page,bfloatpattinf)"
  # instead expose bfloatpatt in interface so can hand-fix if necessary
  tixLabelEntry $f.i2 -label "Fourier Format (minus infixes): " -labelside \
    left -options "entry.textVariable functscanlists($page,bfloatpatt)"
  # infixes not saved (def on restart)
  tixLabelEntry $f.j -label "Real and Imaginary Infixes: " -labelside left \
    -options "entry.textVariable realname"
  $f.j subwidget entry config -width 6  ;# shrink to add next
  entry $f.j.e -textvariable complexname -width 6 -selectbackground $selbgcol \
    -bg $entbgcol -highlightbackground $bgcol -highlightbackground $bgcol
  # why? (next sometimes inserts current page into paintext value)
  #tixLabelEntry $f.k -label "Surface for Sampling 3D Data: " -labelside left \
  #  -options "entry.textVariable functscanlists($page,paintext)"
  tixLabelEntry $f.k -label "Surface for Sampling 3D Data: " -labelside left
  $f.k subwidget entry config -textvariable functscanlists($page,paintext)
 # why? (next sometimes inserts image/align instead of filename)
 #tixLabelEntry $f.l -label "Painted Vertex List Files (rh): " -labelside left \
 #  -options "entry.textVariable functscanlists($page,rh,wfile)"
 #tixLabelEntry $f.m -label "Painted Vertex List Files (lh): " -labelside left \
 #  -options "entry.textVariable functscanlists($page,lh,wfile)"
  tixLabelEntry $f.l -label "Painted VertexList Files (rh): " -labelside left
  $f.l subwidget entry config -textvariable functscanlists($page,rh,wfile)
  tixLabelEntry $f.m -label "Painted VertexList Files (lh): " -labelside left
  $f.m subwidget entry config -textvariable functscanlists($page,rh,wfile)
  tixLabelEntry $f.n -label "Angle_Offset for 1sec delay: " -labelside left \
    -options "entry.textVariable functscanlists($page,angle_offset1sec)"

  pack $f.aa $f.b -side top -padx 10 -pady 2
  pack $f.c -side top -padx 0 -pady 2
  pack $f.c.a $f.c.b $f.c.c $f.c.d -side left -padx 0 -pady 0
  pack $f.d $f.e $f.f $f.f2 $f.f3 $f.f4 $f.g $f.g1 $f.g4 $f.g2 $f.g3 $f.h \
    $f.h2 $f.i2 $f.j $f.k $f.l $f.m $f.n -side top -padx 10 -pady 2
  pack $f.g4.la1 $f.g4.e1 $f.g4.la2 $f.g4.e2 -side left -padx 2
  pack $f.g3.sel -side left
  pack $f.g3.ck $f.g3.bu -side left -padx 4
  pack $f.g3.bu -side left
  pack $f.h2.ck $f.h2.la1 $f.h2.e1 $f.h2.la2 $f.h2.e2 $f.h2.la3 $f.h2.e3 \
    $f.h2.la4 $f.h2.e4 -side left
  pack $f.d.ck0 $f.d.ck $f.d.ck1 $f.d.e $f.j.e -side left -padx 5
  pack $f.d.ck0 $f.d.ck $f.d.ck1 -padx 0  ;# squish
  pack forget $f.j   ;# hide remove rarely used, not saved, live infixes
  pack $f.g4.la1 $f.g4.e1 $f.g4.la2 $f.g4.e2 -padx 0  ;# tighten

  ### next resets req'd if addrender panel opened before this (why? tix bug?)
  $f.c.c subwidget label config -width 20
  $f.e subwidget label config -width 27   ;# no longer needed, left
  $f.f subwidget label config -width 27
  $f.g subwidget label config -width 27
  $f.c.c subwidget entry config -width 14

  if [info exists functscanlists($page,reps)] {
    checkpow2 $functscanlists($page,reps)
  }

  set prevpage $currpage
  set currpage $page
  update idletasks
}

### manual Select using checkboxes
proc setslicetimetype { type page } {
  global functscanlists
  if {$functscanlists($page,fixileaveflag) &&
      $functscanlists($page,useTAXISflag)} {
    if {$type == "sliceord"} {
      set functscanlists($page,useTAXISflag) 0
      confirmalert "Using \"Slice Ord:\" slice time specification\
                \n\nN.B.: AFNI TAXIS_OFFSETS will be ignored"
    }
    if {$type == "taxis"} {
      set functscanlists($page,fixileaveflag) 0
      confirmalert "Using slice times from AFNI TAXIS_OFFSETS\
                \n\nN.B.: \"Slice Ord:\" specification will be ignored"
    }
  }
}

### selecting non-zero permutation count sets phase state type to p-val
proc setphasestattype { page } {
  global functscanlists
  if {$functscanlists($page,permtestcnt) > 0} {
    set functscanlists($page,phasestattype) "p-val"
  } else {
    set functscanlists($page,phasestattype) "sqrt-F"  ;# re-default
  }
}

### selecting "full FT" changes stat format to BRIK (not req'd, but sensible)
proc setphasestatformat { page } {
  global functscanlists
  if {$functscanlists($page,fullfourierflag)} {
    set functscanlists($page,phasestatformat) "afnibrik"
  }
}

### cleanup large full FT's (6x as big as raw data)
proc rmfullFTs { page } {
  global env session iscandir

  set iscandir $page
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  set fullFTlist "\
    [glob -nocomplain $fullscandir/*_xf+orig.HEAD] \
    [glob -nocomplain $fullscandir/*_xf+orig.BRIK] \
    [glob -nocomplain $fullscandir/*_yf+orig.HEAD] \
    [glob -nocomplain $fullscandir/*_yf+orig.BRIK] \
    [glob -nocomplain $fullscandir/*_af+orig.HEAD] \
    [glob -nocomplain $fullscandir/*_af+orig.BRIK]"
  if ![llength $fullFTlist] {
    confirmalert "Fourier: no full FT's to cleanup"
    return
  }
  set fmtlist ""
  foreach file $fullFTlist {
    if ![string match *.HEAD $file] {
      set fmtlist "$fmtlist \n    [file tail $file]"
    }
  }
  if ![okreplace "" \
    "Fourier: delete full FT's (6x raw)?:\n\n  scandir:  $iscandir\n$fmtlist" \
    "Cleanup/Remove Full FTs"] { return }
  foreach file $fullFTlist { rmlog $file }
}

### reset-to-default-like button for cp render parms from prev panel
proc cpprevfourierparms { } {
  global functscanlists currpage prevpage

  if {"$prevpage" == "$currpage"} { return }
  if ![okreplace "" "OK to copy Fourier parms from:\
                 \n\n    $prevpage\
                 \n\nto:\
                 \n\n    $currpage?" "Copy Fourier Parms"] { return }
  set cpparmlist "\
    stimcycles \
    inclharm23flag fixileaveflag useTAXISflag TR \
    smoothfwhm \
    lofreqwin \
    hifreqwin \
    omitfreq \
    permtestcnt \
    preclustfthr \
    clustarea \
    clusterrad clustervol \
    phasestattype \
    phasestatformat fullfourierflag \
    phasetype \
    filetruncphaseflag \
    lh,truncphasemin lh,truncphasemax rh,truncphasemin rh,truncphasemax \
    paintext"
  foreach parm $cpparmlist {
    if [info exists functscanlists($prevpage,$parm)] {
      set functscanlists($currpage,$parm) $functscanlists($prevpage,$parm)
    } else {
      confirmalert "Can't copy Fourier parameter from prev scandir:\
                    \n\n    $prevpage\
                    \n\nScandir \"$prevpage\" not yet configured\
                    \n\n(first missing parm: $parm)"
      return
    }
  }
}

### Rand Block Dir button command--make one notebook page of widgets
proc addrandscan { nbwin } {
  global env session iscandir
  global bgcol selcol selbgcol hilbgcol hilcol actbgcol
  global ffontb tfont ifontb hfont
  global currpage prevpage
  global sessionscanlists functscanlists
  global paradigmhlist paradigmscombo paradigmdefdir
  global condnamescombo1 condnamescombo2 condnames2difforaddhlist
  global condname1 condname2 simplediffsflag

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page

  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "sphavgscan" } {
    confirmalert "this is a Cross Session Spherical Avg:\n\nuse CrossSessTools"
    return
  }
  if ![info exists sessionscanlists($page,type)] {
    confirmalert "Calc Fourier Stats: first do Setup Funct Scan for \"$page\""
    return
  }
  set functscanlists($page,randflag)   1
  set functscanlists($page,stattype)  paradigm

  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la -labelside acrosstop -background $bgcol -padx 10 \
     -label "Random Block Design Scan Directory" \
     -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  ## defaults
  foreach parm { smoothfwhm maxlag polort concatfiles vregdfile \
                 extraoptsrand deconvtype contrastcnt vregregressflag } {
    if ![info exists functscanlists($page,$parm)] {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }  
  if ![info exists functscanlists($page,paradigmdir)] {
    set functscanlists($page,paradigmdir) $paradigmdefdir  ;# now req rel
  }
  if ![info exists functscanlists($page,paradigmfile)] {
    set functscanlists($page,paradigmfile) ""
  }
  if ![info exists functscanlists($page,reps)] {
    set functscanlists($page,reps) 0   ;# delay raise error
  }
  if ![info exists functscanlists($page,condnames)] {
    set functscanlists($page,condnames) {}
  }
  if ![info exists functscanlists($page,condnames2difflist)] {
    set functscanlists($page,condnames2difflist) {}
  }
  if ![info exists functscanlists($page,condnames2addlist)] {
    set functscanlists($page,condnames2addlist) {}
  }
  if ![info exists functscanlists($page,stats3ddecon)] {
    set functscanlists($page,stats3ddecon) -rundeconvolve-
  }

  ## infile
  #tixLabelEntry $f.a -label "Image Name Format: " -labelside left -options \
  #  "entry.textVariable functscanlists($page,imagepatt)"
#xxx -- fixed imagepatt corrupt? (avoid -option, a->aaa)
  tixLabelEntry $f.aaa -label "Image Name Format: " -labelside left
  $f.aaa subwidget label config -width 23
  $f.aaa subwidget entry config -textvariable functscanlists($page,imagepatt)
  $f.aaa subwidget entry config -width 27

  ## paradigm
  tixLabelEntry $f.b -label "Paradigm Dir (stim1Ds): " -labelside left
  $f.b subwidget label config -width 23
  $f.b subwidget entry config -width 27
  $f.b subwidget entry config -textvariable functscanlists($page,paradigmdir)
  bind [$f.b subwidget entry] <Return> "fixparadigms $page; fixcondnames $page"
  $f.b subwidget entry xview moveto 1

  set paradigmscombo($page) $f.cbx
  tixComboBox $f.cbx -label "Paradigm Files: " -dropdown true \
    -command "cbx:select_paradigm $page" -editable false \
    -variable functscanlists($page,paradigmfile) -listwidth 173 \
    -options "label.width 27 label.anchor e
              entry.width 15
              listbox.height 10" ;# listbox.width 10 -> 20
  fixparadigms $page
  button $f.cbx.bu -text "READ 1Ds" -font $ffontb -highlightbackground $bgcol \
    -command "fixparadigms $page; fixcondnames $page" -pady 1 -padx 5
  $f.cbx config -background $bgcol
  $f.cbx subwidget label config -width 14

  ### parms
  frame $f.c -bg $bgcol
  tixLabelEntry $f.c.a -label "3D Smooth FWHM (mm): " -labelside left \
    -options "entry.textVariable functscanlists($page,smoothfwhm)"
  $f.c.a subwidget label config -width 22
  $f.c.a subwidget entry config -width 5
  tixLabelEntry $f.c.b -label "TR (sec): " -labelside left \
    -options "entry.textVariable functscanlists($page,TR)"
  $f.c.b subwidget label config -width 12
  $f.c.b subwidget entry config -width 5
  tixLabelEntry $f.c2 -label "Maximum Lag (-maxlag, TRs): " -labelside left \
    -options "entry.textVariable functscanlists($page,maxlag)"
  tixLabelEntry $f.c3 -label "Polynomial Fit Order (-polort): " -labelside \
    left -options "entry.textVariable functscanlists($page,polort)"
  tixLabelEntry $f.c4 -label "Motion Params File (-dfile): " -labelside left \
    -options "entry.textVariable functscanlists($page,vregdfile)"
  checkbutton $f.c4.ck1 -selectcolor $selcol -bg $bgcol \
    -variable functscanlists($page,vregregressflag) -highlightbackground $bgcol
  tixLabelEntry $f.c4a -label "Other Options: " -labelside left -options \
    "entry.textVariable functscanlists($page,extraoptsrand)"
  $f.c4a subwidget label config -width 13
  $f.c4a subwidget entry config -width 33
  frame $f.c5 -bg $bgcol
  tixLabelEntry $f.c5.a -label "Scans: " -labelside left \
    -options "entry.textVariable functscanlists($page,concatfiles)"
  tixLabelEntry $f.c5.b -label "Total TRs: " -labelside left \
    -options "entry.textVariable functscanlists($page,reps)"
  $f.c5.a subwidget entry config -width 9   ;# -state disabled
  $f.c5.b subwidget entry config -width 9   ;# -state disabled
  $f.c5.a subwidget label config -width 10
  $f.c5.b subwidget label config -width 13

  tixSelect $f.ck1 -allowzero false -radio true -orientation horizontal
  $f.ck1 add test -text "Test Design (check log)" -font $hfont \
    -bg $bgcol -pady 1 -padx 5 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $f.ck1 add fout -text "F-Stats Output" -font $hfont \
    -bg $bgcol -pady 1 -padx 5 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $f.ck1 add tout -text "t-Stats Output" -font $hfont \
    -bg $bgcol -pady 1 -padx 5 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $f.ck1 config -variable functscanlists($page,deconvtype)

  ## user feedback: hlist of paradigm column files made into matrix
  tixScrolledHList $f.shlist -scrollbar auto -height 110 -width 360 \
    -options "hlist.selectBackground $selbgcol" -background $bgcol \
    -highlightbackground $bgcol
  $f.shlist subwidget hlist config -font $hfont  ;# newpkgtix
  set paradigmhlist($page) [$f.shlist subwidget hlist]  ;# save in array
  $paradigmhlist($page) config -header true -selectmode single -font $hfont \
    -browsecmd "" -separator "!"
  set hstyle [tixDisplayStyle text -refwindow $paradigmhlist($page) \
    -padx 2 -pady 2 -font $tfont]
  $f.shlist subwidget hsb config -highlightbackground $bgcol
  $f.shlist subwidget vsb config -highlightbackground $bgcol
  ## next now, else stale names in title (select_paradigm call bef hlist there)
  readparadigmfiles $page
  set ti TR
  foreach cond $functscanlists($page,condnames) {
    if { [string length $cond] > 7 } {
      set ti "$ti  $cond"
    } else {
      set ti "$ti\t$cond"
    }
  }
  $paradigmhlist($page) header create 0 -itemtype text -text $ti -style $hstyle

  ## orig setup contrasts: nice interface, but just binary diffs/adds
  frame $f.d -bg $bgcol
  frame $f.d.l -bg $bgcol
  frame $f.d.l.sp1 -height 16 -bg $bgcol
  label $f.d.l.l1 -bg $bgcol -font $tfont -text "Condition A:"
  label $f.d.l.l2 -bg $bgcol -font $tfont -text "Condition B:"

  # combo boxes select condition name (synt equiv addfunct $f.d.* fixes yoking)
  frame $f.d.m -bg $bgcol
  label $f.d.m.l -bg $bgcol -font $ifontb -text "   Condition Name"
  set condnamescombo1($page) $f.d.m.cbx1
  tixComboBox $f.d.m.cbx1 -dropdown true \
    -command "cbx:select_condname1 $page" -editable true \
    -variable condname1($page) \
    -options "label.width 0
              entry.width 17
              listbox.height 10 listbox.width 10"
  set condnamescombo2($page) $f.d.m.cbx2
  tixComboBox $f.d.m.cbx2 -dropdown true \
    -command "cbx:select_condname2 $page" -editable true \
    -variable condname2($page) \
    -options "label.width 0
              entry.width 17
              listbox.height 10 listbox.width 10"
  fixcondnames $page

  frame $f.d.r1 -bg $bgcol
  frame $f.d.r1.sp1 -height 16 -bg $bgcol
  frame $f.d.r1.sub -bg $bgcol
  frame $f.d.r1.add -bg $bgcol
  button $f.d.r1.sub.bu -text "ADD SUBTRACTION" -font $ffontb -command \
    "addcondnames2diff $page" -pady 1 -padx 2 -highlightbackground $bgcol
  button $f.d.r1.add.bu -text "ADD ADDITION" -font $ffontb -command \
    "addcondnames2add $page" -pady 1 -padx 2 -highlightbackground $bgcol

  # current diffs hlist
  frame $f.e -bg $bgcol
  tixScrolledHList $f.e.shlist -scrollbar auto -width 325 -height 100 \
    -options "hlist.selectBackground $selbgcol" -background $bgcol \
    -highlightbackground $bgcol
  $f.e.shlist subwidget hlist config -font $hfont  ;# newpkgtix
  set condnames2difforaddhlist($page) [$f.e.shlist subwidget hlist]
  $condnames2difforaddhlist($page) config -header true -selectmode single \
    -font $hfont -browsecmd "hlist3:browse" -separator "!" -bd 1 -relief groove
 set hstyle [tixDisplayStyle text -refwindow $condnames2difforaddhlist($page) \
    -padx 8 -pady 2 -font $tfont]
  $condnames2difforaddhlist($page) header create 0 -itemtype text \
    -text "Subtractions List -- omit: <Backspace>" -style $hstyle
  if [llength $functscanlists($page,condnames2difflist)] {
    foreach diff $functscanlists($page,condnames2difflist) {
      $condnames2difforaddhlist($page) add $diff -text $diff
    }
  }
  if [llength $functscanlists($page,condnames2addlist)] {
    foreach add $functscanlists($page,condnames2addlist) {
      $condnames2addoraddhlist($page) add $add -text $add
    }
  }
  bind $condnames2difforaddhlist($page) <BackSpace> \
    "omitcondnames2difforadd $page"
  bind $condnames2difforaddhlist($page) <Delete> \
    "omitcondnames2difforadd $page"

  ## new setup contrasts: arbitrary glts
  frame $f.f -bg $bgcol -bd 2 -relief groove
  frame $f.f.tp -bd 3 -bg $bgcol
  label $f.f.tp.la -text "      " -bg $bgcol -font $tfont
  button $f.f.tp.bu0 -text "AUTO NAMES" -font $ffontb -pady 2 -padx 1 \
    -command "contrastwline mknames $page $f.f.ens" -highlightbackground $bgcol
  set autonamesbu $f.f.tp.bu0
  button $f.f.tp.bu1 -text "ADD CONTRAST" -font $ffontb -pady 2 -padx 1 \
    -command "contrastwline add $page $f.f.ens" -highlightbackground $bgcol
  set addnewcontrastbu $f.f.tp.bu1
  button $f.f.tp.bu2 -text "DELETE LAST" -font $ffontb -pady 2 -padx 1 \
    -command "contrastwline delete $page $f.f.ens" -highlightbackground $bgcol
  label $f.f.tp.la2 -text "    " -bg $bgcol -font $tfont
  frame $f.f.tp2 -bg $bgcol
  label $f.f.tp2.la -text "                 Condition GLTs" -bg $bgcol \
    -font $tfont
  frame $f.f.cnds -bg $bgcol
  set ti "    GLT name"
  foreach cond $functscanlists($page,condnames) {
    if { [string length $cond] > 7 } {
      set ti "$ti  $cond"
    } else {
      set ti "$ti\t$cond"
    }
  }
  label $f.f.cnds.la -text "$ti " -bg $bgcol -font $tfont
  frame $f.f.ens -bg $bgcol
  # reinstate panel
  set functscanlists($page,contrastcnt) 0   ;# have to recount upon remake
  set i 0
  foreach index [lsort [array names functscanlists $page,?,*,gltnum]] {
    if [string match $page,$i,*,gltnum $index] {
      $addnewcontrastbu invoke ;# uses $functscanlists($page,$num,$cond,gltnum)
      incr i
    }
  }

  ## outfile
  tixLabelEntry $f.g -label "Stats Output File: " -labelside left \
    -options "entry.textVariable functscanlists($page,stats3ddecon)"
  $f.g subwidget entry config -width 27
  $f.g subwidget label config -width 17

  ## pack
  pack $f.aaa $f.b $f.cbx $f.cbx.bu $f.c $f.c2 $f.c3 $f.c4 $f.c4a $f.c5 \
         $f.ck1 $f.shlist $f.d $f.e -side top -padx 10 -pady 1
    pack $f.c.a $f.c.b -side left -padx 0 -pady 0
    pack $f.c4.ck1 -side left -padx 0 -pady 0
    pack $f.c5.a $f.c5.b -side left
    pack $f.d.l $f.d.m $f.d.r1 -side left
      pack $f.d.l.sp1 $f.d.l.l1 $f.d.l.l2 -side top -anchor w -pady 1
      pack $f.d.m.l $f.d.m.cbx1 $f.d.m.cbx2 -side top -anchor w
      pack $f.d.r1.sp1 $f.d.r1.sub $f.d.r1.add -side top
      pack $f.d.r1.sub.bu $f.d.r1.add.bu -side top
    pack $f.e.shlist -side left -padx 5
  pack $f.f -side top -padx 5 -pady 6
    pack $f.f.tp $f.f.tp2 $f.f.cnds $f.f.ens -side top -padx 0
      pack $f.f.tp.bu0 $f.f.tp.la $f.f.tp.bu1 $f.f.tp.bu2 $f.f.tp.la2 \
        -side left -padx 3
      pack $f.f.tp2.la -side left -pady 2
      pack $f.f.cnds.la -side left -padx 0
  pack $f.g -side top -padx 10 -pady 1
  if {$simplediffsflag} { pack forget $f.f } else { pack forget $f.d $f.e }

  set prevpage $currpage
  set currpage $page
  update idletasks
}

### load/update Rand Block Dir listbox with paradigm files
proc readparadigmfiles { page } {
  global env session iscandir functscanlists paradigmhlist parasuff diffinfix

  #TODO: gets in here twice on panel read
  if ![info exists paradigmhlist($page)] { return }
  if ![winfo exists $paradigmhlist($page)] { return } 
  if {$functscanlists($page,paradigmfile) == ""} { return }
  set iscandir $page
  foreach line [$paradigmhlist($page) info children] {
    $paradigmhlist($page) delete entry $line
  }
  set pstemlist {}
  set paradir $functscanlists($page,paradigmdir)
  #if ![string match /* $paradir] {  ;# glob saved rel dir here too
  #  set paradir $env(FUNCTIONALS_DIR)/$session/$iscandir/$paradir
  #}
  set paradir $env(FUNCTIONALS_DIR)/$session/$iscandir/$paradir ;# now req rel
  set pfilelist [glob -nocomplain $paradir/*.$parasuff]
  set tr 0
  set cn 0
  foreach fullpfile $pfilelist {
    set pstem [file rootname [file tail $fullpfile]]
    lappend pstemlist $pstem
    set id [open $fullpfile r]
    set tr 0
    foreach line [split [read $id] "\n"] {
      if ![llength $line] { continue }
      if { [lindex $line 0] == "1"} {
        array set paradigmmat "$tr,$cn $pstem"
      } elseif { [lindex $line 0] == "0"} {
        array set paradigmmat "$tr,$cn -----" 
      } else {
        confirmalert \
            " Read Paradigm Files: bad 1D val:\n\n\
              value: [lindex $line 0]\n\
              line: [expr $tr + 1]\n\
              in paradigm file:\n\
              $fullpfile\n\n\
              (fix 1D file and re-click READ 1Ds)"
        return
      }
      incr tr
    }
    if { [info exists trlast] && $trlast != $tr } {
      confirmalert \
"Read Paradigm Files: length ($tr):\n\n   $fullpfile\n\ndoesn't match previous"
      return
    }
    set trlast $tr
    incr cn
  }
  set trcnt $tr
  set cncnt $cn
  # condition names come from paradigm file stems
  set functscanlists($page,condnames) $pstemlist
  foreach cond $functscanlists($page,condnames) {
    if {"$cond" == "$diffinfix"} {
      confirmalert \
    "Read Paradigm Files: bad cond name: $diffinfix (same as diff infix)"
      return
    }
  }
  for {set tr 0} {$tr < $trcnt} {incr tr} {  ;# print as matrix
    set trline "  $tr"
    for {set cn 0} {$cn < $cncnt} {incr cn} {
      set trline "$trline\t$paradigmmat($tr,$cn)"
    }
    $paradigmhlist($page) add $tr -text "$trline"
  }
  # nag/warn too-long names (one for every RandBlock scandir on panel opening)
  foreach cond $functscanlists($page,condnames) {
    if { [string length $cond] > 7 } {
      confirmalert "READ 1Ds: shorten 1D condition filename:\
                \n\n    scandir:     $page\
                  \n    condition:  $cond\
                \n\nUse 7 or less chars before the \".1D\" suffix"
      break
    }
  }
}

### ADD CONTRAST,DEL_LAST.. butt cmds (Calculate Random Block Statistics panel)
proc contrastwline { action page enswin } {
  global functscanlists
  global bgcol selbgcol entbgcol hfont

  if {$action == "add" && $functscanlists($page,contrastcnt) > 9} {
    confirmalert "Add Contrast: can't add more than 10 between-cond glts"
    return
  }
  set contrastlinelist [lsort [info commands $enswin.li?]]
  if {$action == "add"} {
    set num [llength $contrastlinelist]  ;# new zero-based line
    frame $enswin.li$num -bg $bgcol
    pack $enswin.li$num -side top
    label $enswin.li$num.la -text " $num" -bg $bgcol
    pack $enswin.li$num.la -side left -padx 0
    entry $enswin.li$num.e0 \
      -textvariable functscanlists($page,$num,gltname) \
      -bg $entbgcol -selectbackground $selbgcol -width 10 -font $hfont \
      -selectforeground black -highlightbackground $bgcol
    pack $enswin.li$num.e0 -side left -padx 3

    set i 1
    foreach cond $functscanlists($page,condnames) {
      entry $enswin.li$num.e$i \
        -textvariable functscanlists($page,$num,$cond,gltnum) \
        -bg $entbgcol -selectbackground $selbgcol -width 3 -font $hfont \
        -selectforeground black -highlightbackground $bgcol
      if {$functscanlists($page,$num,$cond,gltnum) == ""} {
        set functscanlists($page,$num,$cond,gltnum) 0  ;# only default empty
      }
      pack $enswin.li$num.e$i -side left -padx 14
      incr i 
    }
    incr functscanlists($page,contrastcnt)
  }
  if {$action == "delete" && "$contrastlinelist" != ""} {
    set lastnum [expr [llength $contrastlinelist] - 1]
    destroy [lindex $contrastlinelist end]
    foreach cond $functscanlists($page,condnames) {
      unset functscanlists($page,$lastnum,$cond,gltnum)
    }
    incr functscanlists($page,contrastcnt) -1
  }
  if {$action == "mknames"} {
    set mknamesflag 1
    chkcontrastsmknames $page $mknamesflag
  }
}

### Make CombineDir button command--make one notebook page of widgets
proc addsigavgscan { nbwin mkdirflag } {
  global env session iscandir
  global bgcol selcol selbgcol entbgcol tfont ifontb hfont
  global currpage prevpage 
  global sigavgdir newsigavgdir
  global sigtoavgcombo sigtoavghlist sigtoavgckwidget sigtoavgbfloatstem
  global sessionscanlists functscanlists

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page

  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "sphavgscan" } {
    confirmalert "this is a Cross Session Spherical Avg:\n\nuse CrossSessTools"
    return
  }
  if {$mkdirflag} {
    set sigavgscandir $newsigavgdir
    set fullsess $env(FUNCTIONALS_DIR)/$session
    if [string match "* *" $sigavgscandir] {
      confirmalert " Make Combine Dir: remove spaces\n\
                     from directory name:\n\n    \"$sigavgscandir\"\n\n\
                     and try again"
      return
    }
    if ![file exists $fullsess/$sigavgscandir] {
      if ![canwriteormakefile $fullsess/$sigavgscandir] {
        confirmalert "Make Combine Dir: can't create: $fullsess/$sigavgscandir"
        return
      }
#xxxxxxxxxxxx -- was backwards! TODO: change all other $new*dir like this
      #if [string match "*$sigavgdir" "$newsigavgdir"] { }
      if [string match "*/$newsigavgdir" "$sigavgdir"] {
        if ![okreplace "" \
           " Make Combine Dir: OK to use not-very-informative\n\
             default name ($sigavgdir) for new scandir?\n\n\
             (or Cancel, add informative suffix, try again)" "OK"] { return }
      }
      mkdirlog $fullsess/$sigavgscandir
      set page $sigavgscandir
      set mpage [manglepath $page]
      $nbwin subwidget hlist add $mpage -text $page -at 0   ;# put first
      $nbwin add $mpage -raisecmd "set iscandir $page; findsigavgfuncts $page"
      $nbwin subwidget $mpage config -bg $bgcol
    } else {
      confirmalert \
       "Make Combine Dir: $fullsess/$sigavgscandir already exists  ...using it"
      set page $sigavgscandir
      set mpage [manglepath $page]
    }
    $nbwin raise $mpage
    set iscandir $page
    set f [$nbwin subwidget $mpage]
  }
  set sessionscanlists($page,type) functscan
  set functscanlists($page,sigavgflag) 1

  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la -labelside acrosstop -background $bgcol -padx 10 \
     -label "3D Stats Combine Scan Directory" \
     -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2   ;# newpkgtix internal ugh
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  # default missing parms (N.B.: overwritten using firstdir at COMBINE time)
  foreach parm {paintext brightness allverticesflag preclustfthr clustarea} {
    if ![info exists functscanlists($page,$parm)] {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }
  if ![info exists functscanlists($page,sigtoavgdirs)] {
    set functscanlists($page,sigtoavgdirs) {}
  }
  if ![info exists functscanlists($page,sigtoavgrevs)] {
    set functscanlists($page,sigtoavgrevs) {}
  }
  if ![info exists functscanlists($page,sigoperation)] {
    set functscanlists($page,sigoperation) phaseaverage
  }
  if ![info exists functscanlists($page,smoothsteps3d)] {
    set functscanlists($page,smoothsteps3d) 0
  }
  if ![info exists functscanlists($page,sigavgoffset)] {
    set functscanlists($page,sigavgoffset) 0.0
  }

  frame $f.sp1 -height 7 -bg $bgcol
  label $f.a -bg $bgcol -font $tfont \
   -text " Fourier-Analyzed or Random Block-Analyzed\n\
           3D Scan Dirs to Combine (new 'scan' made here)"
  frame $f.sp2 -height 7 -bg $bgcol

  # available dirs
  frame $f.b -bg $bgcol
  frame $f.b.l -bg $bgcol
  frame $f.b.l.sp3 -height 16 -bg $bgcol
  label $f.b.l.l -bg $bgcol -font $tfont -text "Select to Add:"
  frame $f.b.m -bg $bgcol
  label $f.b.m.l -bg $bgcol -font $ifontb -text "   Scan Directory"
  set sigtoavgcombo($page) $f.b.m.cbx1
  tixComboBox $f.b.m.cbx1 -dropdown true \
    -command "cbx:select_sigtoavgdir $page" -editable true -listwidth 278 \
    -options "label.width 0 label.anchor e
              entry.width 14
              listbox.height 16" ;# listbox.width 35
  frame $f.b.r -bg $bgcol
  label $f.b.r.l -bg $bgcol -font $ifontb -text " 3D Stat Image Prefix"
  entry $f.b.r.e -width 18 -textvariable sigtoavgbfloatstem \
    -state disabled -bg $entbgcol -selectbackground $selbgcol \
    -highlightbackground $bgcol

  # bottom part of panel
  frame $f.c -bg $bgcol
  frame $f.c.l -bg $bgcol

  # checklist of currently selected dirs-to-combine
  label $f.c.l.la -bg $bgcol -font $tfont \
   -text "<Backspace> to Omit Scan \n<Return> to Reverse Phase"
  set sigtoavgckwidget($page) $f.c.l.cklist  ;# save in array
  tixCheckList $f.c.l.cklist -scrollbar auto -height 160 -width 200 \
     -options "hlist.selectBackground $selbgcol" -bg $bgcol \
     -highlightbackground $bgcol \
     -command "cklist1:select $sigtoavgckwidget($page) $page" ;# appends sel
  $f.c.l.cklist subwidget hlist config -font $hfont  ;# newpkgtix
  set sigtoavghlist($page) [$f.c.l.cklist subwidget hlist]  ;# save in array
  $sigtoavghlist($page) config -bd 2 -relief groove -highlightbackground $bgcol
  $sigtoavghlist($page) config -header true -indent 17 -font $hfont \
    -selectmode single -browsecmd "cklist1:browse" -separator "!" ;#appends sel
  set hstyle [tixDisplayStyle text -refwindow $sigtoavghlist($page) \
    -padx 8 -pady 2 -font $tfont]
  $f.c.l.cklist subwidget hsb config -highlightbackground $bgcol
  $f.c.l.cklist subwidget vsb config -highlightbackground $bgcol
  $sigtoavghlist($page) header create 0 \
    -itemtype text -text "Rev--ScansToCombine" -style $hstyle
  if [llength $functscanlists($page,sigtoavgdirs)] {
    foreach dir $functscanlists($page,sigtoavgdirs) {
      $sigtoavghlist($page) add $dir -itemtype imagetext -text $dir
      set index [lsearch -exact $functscanlists($page,sigtoavgdirs) $dir]
      set revstate [lindex $functscanlists($page,sigtoavgrevs) $index]
      $sigtoavgckwidget($page) setstatus $dir $revstate
    }
  }
  bind $sigtoavghlist($page) <BackSpace> "omitsigtoavgdir $page"
  bind $sigtoavghlist($page) <Delete>    "omitsigtoavgdir $page"

  # operation and smooth
  frame $f.c.r -bg $bgcol
  tixSelect $f.c.r.op -allowzero false -radio true -label "Combine Operation" \
    -labelside top -orientation vertical -bg $bgcol -command \
    "select_sigoperation $sigtoavgckwidget($page) $page" ;# appends butt,state
  foreach but "phaseaverage phasecancel fullphavgsig" {
    # TODO: reintate/reactivate old combine non-complex?
    if {$but == "phaseaverage"} { set btext "vect avg complex sigs" }
    if {$but == "phasecancel"}  { set btext "phasecancel 2 cpx sigs" }
    if {$but == "fullphavgsig"} { set btext "vect avg full FT's, do sig" }
    $f.c.r.op add $but -text $btext -font $hfont -width 17 -bg $bgcol -pady 1
  }
  $f.c.r.op config -disablecallback true
  $f.c.r.op config -variable functscanlists($page,sigoperation)
  $f.c.r.op config -disablecallback false
  $f.c.r.op subwidget label config -anchor center

  tixLabelEntry $f.c.r.a -label "Phase Offset\n(cyc=1.0, before rev)" \
    -labelside top \
    -options "entry.textVariable functscanlists($page,sigavgoffset)"
  $f.c.r.a subwidget label config -width 19
  tixLabelEntry $f.c.r.b -label "Smooth Steps (3D)" -labelside top \
    -options "entry.textVariable functscanlists($page,smoothsteps3d)"
  $f.c.r.b subwidget label config -width 19
  tixLabelEntry $f.c.r.c -label "Surf to Sample 3Ddata" -labelside top \
    -options "entry.textVariable functscanlists($page,paintext)"
  $f.c.r.c subwidget label config -width 19   ;# controls entry width

  pack $f.sp1 $f.a $f.sp2 $f.b $f.c -side top -padx 10 -pady 2
  pack $f.b.l $f.b.m $f.b.r -side left
  pack $f.c.l $f.c.r -side left -pady 5
  pack $f.b.l.sp3 $f.b.l.l $f.b.m.l $f.b.m.cbx1 $f.b.r.l $f.b.r.e \
    -side top -anchor w
  pack $f.c.l.la -side top
  pack $f.c.l.cklist -side top -padx 10
  pack $f.c.r.op -side top -padx 5 -pady 8
  pack $f.c.r.a -side top -padx 10 -pady 8
  #pack $f.c.r.b -side top -padx 20 -pady 8  ;# omit rarely-used smooth 3D
  pack $f.c.r.c -side top -padx 10 -pady 8

  if {$mkdirflag} { findsigavgfuncts $page }
  set prevpage $currpage
  set currpage $page
  update idletasks
  update    ;# else panel unfinished when called by runpanel
}

### on sigtoavgdirs cklist browse
proc cklist1:browse { dir } {
  global sigtoavgdir
  set sigtoavgdir $dir
}

### on sigtoavgdirs cklist select
proc cklist1:select { cklist page dir } {
  global functscanlists
  set status [$cklist getstatus $dir]
  set index [lsearch -exact $functscanlists($page,sigtoavgdirs) $dir]
  set functscanlists($page,sigtoavgrevs) \
    [lreplace $functscanlists($page,sigtoavgrevs) $index $index $status]
}

### on change sig combine operation
proc select_sigoperation { cklist page operation selected } {
  global functscanlists
  if {$selected} {
    set status off  ;# reinstate checkboxes off
    if {$operation == "phasecancel"} {
      confirmalert "UNDER CONSTRUCTION: test if 1 or 2 reversed"
      set status none   ;# remove irrelevant-for-phcancel checkboxes
      set functscanlists($page,sigavgoffset) 0.0
    }
    foreach sigtoavgdir $functscanlists($page,sigtoavgdirs) {
      $cklist setstatus $sigtoavgdir $status
    }
  }
}

### on change raw combine operation
proc select_rawoperation { page operation selected } {
}

### Make SurfAvg Dir button command--make one notebook page of widgets
proc addsurfavgscan { nbwin mkdirflag } {
  global env session iscandir
  global bgcol selcol selbgcol tfont ifontb hfont
  global currpage prevpage 
  global surfavgdir newsurfavgdir
  global sessionscombo
  global sesstoavgcombo surftoavgcombo surftoavgwfileprefcombo
  global surftoavgckwidget surftoavghlist 
  global sessionscanlists functscanlists

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page

  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "sphavgscan" } {
    confirmalert "this is a Cross Session Spherical Avg:\n\nuse CrossSessTools"
    return
  }
  if {$mkdirflag} {
    set surfavgscandir $newsurfavgdir
    set fullsess $env(FUNCTIONALS_DIR)/$session
    if [string match "* *" $surfavgscandir] {
      confirmalert " Make Combine Dir: remove spaces\n\
                     from directory name:\n\n    \"$surfavgscandir\"\n\n\
                     and try again"
      return
    }
    if ![file exists $fullsess/$surfavgscandir] {
      if ![canwriteormakefile $fullsess/$surfavgscandir] {
        confirmalert "Make Combine Dir: can't create: $fullsess/$surfavgscandir"
        return
      }
      if [string match "*$surfavgdir" "$newsurfavgdir"] {
        if ![okreplace "" \
           " Make Combine Dir: OK to use not-very-informative\n\
             default name ($surfavgdir) for new scandir?\n\n\
             (or Cancel, add informative suffix, try again)" "OK"] { return }
      }
      mkdirlog $fullsess/$surfavgscandir
      set page $surfavgscandir
      set mpage [manglepath $page]
      $nbwin subwidget hlist add $mpage -text $page -at 0   ;# put first
      $nbwin add $mpage -raisecmd "set iscandir $page; findsurfavgfuncts $page"
      $nbwin subwidget $mpage config -bg $bgcol
    } else {
      confirmalert \
      "Make Combine Dir: $fullsess/$surfavgscandir already exists  ...using it"
      set page $surfavgscandir
      set mpage [manglepath $page]
    }
    $nbwin raise $mpage
    set iscandir $page
    set f [$nbwin subwidget $mpage]
  }
  set sessionscanlists($page,type) functscan
  set functscanlists($page,surfavgflag) 1

  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la -labelside acrosstop -background $bgcol -padx 10 \
     -label "Surface Stats Combine Scan Directory" \
     -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  if ![info exists functscanlists($page,surftoavgbigstems)] {
    set functscanlists($page,surftoavgbigstems) {}
  }
  if ![info exists functscanlists($page,surftoavgrevs)] {
    set functscanlists($page,surftoavgrevs) {}
  }
  if ![info exists functscanlists($page,surfoperation)] {
    set functscanlists($page,surfoperation) phaseavg-pol
  }
  if ![info exists functscanlists($page,surfavgoffset)] {
    set functscanlists($page,surfavgoffset) $functscanlists(def,surfavgoffset)
  }
  if ![info exists functscanlists($page,surfavgscriptflag)] {
    set functscanlists($page,surfavgscriptflag) \
         $functscanlists(def,surfavgscriptflag)
  }
  if ![info exists functscanlists($page,mksurfavgscriptflag)] {
    set functscanlists($page,mksurfavgscriptflag) \
         $functscanlists(def,mksurfavgscriptflag)
  }
  if ![info exists functscanlists($page,paintext)] {
    set functscanlists($page,paintext) $functscanlists(def,paintext)
  }
  if ![info exists functscanlists($page,rh,wfile)] {
    set functscanlists($page,rh,wfile) -runsurfcombine-
  }
  if ![info exists functscanlists($page,lh,wfile)] {
    set functscanlists($page,lh,wfile) -runsurfcombine-
  }
  frame $f.sp1 -height 7 -bg $bgcol
  label $f.a -bg $bgcol -font $tfont \
   -text " Surface Statistics (possibly cross-session) to Combine\n\
           Painted Inputs All On Same Surface (new 'scan' made here)"
  frame $f.sp2 -height 7 -bg $bgcol

  # sessions
  set sesstoavgcombo($page) $f.cbx0
  tixComboBox $f.cbx0 \
    -label "Functional Session to Choose From:" -dropdown true \
    -command "cbx:select_sesstoavgdir $nbwin $page" -editable true \
    -variable sesstoavgdir -listwidth 180 \
    -options "label.width 0 label.anchor e
              entry.width 14
              listbox.height 30" ;# listbox.width 17 -> 21
  foreach sess [$sessionscombo subwidget listbox get 0 end] {
    $f.cbx0 insert end $sess
  }
  $f.cbx0 config -value $session

  # scandirs,wfiles
  frame $f.b -bg $bgcol
  frame $f.b.l -bg $bgcol
  frame $f.b.l.sp3 -height 16 -bg $bgcol
  label $f.b.l.l -bg $bgcol -font $tfont -text "Select Both:"
  frame $f.b.m -bg $bgcol
  label $f.b.m.l -bg $bgcol -font $ifontb -text "   Scan Directory"
  set surftoavgcombo($page) $f.b.m.cbx1
  tixComboBox $f.b.m.cbx1 -dropdown true \
    -command "cbx:select_surftoavgdir $nbwin $page" -editable true \
    -variable surftoavgdir -listwidth 187 \
    -options "label.width 0 label.anchor e
              entry.width 15
              listbox.height 10" ;# listbox.width 22
  $f.b.m.cbx1 config -value ""
  frame $f.b.r -bg $bgcol
  label $f.b.r.l -bg $bgcol -font $ifontb -text "   Vertex List Prefix"
  set surftoavgwfileprefcombo($page) $f.b.r.cbx2
  tixComboBox $f.b.r.cbx2 -dropdown true \
    -command "cbx:select_surftoavgwfilepref $nbwin $page" -editable true \
    -variable surftoavgbfloatstem -listwidth 187 \
    -options "label.width 0 label.anchor e
              entry.width 15
              listbox.height 10" ;# listbox.width 22
  $f.b.r.cbx2 config -value ""

  # bottom part of the panel
  frame $f.c -bg $bgcol
  frame $f.c.l -bg $bgcol
  frame $f.c.r -bg $bgcol

  # checklist of currently selected wfiles to combine
  label $f.c.l.la -bg $bgcol -font $tfont \
   -text "<Backspace> to Omit, <Return> to Reverse"
  set surftoavgckwidget($page) $f.c.l.cklist
  tixCheckList $f.c.l.cklist -scrollbar auto -height 200 -width 275 \
     -options "hlist.selectBackground $selbgcol" -bg $bgcol \
     -highlightbackground $bgcol \
     -command "cklist2:select $surftoavgckwidget($page) $page" ;# appends sel
  $f.c.l.cklist subwidget hlist config -font $hfont  ;# newpkgtix
  set surftoavghlist($page) [$f.c.l.cklist subwidget hlist]  ;# save in array
 $surftoavghlist($page) config -bd 2 -relief groove -highlightbackground $bgcol
  $surftoavghlist($page) config -header true -indent 15 -font $hfont \
    -selectmode single -browsecmd "hlist5:browse" -separator "!"
  set hstyle [tixDisplayStyle text -refwindow $surftoavghlist($page) \
    -padx 8 -pady 2 -font $tfont]
  $f.c.l.cklist subwidget hsb config -highlightbackground $bgcol
  $f.c.l.cklist subwidget vsb config -highlightbackground $bgcol

  $surftoavghlist($page) header create 0 -itemtype text \
    -text "Rev--Fullpath Paintfiles to Combine (DEL)" -style $hstyle
  if [llength $functscanlists($page,surftoavgbigstems)] {
    foreach dir $functscanlists($page,surftoavgbigstems) {
      $surftoavghlist($page) add $dir -itemtype imagetext -text $dir
      set index [lsearch -exact $functscanlists($page,surftoavgbigstems) $dir]
      set revstate [lindex $functscanlists($page,surftoavgrevs) $index]
      $surftoavgckwidget($page) setstatus $dir $revstate
    }
  }
  bind $surftoavghlist($page) <BackSpace> "omitsurftoavgdir $page"
  bind $surftoavghlist($page) <Delete>    "omitsurftoavgdir $page"

  # offset
  tixLabelEntry $f.c.r.e -label "Offset (cyc=1.0)" -labelside top \
    -options "entry.textVariable functscanlists($page,surfavgoffset)"
  $f.c.r.e subwidget label config -width 14

  # combine
  tixSelect $f.c.r.op -allowzero false -radio true -label "Combine Oper" \
    -labelside top -orientation vertical -bg $bgcol
  foreach but "realaverage phaseavg-ecc phaseavg-pol phaseavg-two" {
    $f.c.r.op add $but -text $but -font $hfont -bg $bgcol -padx 2 -pady 1
  }
  if {$functscanlists($page,surfoperation) == "phaseaverage"} { ;# hack compat 
    set functscanlists($page,surfoperation) phaseavg-pol
  }
  $f.c.r.op config -variable functscanlists($page,surfoperation)

  checkbutton $f.c.r.ck1 -selectcolor $selcol -bg $bgcol -text "Use Script " \
  -highlightbackground $bgcol -variable functscanlists($page,surfavgscriptflag)
  checkbutton $f.c.r.ck2 -selectcolor $selcol -bg $bgcol -text "New Script" \
    -highlightbackground $bgcol -command "cknewsurfscript $page" \
    -variable functscanlists($page,mksurfavgscriptflag)

  # feedback
  tixLabelEntry $f.d -label "Painted VertexList File (rh): " -labelside left \
    -options "entry.textVariable functscanlists($page,rh,wfile) entry.width 25"
  tixLabelEntry $f.e -label "Painted VertexList File (lh): " -labelside left \
    -options "entry.textVariable functscanlists($page,lh,wfile) entry.width 25"

  $f.d subwidget label config -width 24
  $f.e subwidget label config -width 24
  pack $f.sp1 $f.a $f.sp2 $f.cbx0 $f.b $f.c $f.d $f.e \
    -side top -padx 10 -pady 2
  pack $f.c -pady 10
  pack $f.b.l $f.b.m $f.b.r -side left
  pack $f.c.l $f.c.r -side left
  pack $f.b.l.sp3 $f.b.l.l $f.b.m.l $f.b.m.cbx1 $f.b.r.l $f.b.r.cbx2 \
    -side top -anchor w
  pack $f.c.l.la -side top
  pack $f.c.l.cklist -side top -padx 5 -pady 5
  pack $f.c.r.e -side top -padx 5 -pady 5
  pack $f.c.r.op -side top -padx 5 -pady 5
  pack $f.c.r.ck1 $f.c.r.ck2 -side top -padx 5 -pady 0

  if {$mkdirflag} { findsurfavgfuncts $page }

  set prevpage $currpage
  set currpage $page
  update idletasks
}

### on change reverse checkbox of selected surface average vertex list prefix
proc cklist2:select { cklist page bigstem } {
  global functscanlists
  set status [$cklist getstatus $bigstem]
  set index [lsearch -exact $functscanlists($page,surftoavgbigstems) $bigstem]
  set functscanlists($page,surftoavgrevs) \
    [lreplace $functscanlists($page,surftoavgrevs) $index $index $status]
}

### on select surface average vertex list prefix
proc hlist5:browse { bigstem } {
  global surftoavgbigstem
  set surftoavgbigstem $bigstem
}

### on change state of New Script button
proc cknewsurfscript { page } {
  global functscanlists
  if {$functscanlists($page,mksurfavgscriptflag)} {
    set functscanlists($page,surfavgscriptflag) 1
  }
}

### Make Fieldsign Dir button command--make one notebook page of widgets
proc addfieldscan { nbwin mkdirflag } {
  global env session iscandir
  global bgcol selbgcol selcol tfont ifontb
  global currpage prevpage 
  global fsdir newfsdir
  global sessionscanlists functscanlists renderscanlists
  global eccenscombo polarscombo eccenwfileprefscombo polarwfileprefscombo
  global partialpatch endflatext

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page

  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "sphavgscan" } {
    confirmalert "this is a Cross Session Spherical Avg:\n\nuse CrossSessTools"
    return
  }
  if {$mkdirflag} {
    if { [string match   fs* $newfsdir] ||
         [string match */fs* $newfsdir] } {
      set fsscandir $newfsdir
    } else {
      confirmalert \
        "Fieldsign: new fieldsign (sub)directory must start with fs"
      return
    }
    set fullsess $env(FUNCTIONALS_DIR)/$session
    if [string match "* *" $fsscandir] {
      confirmalert " Fieldsign: remove spaces\n\
                     from directory name:\n\n    \"$fsscandir\"\n\n\
                     and try again"
      return
    }
    if ![file exists $fullsess/$fsscandir] {
      mkdirlog $fullsess/$fsscandir
      set page $fsscandir
      set mpage [manglepath $page]
      $nbwin subwidget hlist add $mpage -text $page -at 0   ;# put first
      $nbwin add $mpage -raisecmd "set iscandir $page; findretins $page"
      $nbwin subwidget $mpage config -bg $bgcol
    } else {
      confirmalert \
        "Make Fieldsign Dir: $fullsess/$fsscandir already exists  ...using it"
      set page $fsscandir
      set mpage [manglepath $page]
    }
    $nbwin raise $mpage
    set iscandir $page
    set f [$nbwin subwidget $mpage]
  }
  set sessionscanlists($page,type) fsscan
  set functscanlists($page,stattype) real

  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la -labelside acrosstop -background $bgcol -padx 10 \
     -label "Fieldsign/Borders Directory (no need to PAINT)" \
     -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  foreach parm { smoothstepsfs polardir eccendir bfloatpatt fspatchext \
                 smoothstepsbd retinseedlabel retinvtxfrac maxretinsearch \
                 minretindist retinprogressflag} {
    if ![info exists functscanlists($page,$parm)] {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }
  if {$functscanlists($page,fspatchext) == "-unset-"} {
    set functscanlists($page,fspatchext) $partialpatch.$endflatext
  }

  # select_ecc/pol gets stems from uniq+noinfix wfile prefs, save in arrays
  frame $f.sp0 -height 10 -bg $bgcol
  label $f.a -bg $bgcol -font $tfont -text "Eccentricity Scan    "
  frame $f.b -bg $bgcol
  frame $f.b.l -bg $bgcol
  label $f.b.l.l -bg $bgcol -font $ifontb -text "    Scan Directory"
  set eccenscombo($page) $f.b.l.cbx1
  tixComboBox $f.b.l.cbx1 -dropdown true \
    -command "cbx:select_eccen $page" -editable true \
    -variable functscanlists($page,eccendir) -listwidth 243 \
    -options "label.width 0
              entry.width 20
              listbox.height 10" ;# listbox.width 30
  frame $f.b.r -bg $bgcol
  label $f.b.r.l -bg $bgcol -font $ifontb -text "    Vertex List Prefix"
  set eccenwfileprefscombo($page) $f.b.r.cbx2
  tixComboBox $f.b.r.cbx2 \
    -command "cbx:select_eccenwfilepref" -editable true -dropdown true \
    -variable renderscanlists($page,eccenstem) -listwidth 243 \
    -options "label.width 0
              entry.width 20
              listbox.height 10" ;# listbox.width 30
  frame $f.sp1 -height 10 -bg $bgcol
  label $f.c -bg $bgcol -font $tfont -text "Polar Angle Scan    "
  frame $f.d -bg $bgcol
  frame $f.d.l -bg $bgcol
  label $f.d.l.l -bg $bgcol -font $ifontb -text "    Scan Directory"
  set polarscombo($page) $f.d.l.cbx3
  tixComboBox $f.d.l.cbx3 -dropdown true \
    -command "cbx:select_polar $page" -editable true \
    -variable functscanlists($page,polardir) -listwidth 243 \
    -options "label.width 0
              entry.width 20
              listbox.height 10" ;# listbox.width 30
  frame $f.d.r -bg $bgcol
  label $f.d.r.l -bg $bgcol -font $ifontb -text "    Vertex List Prefix"
  set polarwfileprefscombo($page) $f.d.r.cbx4
  tixComboBox $f.d.r.cbx4 \
    -command "cbx:select_polarwfilepref" -editable true -dropdown true \
    -variable renderscanlists($page,polarstem) -listwidth 243 \
    -options "label.width 0
              entry.width 20
              listbox.height 10" ;# listbox.width 30

  frame $f.sp2 -height 8 -bg $bgcol
  frame $f.sp3 -height 3 -width 350 -bg $bgcol -bd 2 -relief groove
  label $f.e -bg $bgcol -font $tfont \
    -text "Borders by Visual Field Sign (outp -> fs dir)"
  tixLabelEntry $f.f -label "Surf Smoothsteps Before Calc: " -labelside left
  $f.f subwidget entry config -textvariable functscanlists($page,smoothstepsfs)
  tixLabelEntry $f.g -label "Flat Surface for Fieldsign Calc: " -labelside left
  $f.g subwidget entry config -textvariable functscanlists($page,fspatchext)

  frame $f.sp4 -height 8 -bg $bgcol
  frame $f.sp5 -height 3 -width 350 -bg $bgcol -bd 2 -relief groove
  label $f.h -bg $bgcol -font $tfont \
    -text "Borders by Region Growing (outp -> ecc/pol dirs)"
  tixLabelEntry $f.i -label "Surf Smoothsteps Before Calc: " -labelside left
  $f.i subwidget entry config -textvariable functscanlists($page,smoothstepsbd)
  tixLabelEntry $f.j -label "Label for Retin Seeds (rh-, lh-): " -labelside left
  $f.j subwidget entry config -textvariable functscanlists($page,retinseedlabel)
  tixLabelEntry $f.k -label "Search Dist From Seed (mm): " -labelside left
  $f.k subwidget entry config -textvariable functscanlists($page,maxretinsearch)
  tixLabelEntry $f.l -label "RF Dist Below This Marks Repeat: " -labelside left
  $f.l subwidget label config -width 29
  $f.l subwidget entry config -width 12
  #tixLabelEntry $f.l -label "RF Below This Dist Marks Bord: " -labelside left
  $f.l subwidget entry config -textvariable functscanlists($page,minretindist)
 tixLabelEntry $f.m -label "Frac Label Vtxs To Seed (0-1): " -labelside left
 $f.m subwidget entry config -textvariable functscanlists($page,retinvtxfrac)
  checkbutton $f.ck -font $tfont \
    -text "Show Retin Region-Growing (every 200'th seed)" \
    -selectcolor $selcol -bg $bgcol -highlightbackground $bgcol \
    -variable functscanlists($page,retinprogressflag)

  # tix bug: fix mangle 2 if this panel opened after Render panel
  $f.f subwidget label config -width 27  ;# why?
  $f.g subwidget label config -width 27  ;# why?

 pack $f.sp0 $f.a $f.b $f.sp1 $f.c $f.d $f.sp2 $f.sp3 -side top -padx 10 -pady 2
  pack $f.e -side top -padx 10 -pady 12
  pack $f.f $f.g $f.sp4 $f.sp5 -side top -padx 10 -pady 2
  pack $f.h -side top -padx 10 -pady 12
  pack $f.i $f.j $f.k $f.l $f.m $f.ck -side top -padx 10 -pady 2
  pack $f.b.l $f.b.r $f.d.l $f.d.r -side left
  pack $f.b.l.l $f.b.r.l $f.b.l.cbx1 $f.b.r.cbx2 -side top -anchor w
  pack $f.d.l.l $f.d.r.l $f.d.l.cbx3 $f.d.r.cbx4 -side top -anchor w

  if {$mkdirflag} { findretins $page; $eccenscombo($page) invoke }

  set prevpage $currpage
  set currpage $page
  update idletasks    ;# fixes squished bottom buttons on Ubuntu
}

### browse command for Random Block panel
proc hlist3:browse { difforadd } {
  global condnames2difforadd
  set condnames2difforadd $difforadd
}

### load/update condnames-to-calc-diffs-for listbox (cond num from cond name)
proc addcondnames2diff { page } {
  global condnames2difforaddhlist condnames2difforadd condname1 condname2
  global functscanlists diffinfix

  set cn1 $condname1($page)
  set cn2 $condname2($page)
  if {$cn1 == $cn2} {
    confirmalert "Select Condition Name: bad difference: identical conditions"
    return
  }
  if { [lsearch -exact $functscanlists($page,condnames) $cn1] == -1 } {
    confirmalert "Select Condition Name: bad condition: $cn1"
    return
  }
  if { [lsearch -exact $functscanlists($page,condnames) $cn2] == -1 } {
    confirmalert "Select Condition Name: bad condition: $cn2"
    return
  }
  set condnames2difforadd "${cn1}${diffinfix}${cn2}"
  if { [lsearch -exact $functscanlists($page,condnames2difflist) \
        $condnames2difforadd] == -1} {
    lappend functscanlists($page,condnames2difflist) $condnames2difforadd
    $condnames2difforaddhlist($page) add $condnames2difforadd \
      -text $condnames2difforadd
  }
}

### load/update condnames-to-calc-adds-for listbox (cond num from cond name)
proc addcondnames2add { page } {
  global condnames2difforaddhlist condnames2add condname1 condname2
  global functscanlists addinfix

  set cn1 $condname1($page)
  set cn2 $condname2($page)
  if {$cn1 == $cn2} {
    confirmalert "Select Condition Name: bad addition: identical conditions"
    return
  }
  if { [lsearch -exact $functscanlists($page,condnames) $cn1] == -1 } {
    confirmalert "Select Condition Name: bad condition: $cn1"
    return
  }
  if { [lsearch -exact $functscanlists($page,condnames) $cn2] == -1 } {
    confirmalert "Select Condition Name: bad condition: $cn2"
    return
  }
  set condnames2add "${cn1}${addinfix}${cn2}"
  if { [lsearch -exact $functscanlists($page,condnames2addlist) \
        $condnames2add] == -1} {
    lappend functscanlists($page,condnames2addlist) $condnames2add
    $condnames2difforaddhlist($page) add $condnames2add -text $condnames2add
  }
}

### Extern Stats Dir button command--make one notebook page of widgets
proc addextstatscan { nbwin } {
  global env session iscandir
  global statscombo
  global scrwinpackpoint scrwinmultibrik
  global bskippackpoint bskipline
  global bgcol selbgcol hilcol hilbgcol actbgcol ffontb tfont hfont
  global currpage prevpage
  global sessionscanlists functscanlists renderscanlists
  global cmdlog funct2subjbu
  global makingextstatscan

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page

  if { [info exists sessionscanlists($page,type)] && \
       $sessionscanlists($page,type) == "sphavgscan" } {
    confirmalert "this is a Cross Session Spherical Avg:\n\nuse CrossSessTools"
    return
  }
  if [info exists sessionscanlists($page,type)] {
    if {$sessionscanlists($page,type) == "functscan"} {
      set functscanlists($page,extstatfunctims) 1
      confirmalert " Reconfig Funct Scan:\n\n    $page\n\n\
                     to Extern Stats Scan"
    }
  }
  if ![info exists functscanlists($page,extstatfunctims)] {
    set functscanlists($page,extstatfunctims) 0
  }
  set sessionscanlists($page,type) extstatscan
  set functscanlists($page,stattype) real   ;# TODO: accept complex
  set makingextstatscan 1

  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la \
    -label "External 3D Stats Directory" -labelside acrosstop \
    -background $bgcol -padx 10 -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  # bak compat: for old config'd pre-realstatformat scan w/1st action EXTRACT
  if ![info exists functscanlists($page,realstatformat)] {
    set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
    if { [glob -nocomplain $fullscandir/*_000.bfloat] != "" } { ;# req done
      set functscanlists($page,realstatformat) bfloat  ;# def now afnibrik
    }
  }

  # default missing functscanlist parms
  foreach parm { statformat regdat bskip paintext paintdmin paintdmax \
                 paintdstep paintnormop paintnormtype multiprefix multiinfix \
                 clusterrad clustervol allverticesflag realstatformat } {
    if ![info exists functscanlists($page,$parm)] {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }
  if ![info exists functscanlists($page,deconvtype)] {
    set functscanlists($page,deconvtype) fout
  }
  if ![info exists functscanlists($page,bfloatpatt)] {
    set functscanlists($page,bfloatpatt) -selectimageset-
  }
  if ![info exists functscanlists($page,rh,wfile)] {
    set functscanlists($page,rh,wfile) -runpaint-
  }
  if ![info exists functscanlists($page,lh,wfile)] {
    set functscanlists($page,lh,wfile) -runpaint-
  }

  set statscombo($page) $f.cbx1
  tixComboBox $f.cbx1 -label "External Stats Image Set: " -dropdown true \
    -command "cbx:select_statimage $nbwin" -editable true \
    -variable functscanlists($page,extstatfile) -listwidth 315 \
    -options "label.width 27 label.anchor e
              entry.width 30
              listbox.height 20" ;# listbox.width 40
  fixstats $page

  if { [info exists functscanlists($page,statformat)] && \
       $functscanlists($page,statformat) == "brik" } {  ;# backward compat
    set functscanlists($page,statformat) brikmulti
  }
  tixSelect $f.b -allowzero false -radio true -label "Input Stat Format: " \
    -orientation horizontal -command "togglemultibrikpanel $page"
  $f.b subwidget label config -width 16   ;# -options reconfigs others
  $f.b add bfloat -text BFLOAT -width 5 -bg $bgcol -pady 1 \
     -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $f.b add mgzsingle -text MGZ -width 3 -bg $bgcol -pady 1 \
     -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $f.b add briksingle -text AFNI-SINGLE -width 8 -bg $bgcol -pady 1 \
     -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $f.b add brikmulti -text AFNI-MULTI -width 7 -bg $bgcol -pady 1 \
     -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $f.b config -variable functscanlists($page,statformat)

  # page-specific tix scrolled window for variable length multibrik parms
  set scrwinpackpoint($page) $f.b
  set scrwinmultibrik($page) \
    [tixScrolledWindow $f.scrwin -height 250 -scrollbar auto] ;# auto:newpkgtix
  set scrwinwidget [$scrwinmultibrik($page) subwidget window]
  $scrwinwidget config -bg $bgcol ;#-bd 2 -relief sunken (relief under frame)
  $scrwinmultibrik($page).f1 config -bd 2 -relief sunken ;# kinda internal
  $scrwinmultibrik($page).f1 config -highlightbackground $bgcol
  $scrwinmultibrik($page) subwidget vsb config -highlightbackground $bgcol
  set scrwin1 [frame $scrwinwidget.f1]    ;# read header, thresh
  set scrwin2 [frame $scrwinwidget.f2]    ;# cluster, infix
  set scrwin3 [frame $scrwinwidget.f3]    ;# this one destroyed/remade
  pack $scrwin1 $scrwin2 $scrwin3 -side top -padx 0
  $scrwin1 config -bg $bgcol
  $scrwin2 config -bg $bgcol
  $scrwin3 config -bg $bgcol
  button $scrwin1.bu -text "READ HEADER" -font $ffontb -pady 2 -padx 3 \
    -command "readmultibrikheader $page $scrwin3" -highlightbackground $bgcol
  tixLabelEntry $scrwin1.le1 \
    -label "Clust (units=vox):  connected=" -labelside left \
    -options "entry.textVariable functscanlists($page,clusterrad)"
  $scrwin1.le1 subwidget entry config -width 4
  $scrwin1.le1 subwidget label config -width 27 ;# 18->"Cluster:   rad (mm):"
  tixLabelEntry $scrwin1.le2 -label "minvol=" -labelside left \
    -options "entry.textVariable functscanlists($page,clustervol)"
  $scrwin1.le2 subwidget entry config -width 4
  $scrwin1.le2 subwidget label config -width 7 ;# 11->"vol (mm^3):"
  tixLabelEntry $scrwin2.le0 -label "Prefix:" -labelside left \
    -options "entry.textVariable functscanlists($page,multiprefix)"
  $scrwin2.le0 subwidget entry config -width 8
  $scrwin2.le0 subwidget label config -width 5 
  tixLabelEntry $scrwin2.le1 -label "Infix:" -labelside left \
    -options "entry.textVariable functscanlists($page,multiinfix)"
  $scrwin2.le1 subwidget entry config -width 8
  $scrwin2.le1 subwidget label config -width 5
 tixLabelEntry $scrwin2.le2 -label "Global MaskThresh <Ret>:" -labelside left \
    -options "entry.textVariable functscanlists($page,globalmaskthresh)"
  $scrwin2.le2 subwidget entry config -width 4
  $scrwin2.le2 subwidget label config -width 23
 bind [$scrwin2.le2 subwidget entry] <Return> "updatemaskthresh $scrwin3 $page"
  pack $scrwin1.bu $scrwin1.le1 $scrwin1.le2 $scrwin2.le0 $scrwin2.le1 \
    $scrwin2.le2 -side left -padx 0
  set valuefilelist [getsortedvaluefilelist $page]
  if [llength $valuefilelist] {
    makemultibrikpanel $page $scrwin3 $valuefilelist
  }

  set bskippackpoint($page) $f.b    ;# save for repack
  set bskipline($page) $f.b2
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  set selectedimage $fullscandir/\$functscanlists($page,extstatfile)  ;# wait
  tixLabelEntry $bskipline($page) -label "Briks to Skip (AFNI-SINGLE): " \
    -labelside left -options "entry.textVariable functscanlists($page,bskip)"
  button $f.b2.bu -text "READ HEADER" -font $ffontb -pady 2 -padx 4 \
    -command "readheader $selectedimage $page functscan" \
    -highlightbackground $bgcol
  pack $f.b2.bu

  frame $f.b3 -bg $bgcol
  tixSelect $f.b3.sel -allowzero true -radio true \
    -label "Output Stat Format: " \
    -orientation horizontal -options "label.width 18"
  foreach but "bfloat afnibrik" {
    $f.b3.sel add $but -text $but -font $hfont -width 3 -bg $bgcol -pady 1
  }
  $f.b3.sel config -variable functscanlists($page,realstatformat)

  tixLabelEntry $f.c -label "Converted Stats Image Set: " -labelside left \
    -options "entry.textVariable functscanlists($page,bfloatpatt)"
  tixLabelEntry $f.e -label "Slice Count: " -labelside left \
    -options "entry.textVariable functscanlists($page,slices)"
  tixLabelEntry $f.f -label "In Plane Pixel (mm): " -labelside left \
    -options "entry.textVariable functscanlists($page,inplane)"
  tixLabelEntry $f.g -label "Slice Thickness (mm): " -labelside left \
    -options "entry.textVariable functscanlists($page,thickness)"
  tixLabelEntry $f.h -label "Funct->Struct Transform File: " -labelside left \
    -options "entry.textVariable functscanlists($page,regdat)"
  #tixLabelEntry $f.i -label "Surface for Sampling 3D Data: " -labelside left \
  #  -options "entry.textVariable functscanlists($page,paintext)"
  tixLabelEntry $f.i -label "Surface for Sampling 3D Data: " -labelside left
  $f.i subwidget entry config -textvariable functscanlists($page,paintext)

  frame $f.j -bg $bgcol
  label $f.j.la1 -text "NormSearch:" -bg $bgcol -font $tfont   ;# -width 12
  tixSelect $f.j.s0 -allowzero false -radio true -orientation horizontal \
    -command "select_paintnormtype $page" ;# appends butt,state
  foreach but "mm frac" {
    $f.j.s0 add $but -text $but -font $hfont \
       -width 0 -bg $bgcol -padx 0 -pady 0 \
       -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  }
  $f.j.s0 config -variable functscanlists($page,paintnormtype)
  $f.j.s0 subwidget label config -bd 0 -padx 0
  tixLabelEntry $f.j.le0 -label "mn/mx: " -labelside left \
    -options "entry.textVariable functscanlists($page,paintdmin)"
  tixLabelEntry $f.j.le1 -label "" -labelside left \
    -options "entry.textVariable functscanlists($page,paintdmax)"
  $f.j.le0 subwidget entry config -width 3
  $f.j.le0 subwidget label config -width 8 -padx 0
  $f.j.le1 subwidget entry config -width 3
  $f.j.le1 subwidget label config -width 0 -padx 0
  tixLabelEntry $f.j.le2 -label "dx:" -labelside left \
    -options "entry.textVariable functscanlists($page,paintdstep)"
  $f.j.le2 subwidget entry config -width 4
  $f.j.le2 subwidget label config -width 3 -padx 0
  tixSelect $f.j.s1 -allowzero false -radio true -orientation horizontal
  foreach but "max avg min" {
    if {$but == "max"} { set btext mx }
    if {$but == "avg"} { set btext av }
    if {$but == "min"} { set btext mn }
    $f.j.s1 add $but -text $btext -font $hfont \
       -width 2 -bg $bgcol -padx 0 -pady 0 \
       -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  }
  $f.j.s1 config -variable functscanlists($page,paintnormop) \
    -command "select_paintnormop $page" ;# appends butt,state

  tixLabelEntry $f.k -label "Painted VertexList File (rh): " -labelside left \
    -options "entry.textVariable functscanlists($page,rh,wfile)"
  tixLabelEntry $f.l -label "Painted VertexList File (lh): " -labelside left \
    -options "entry.textVariable functscanlists($page,lh,wfile)"

  foreach wid {c e f g h i k l} { ;# tweak labels
    $f.$wid subwidget label config -width 26
    $f.$wid subwidget entry config -width 25
  }
  $f.b2 subwidget entry config -width 12
  $f.b2 subwidget label config -width 27  ;# why?
  pack $f.cbx1 $f.b -side top -padx 10 -pady 2
  if {$functscanlists($page,statformat) == "brikmulti"} {
    pack $scrwinmultibrik($page) -side top   ;# -expand yes -fill both
  }
  if {$functscanlists($page,statformat) == "briksingle" || \
      $functscanlists($page,statformat) == "mgzsingle"} {
    pack $bskipline($page) -side top
  }
  pack $f.b3 $f.b3.sel $f.c $f.e $f.f $f.g $f.h $f.i $f.j $f.k $f.l \
    -side top -padx 10 -pady 2
  pack $f.j.la1 $f.j.s0 $f.j.le0 $f.j.le1 $f.j.le2 $f.j.s1 -side left
  set makingextstatscan 0
  update idletasks
}

### sort hashed array names into subbrik order using value of subbrikindex
proc getsortedvaluefilelist { page } {
  global functscanlists
  foreach index [array names functscanlists $page,*,subbrikindex] {
    set indexarr($functscanlists($index)) $index   ;# new array index <- value
  }
  set valuefilelist ""
  foreach index [lsort [array names indexarr]] {  ;# construct valuefile index
    set sortedindex [string trimright $indexarr($index) subbrikindex]valuefile
    lappend valuefilelist $functscanlists($sortedindex)
  }
  return $valuefilelist  ;# maybe empty
}

### READ HEADER button in multibrik scrollwin--check/warn,destroy/unset,remake
proc readmultibrikheader { page scrwin } {
  global env session iscandir functscanlists

  set iscandir $page
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  set inbrik $fullscandir/$functscanlists($page,extstatfile)
  set inheader [file rootname $inbrik].HEAD
  if { [file extension $inbrik] != ".BRIK"} {
    confirmalert "BRIK Stats: bad suffix on input brik (not .BRIK): $inbrik"
    return
  }
  if ![file exists $inbrik] {
    confirmalert "BRIK Stats: input AFNI brik not found: $inbrik"
    return
  }
  if ![file exists $inheader] {
    confirmalert "BRIK Stats: input AFNI header not found: $inheader"
    return
  }

  set valuefilelist ""
  foreach index [array names functscanlists $page,*,valuefile] {
    lappend valuefilelist $functscanlists($index)
  }
  if [llength $valuefilelist] {
    if ![okreplace "" "BRIK Stats: already configured--Clear/Re-Read?" \
         "Clear/Re-Read"] {
      confirmalert "BRIK Stats: configuration not altered"
      return
    }
    if [winfo exists $scrwin] { destroy $scrwin }
    set multivars "[array names functscanlists $page,*,extractflag] \
                   [array names functscanlists $page,*,clusterflag] \
                   [array names functscanlists $page,*,valuefile] \
                   [array names functscanlists $page,*,subbrikindex] \
                   [array names functscanlists $page,*,maskfile] \
                   [array names functscanlists $page,*,maskthresh] \
                   [array names functscanlists $page,*,bfloatstem]"
    foreach var $multivars { unset functscanlists($var) }    
  } else {
    if [winfo exists $scrwin] { destroy $scrwin }
  }

  set briklabellist [readmultibriklabels $inheader]
  set briklabels [llength $briklabellist]
  if {$briklabels > 60} {
    if ![okreplace "" \
        " BRIK Stats: Large number of subbriks ($briklabels) in:\n\n    \
          [file tail $inbrik]\n\n\
          It may not be a stats BRIK.  If it isn't,\n\
          Cancel and select a different BRIK, or\n\
          use \"Unset Dir\" to ignore this directory.\n\
          next time.\n\n\
          Read Anyway?  (may take a while)" "Read Anyway"] {
      return
    }
  }
  # write labels read from HEAD (valuefiles) into saveable vars, default others
  set i 0
  set valuefilelist ""  ;# start again
  foreach briklabel $briklabellist {
    set functscanlists($page,$briklabel,extractflag)       1  ;# unclick
    set functscanlists($page,$briklabel,clusterflag)       1  ;# new 6 ops
    set functscanlists($page,$briklabel,valuefile)      $briklabel
    set functscanlists($page,$briklabel,subbrikindex) [format "#%02d" $i]
    set functscanlists($page,$briklabel,maskfile)       "-unset-"
    set functscanlists($page,$briklabel,maskthresh)        0.01
    set functscanlists($page,$briklabel,bfloatstem)     "-unset-"
    if ![string match "*t^?_Coef" $briklabel] {  ;# skip t^1_Coef (keep _Coef)
      lappend valuefilelist $briklabel
    }
    incr i
  }
  makemultibrikpanel $page $scrwin $valuefilelist
}

### read HEAD, get full labels, fix quotes/space/brack/hash, uniq, return list
proc readmultibriklabels { header } {
  global wasbrak washash

  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  set rawlabels ""
  foreach line $lines {
    if [string match *BRICK_LABS* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set trimmedline [string trimright [string trimleft $line '] ~]
      set rawlabels [split $trimmedline ~]
      set i 0
    }
  }

  ### AFNI 3dDeconvolve changed BRICK_LABS: "ba LC[0] coef" -> "ba_GLT#0_Coef"
  ## old: 'ba LC[0] coef~ba F-stat~odb LC[0] coef~odb F-stat~hm LC[0] coef~hm F-stat~db LC[0] coef~db F-stat~ohm LC[0] coef~ohm F-stat~hm-VS-ohm LC[0] coef~hm-VS-ohm F-stat~db-VS-odb LC[0] coef~db-VS-odb F-stat~ohm-VS-odb LC[0] coef~ohm-VS-odb F-stat~hm-VS-db LC[0] coef~hm-VS-db F-stat~Full F-stat~
  ## new: 'Full_Fstat~ba_GLT#0_Coef~ba_GLT_Fstat~db_GLT#0_Coef~db_GLT_Fstat~hm_GLT#0_Coef~hm_GLT_Fstat~odb_GLT#0_Coef~odb_GLT_Fstat~ohm_GLT#0_Coef~ohm_GLT_Fstat~hm-VS-ohm_GLT#0_Coef~hm-VS-ohm_GLT_Fstat~db-VS-odb_GLT#0_Coef~db-VS-odb_GLT_Fstat~ohm-VS-odb_GLT#0_Coef~ohm-VS-odb_GLT_Fstat~hm-VS-db_GLT#0_Coef~hm-VS-db_GLT_Fstat~

  # demangle labels:brackets now gone (keep bak compat), strip new # for nmovie
  set fixedlabels ""
  foreach label $rawlabels {
    set fixedlabel $label
    set fixedlabel [replchar $fixedlabel "\"" ""]   ;# rm quotes
    set fixedlabel [replchar $fixedlabel " " "_"]   ;# space -> underscore
    set fixedlabel [replchar $fixedlabel "\[" "$wasbrak"]  ;# R-bracket -> @
    set fixedlabel [replchar $fixedlabel "\]" "$wasbrak"]  ;# L-bracket -> @
    # new: [0] -> #0 (breaks nmovie)
    set fixedlabel [replchar $fixedlabel "#" "$washash"]   ;# # -> @
    foreach uniqlabel $fixedlabels {
      if {"$fixedlabel" == "$uniqlabel"} {set fixedlabel ${fixedlabel}_; break}
    }
    lappend fixedlabels $fixedlabel
  }
  return $fixedlabels
}

### read HEAD, get TYPESTRING of HEAD
proc readheadtypestring { header } {
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  set typestring ""
  foreach line $lines {
    if [string match *TYPESTRING* $line] { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} {
      set trimmedline [string trimright [string trimleft $line '] ~]
      set typestring [split $trimmedline ~]
      set i 0
    }
  }
  return $typestring
}

### read HEAD, get BRICK_TYPES {types: byte,short,int,float,unrecnum,err=empty}
proc readheadbriktypes { header } {  ;# Cox says try not to mix types in brik
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id
  set i 0
  set typecodelist ""
  foreach line $lines {
    if [string match *BRICK_TYPES* $line] { set i 2; continue }
    if { $i == 2 } { set i 1; set count [lindex $line 2]; continue }
    if { $i == 1 } {
      set typecodelist "$typecodelist $line"
      if { [llength $typecodelist] < $count } { continue }
      set i 0
    }
  }
  set typelist ""
  foreach typecode $typecodelist {
    set type $typecode
    if {$typecode == 0} { set type byte }
    if {$typecode == 1} { set type short }
    if {$typecode == 2} { set type int }
    if {$typecode == 3} { set type float }
    if {$typecode == 4} { set type double }
    if {$typecode == 5} { set type complex }
    if {$typecode == 6} { set type rgb }
    set typelist "$typelist $type"
  }
  return $typelist
}

### make/pack multi-brik panel widgets (pre-existing assumed destroyed if new)
proc makemultibrikpanel { page scrwin valuefilelist } {
  global functscanlists
  global bgcol entbgcol selbgcol selcol ffont tfont
  global wasbrak washash debugafnilabels

  if ![winfo exists $scrwin] { frame $scrwin -bg $bgcol }  ;# gone if re-make
  label $scrwin.la -text "Extract Cluster        ValueFile                    \
MaskFile             MaskThresh" -bg $entbgcol -font $tfont
  if ![llength $valuefilelist] {
    label $scrwin.la2 -text "\n\[no labels found in HEAD file\]" \
    -bg $bgcol -font $ffont
  }

  # valuefiles are array-index infixes (already brikstems)
  foreach brik $valuefilelist {
  if {$debugafnilabels} { puts "\n###### brik=$brik" }
    set linef [frame $scrwin.[manglepath $brik] -bg $bgcol]
    label $linef.la -text $functscanlists($page,$brik,subbrikindex) -bg $bgcol
    checkbutton $linef.ck1 -selectcolor $selcol -bg $bgcol \
      -variable functscanlists($page,$brik,extractflag) \
      -highlightbackground $bgcol
    checkbutton $linef.ck2 -selectcolor $selcol -bg $bgcol \
      -variable functscanlists($page,$brik,clusterflag) \
      -highlightbackground $bgcol
    entry $linef.e1 -textvariable functscanlists($page,$brik,valuefile) \
      -bg $entbgcol -selectbackground $selbgcol -width 18 -state disabled \
      -selectforeground black
    tixComboBox $linef.cbx1 -dropdown true \
      -command "cbx:select_maskfile $page" -editable false \
      -variable functscanlists($page,$brik,maskfile) -listwidth 243 \
      -options "label.width 0 label.anchor e
                entry.width 17
                listbox.height 10" ;# listbox.width 17 -> 30
    $linef.cbx1 subwidget listbox delete 0 end
    set brikstem [string range $brik 0 [string last _ $brik]] ;# strip Fstat,t
    if {$debugafnilabels} { puts "#### brikstem=$brikstem" }
    # insert filtered maskfiles to dropdowns (match fixedold/new BRICK_LABS)
    foreach maskfile $valuefilelist {
      set maskstem [string range $maskfile 0 [string last _ $maskfile]]
      set maskstem_no_ [string trimright $maskstem _]
      set brikstem_no_ [string trimright $brikstem _]
      if {$debugafnilabels} { puts "## maskstem=$maskstem" }
      # BRICK_LABS change: "ba LC[0] coef" -> "ba_GLT#0_Coef"
      # old: match <zz>LC@0@ -> <zz>
      # new: match <zz>GLT#0_ -> <zz>GLT_  (*both* have GLT: req. also strip _)
      if { [string match Full_ $maskstem] || \
           [string match $maskstem $brikstem] || \
           [string match ${maskstem}${wasbrak}?${wasbrak} $brikstem] || \
           [string match ${maskstem}LC${wasbrak}?${wasbrak}_ $brikstem] || \
           [string match ${brikstem}LC${wasbrak}?${wasbrak}_ $maskstem] || \
           [string match ${maskstem_no_}${washash}?_ $brikstem] || \
           [string match ${brikstem_no_}${washash}?_ $maskstem] || \
           [string match \
            [string trimright $maskstem _]${wasbrak}?${wasbrak}_ $brikstem] } {
        $linef.cbx1 insert end $maskfile
      }
    }
    # new read: search dropdown to try to default -unset- entries, cluster
    if [string match -unset- $functscanlists($page,$brik,maskfile)] {
      foreach maskfile [$linef.cbx1 subwidget listbox get 0 end] {
        if [string match *F-stat $maskfile] {
          set maskstem [string trimright $maskfile "F-stat"]  ;# old
        }
        if [string match *t-st $maskfile] {
          set maskstem [string trimright $maskfile "t-st"]   ;# old
        }
        if [string match *Fstat $maskfile] {
          set maskstem [string trimright $maskfile "Fstat"]
        }
        if [string match *Tstat $maskfile] {
          set maskstem [string trimright $maskfile "Tstat"]
        }
        set maskstem_no_ [string trimright $maskstem _]
        if { [string match $maskstem $brikstem] || \
             [string match ${maskstem}${wasbrak}?${wasbrak} $brikstem] || \
             [string match ${maskstem}LC${wasbrak}?${wasbrak}_ $brikstem] || \
             [string match ${maskstem_no_}${washash}?_ $brikstem] || \
             [string match \
           [string trimright $maskstem _]${wasbrak}?${wasbrak}_ $brikstem] } {
          set functscanlists($page,$brik,maskfile) $maskfile
        }
      }
      # new def: cluster everything (stats, coef masked by clust stats)
      #if {$maskfile != $brik} { set functscanlists($page,$brik,clusterflag) 1 }
    }
    entry $linef.e2 -textvariable functscanlists($page,$brik,maskthresh) \
     -bg $entbgcol -selectbackground $selbgcol -width 4 -selectforeground black
  }
  pack $scrwin $scrwin.la -side top -fill x -pady 4
  if ![llength $valuefilelist] { pack $scrwin.la2 }
  foreach brik $valuefilelist {
    set linef $scrwin.[manglepath $brik]
    pack $linef -side top -fill x
    pack $linef.la $linef.ck1 $linef.ck2 $linef.e1 $linef.cbx1 -side left
    pack $linef.e2 -padx 8 -side left
  }
}

### update all MaskThresh's in current multibrik window
proc updatemaskthresh { scrwin page } {
  global functscanlists

  foreach index [array names functscanlists $page,*,maskthresh] {
    set functscanlists($index) $functscanlists($page,globalmaskthresh)
  }
}

### show/hide multibrik scrolled window on select/unselect StatType AFNI-MULTI
proc togglemultibrikpanel { page buttonname selected } {
  global functscanlists renderscanlists scrwinpackpoint scrwinmultibrik
  global bskippackpoint bskipline

  if ![info exists scrwinpackpoint($page)] { return }
  if ![info exists scrwinmultibrik($page)] { return }
  if ![winfo exists $scrwinpackpoint($page)] { return }
  if ![winfo exists $scrwinmultibrik($page)] { return }
  if {$buttonname == "brikmulti"} {
    if {$selected} {
      pack $scrwinmultibrik($page) -after $scrwinpackpoint($page) -pady 2
      pack forget $bskipline($page)
      set renderscanlists($page,renderlisttype) last
    } else {
      pack forget $scrwinmultibrik($page)
      #set renderscanlists($page,renderlisttype) one ;# nonmultibrik ON wanted?
    }
  }
  if {$buttonname == "briksingle" || $buttonname == "mgzsingle"} {
    if {$selected} {
      pack $bskipline($page) -after $bskippackpoint($page) -pady 2
    }
  }
  if {$buttonname == "bfloat"} {
    if {$selected} {
      pack forget $bskipline($page)
    }
  }
}

### Render Stats Dir button (View Funct Data)--make 1 notebook page of widgets
proc addrenderscan { nbwin { menuscandirtype functdir } } {
  global env session iscandir
  global bgcol selcol selbgcol entbgcol hilbgcol hilcol actbgcol
  global currpage prevpage ffont tfont hfont
  global sessionscanlists functscanlists renderscanlists sphavglists
  global viewstclcombo flattclcombo wfileprefscombo swfileprefscombo
  global subjectscombo sessionscombo scandirscombo
  global custpackpoint custxforments lastrendertype
  global coupledrevphaseflag statmaskparmslist

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }  ;# no simul functalign + render
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  set iscandir $page
  global viewlist$page

  ### distinguish ViewFunctional, ViewSphereAvg menu items
  if {$menuscandirtype == "functdir"} {  ;# from SessionTools menu
    if {$page == "image/prf"} { ;# autoconfig 1st render open prf2sess'd SamSrf
      set sessionscanlists($page,type) functscan
    }
    if ![info exists sessionscanlists($page,type)] {
      confirmalert " View Functional: first do Setup Functional Scan\
                     for \"$page\""
      return
    }
    if {$sessionscanlists($page,type) == "alignscan"} {
      confirmalert " View Functional: \"$page\" currently configured as\
                     Align Scan Dir (redo Setup Funct Scan for \"$page\")"
      return
    }
    if {$sessionscanlists($page,type) == "functscan"} {  } ;# OK
    if {$sessionscanlists($page,type) == "sphavgscan"} {
      confirmalert " View Functional: this is a Cross Session Spherical\n\
                     Average scandir:\n\n\
                     Use \"CrossSessTools -> View Sphavg Data\" instead"
      return
    }
  }
  # prevent sphavg dirs from acquiring irrelevant SessionTools configs
  if {$menuscandirtype == "sphavgdir"} { ;# from CrossSessTools menu
    if ![info exists sessionscanlists($page,type)] {
      confirmalert " View SphereAvg: first do Cross Session Average"
      return
    }
    if {$sessionscanlists($page,type) == "alignscan" || \
        $sessionscanlists($page,type) == "functscan"} {
      confirmalert " View SphereAvg: \"$page\" currently config'd as\n\
                     Align or Funct Scan Dir (not Cross Sess Average)\n\n\
                     Use \"SessionTools -> View Functional Data\" instead"
      return
    }
    # TODO: could check if $page equals config'd sphavgdir
  }
  #set sessionscanlists($page,type) functscan ;# just this if no Setup Funct

  ### common page setup
  if { [info commands $f.la] != "" } { destroy $f.la }
  tixLabelFrame $f.la -labelside acrosstop -background $bgcol -padx 20 \
     -label "Functional Scan Directory" \
     -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -background $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  pack $f.la -side top
  set lasub [$f.la subwidget frame]
  $lasub config -background $bgcol
  set f $lasub

  ### queried by complex VOLSTATS so always def (perhaps miss-set w/o FOURIER)
  if ![info exists functscanlists($page,phasestatformat)] {
    set functscanlists($page,phasestatformat) \
        $functscanlists(def,phasestatformat)
    # bak compat: for old config'd pre-phasestatformat scan w/1st act VOLSTATS
    set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
    if { [glob -nocomplain $fullscandir/*_000.bfloat] != "" } {
      set functscanlists($page,phasestatformat) bfloat ;# override new BRIK def
    }
  }
  if ![info exists functscanlists($page,realstatformat)] {
    set functscanlists($page,realstatformat) \
        $functscanlists(def,realstatformat)
    # bak compat: for old config'd pre-realstatformat scan w/1st act VOLSTATS
    set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
    if { [glob -nocomplain $fullscandir/*_000.bfloat] != "" } {
      set functscanlists($page,realstatformat) bfloat ;# override new BRIK def
    }
  }

  ### bak compat: mk missing timeseries dump switches (new addfunctscan inits)
  foreach parm { normdsampsearchflag normdsampuniqvoxflag normdsampallflag \
                 samevtxthickflag paintext normdsampuniqvtxflag } {
    if ![info exists functscanlists($page,$parm)] {
      set functscanlists($page,$parm) $functscanlists(def,$parm)
    }
  }
  if ![info exists functscanlists($page,angle_offset1sec)] {
    set functscanlists($page,angle_offset1sec) "--N/A--"
  }

  ### handle multiple data modes (other panels have only 1)
  if ![info exists renderscanlists($page,rgbname)] {
    set renderscanlists($page,rgbname) [file tail $iscandir]  ;# default=dir
  }
  # samestem must exist (used at select_wfilepref callback at widget create)
  if { ![info exists renderscanlists($page,samestem)] ||
       $renderscanlists($page,samestem) == ""} {
    set renderscanlists($page,samestem) $renderscanlists(def,samestem)
  }
  # force rendertypes -- tixSelect: eccen,polar,2cond,fs,2cond,real tixSelect
  if {$sessionscanlists($page,type) == "sphavgscan"} {
    if [info exists sphavglists(00,phasetype)] { ;# no allowzero, subset
      if {$sphavglists(00,phasetype) == "none"} {
        set sphavglists(00,phasetype) real  ;# tmp back compat (rm after 1 yr)
      }
      set renderscanlists($page,rendertype) $sphavglists(00,phasetype)
    }
  }
  if {$sessionscanlists($page,type) == "fsscan"} {
    set renderscanlists($page,rendertype) fs
  }
  if [info exists functscanlists($page,phasetype)] {
    if {$functscanlists($page,phasetype) != ""} {
      set renderscanlists($page,rendertype) $functscanlists($page,phasetype)
    } else { set renderscanlists($page,rendertype) real }
  }
  if { [info exists functscanlists($page,statformat)] } {
    if { $functscanlists($page,statformat) == "brikmulti" || \
         $functscanlists($page,statformat) == "bfloat"} {
      set renderscanlists($page,rendertype) real
    }
  }
  if {$sessionscanlists($page,type) == "extstatscan"} { ;# maybe was fourier
    set renderscanlists($page,rendertype) real
  }
  if ![info exists renderscanlists($page,rendertype)] {
    set renderscanlists($page,rendertype) real
  }
  set lastrendertype($page) $renderscanlists($page,rendertype)
  set functscanlists($page,renderflag)  1

  ### Paint File: (was "Painted VertexList Pref:") + one/multi
  set wfileprefscombo($page) $f.a.cbx0
  frame $f.a -bg $bgcol
  tixComboBox $f.a.cbx0 -label "Paintfile:" -dropdown true \
    -command "cbx:select_wfilepref $nbwin" -editable true \
    -variable renderscanlists($page,bfloatstem) -listwidth 327 \
    -options "label.width 7 label.anchor e
              entry.width 25
              listbox.height 25" ;# listbox.width 42
  #fixwfileprefs $page   ;# runs fixswfileprefs, wait till quered vars exist

  ## multi-render hacks
  tixSelect $f.a.s1 -allowzero false -radio true -orientation horizontal
  foreach but "one last all" {
    $f.a.s1 add $but -text $but -font $hfont \
      -width 3 -bg $bgcol -padx 0 -pady 0 \
      -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  }
  $f.a.s1 config -variable renderscanlists($page,renderlisttype) \
    -command "select_renderlisttype $page"  ;# appends buname, bustate
  $f.a.s1 subwidget label config -padx 0

#xxx -- now:subst logic in ecc/pol/two*tcl + surftestrender copy to testexist
#DONE: mv'd subst logic to fixswfileprefs, initial load at panel create
#      surftestrender still tests consistent/exist after possible comboreselect
#TODO: pass complete sbfloatstem tclvar to eccen/polar/twocond (rm subst there)
#      mv scriptsload->cmdline: -overlay(real,imag,stat), leave just savergb

  ### StatMask File: for both single and cross subject
  set swfileprefscombo($page) $f.b.cbx0
  frame $f.b -bg $bgcol
  tixComboBox $f.b.cbx0 -label "StatMask Paintfile:" -dropdown true \
    -command "cbx:select_swfilepref $nbwin" -editable true \
    -variable renderscanlists($page,sbfloatstem) -listwidth 327 \
    -options "label.width 16 label.anchor e
              entry.width 29
              listbox.height 25" ;# listbox.width 42
  #fixswfileprefs $page  ;# postpone call to below til vars it queries exist

  ### saved images prefix
  # next causes fieldsign eccen combos yoking after addrenderscan (tix bug?)
  #tixLabelEntry $f.c -label "Saved Images Prefix: " -labelside left \
  # -options "entry.textVariable renderscanlists($page,rgbname) label.width 20"
  tixLabelEntry $f.c -label "Saved Images Prefix:" -labelside left \
    -options "label.width 18 entry.width 17"
  $f.c subwidget entry config -textvariable renderscanlists($page,rgbname)
  checkbutton $f.c.ck1 -text "SamePrefix" -selectcolor $selcol -bg $bgcol \
    -variable renderscanlists($page,samestem) -highlightbackground $bgcol \
    -command "setsamestem $page"
  set savergbflag 0    ;# always start test

  ### reset-to-default rendertype buttons + cp prev
  frame $f.d -bg $bgcol
  tixSelect $f.d.a -allowzero true -radio true -label "ResetToDefault: " \
    -orientation horizontal -options "label.width 14" \
    -command "setrenderdefaults $page $f.d" ;# appends buttonname, buttonstate
  foreach but "eccen polar 2cond fstat real fs" {
    $f.d.a add $but -text $but -font $hfont -width 0 -bg $bgcol -pady 1 -padx 0
    if {$but == "fs"} { $f.d.a subwidget fs config -text fs* }
    if {$but == "fstat"} { $f.d.a subwidget fstat config -text stat }
  }
  $f.d.a config -disablecallback true  ;# stop linkvar-caused setrenderdefaults
  $f.d.a config -variable renderscanlists($page,rendertype)
  $f.d.a config -disablecallback false
#xxx-- may need to pass other widgets to block callbacks
  frame $f.d.b -bg $bgcol -width 12
  button $f.d.c -text "cp prev" -font $ffont -bg $bgcol -pady 1 -padx 0 \
    -command "cpprevrenderparms $f.d.a" -highlightbackground $bgcol

  ### cp prev rendertype if not first-config'd render page (before default)
  # unconfig'd Fourier panel phasetype reset to def in 1st config'd propagates
  set cprendertype 0
  foreach parm [array names renderscanlists] {
    if { ![string match def,* $parm] && ![string match $page,* $parm] } {
      set cprendertype 1
    }
  }
  # don't blow away rendertype copied to unconfig'd from Fourier phasetype
  if [info exists renderscanlists($page,rendertype)] { set cprendertype 0 }
  if {$cprendertype} {
    set renderscanlists($page,rendertype) $renderscanlists($prevpage,rendertype)
  }

  ### if no fmid, default everything using rendertype (first time only)
  if { ![info exists renderscanlists($page,fmid)] || \
       $renderscanlists($page,fmid) == ""} {
    setrenderdefaults $page $f.d $renderscanlists($page,rendertype) 1
  }

  ### re-read safety fallback: propagate unset parms from prev page, else def
  foreach defparm [array names renderscanlists def,*] {
    set parm [string range $defparm 4 end]
    if { ![info exists renderscanlists($page,$parm)] ||
         $renderscanlists($page,$parm) == ""} {
      if {$parm == "colscaletype" } {  ;# new in csurf35r
        colscaletypefromrendertype $page  ;# bak compat: don't redef config'd
      } else {
        if [info exists renderscanlists($prevpage,$parm)] {
          set renderscanlists($page,$parm) $renderscanlists($prevpage,$parm)
        } else {
          set renderscanlists($page,$parm) $renderscanlists(def,$parm)
        }
      }
    }
  }

  ### colscaletype: picks set_{[const,curv],real,complex,fs}_color funct
  tixSelect $f.e -allowzero false -radio true -label "Data Type:" \
    -orientation horizontal -options "label.width 0" \
    -command "select_colscaletype $page"   ;# appends butt, state
  if { [info exists renderscanlists($page,colscaletype)] && \
       $renderscanlists($page,colscaletype) == "vstat" } {
    set renderscanlists($page,colscaletype) tstat  ;# bak compat
    confirmalert "BakCompat: update Render DataType: real+stat -> real+tmask"
  }
  foreach but "cplx real fstat tstat fs" {
    if {$but == "cplx"}  { set text "phase" } ;# mask set by $complexstatsource
    if {$but == "real"}  { set text "real" }
    if {$but == "fstat"} { set text "real+Fmsk" }
    if {$but == "tstat"} { set text "real+tmsk" }
    if {$but == "fs"}    { set text "fs+msk" }
    $f.e add $but -text $text -font $hfont -width 0 -bg $bgcol -pady 1 -padx 2
  }
  $f.e config -disablecallback true  ;# stop select_colscaletype reset config'd
  $f.e config -variable renderscanlists($page,colscaletype)
  $f.e config -disablecallback false

  #foreach but "real cplx fs vstat" {   ;# orig for reference
  #  if {$but == "real"}  { set text "real" }
  #  if {$but == "cplx"}  { set text "phase+sig" }
  #  if {$but == "fs"}    { set text "fieldsign+mask" }
  #  if {$but == "vstat"} { set text "real+stat" }
  #  $f.e add $but -text $text -font $hfont -width 0 -bg $bgcol -pady 1 -padx 2
  #}
  #$f.e config -variable renderscanlists($page,colscaletype)

  ### next only visible singlesubj
  if {$menuscandirtype == "functdir"} {
    tixSelect $f.f -allowzero false -radio true -label \
      "PhaseMask:" -orientation horizontal \
      -options "label.width 10" -command "select_complexstatsource $page"
    set found 0   ;# found filters xsubj (same var for now)
    foreach but "sig fclu fcoh" {
      if {$but == "sig"}  { set text "none:sig,amp=sqrtF" }  ;# orig sqrtF
      if {$but == "fclu"} { set text "sig+(clust)Fmask" }    ;# clust _h 1sub
      if {$but == "fcoh"} { set text "sig+coher" }           ;# _c 1sub
      $f.f add $but -text $text -font $hfont -width 0 -bg $bgcol -pady 1 -padx 1
      if {"$renderscanlists($page,complexstatsource)" == $but} { set found 1 }
    }
    if {!$found} { set renderscanlists($page,complexstatsource) sig } ;# no mask
    $f.f config -disablecallback true
    $f.f config -variable renderscanlists($page,complexstatsource)
    $f.f config -disablecallback false
  }

  ### next only visible xsubj (put here since modifies "phase" Data Type)
  if {$menuscandirtype == "sphavgdir"} {
    tixSelect $f.f -allowzero false -radio true -label \
      "XSubPhaseMsk:" -orientation horizontal \
      -options "label.width 13" -command "select_complexstatsource $page"
    set found 0  ;# found filters defunct and single subj parms
    foreach but "sig famp fsig raang tsig tpow" {
      if {$but == "sig"}   { set text sig }      ;# orig sqrtF (no mask)
      if {$but == "famp"}  { set text cxF-amp }  ;# Don's complex F on raw amp
      if {$but == "fsig"}  { set text cxF-sig }  ;# Don's complex F on sig
      if {$but == "raang"} { set text cxR-ang }  ;# Rayleigh R
      if {$but == "tsig"}  { set text t-sig }    ;# t vs. sqrtF
      if {$but == "tpow"}  { set text t-pow }    ;# t (squared) vs. F (power)
      $f.f add $but -text $text -font $hfont -width 0 -bg $bgcol -pady 1 -padx 1
      if {"$renderscanlists($page,complexstatsource)" == $but} { set found 1 }
    }
    if {!$found} { set renderscanlists($page,complexstatsource) sig } ;# no mask
    $f.f config -disablecallback true ;#else c.b. defs sbfloatstem to -no_mask-
    $f.f config -variable renderscanlists($page,complexstatsource)
    $f.f config -disablecallback false
  }

  ### wait til now so variables queried by following functions exist
  fixwfileprefs $page    ;# N.B.: runs fixswfileprefs via cbx:select_wfilepref
  #fixswfileprefs $page  ;# complexvalflag/complexstatsource/colscaletype

  ### colscale: picks subtypes within set_*_color functions
  tixSelect $f.g -allowzero false -radio true -label "ColorScale:" \
    -orientation horizontal -options "label.width 9"
  foreach but "w1 w2 w4 lutw heat bi BRy BRw fs lut jet vd" {
    if {$but == "w1"}   { set colscale 0  }
    if {$but == "w2"}   { set colscale 8  }
    if {$but == "w4"}   { set colscale 18 }
    if {$but == "lutw"} { set colscale 14 }
    if {$but == "heat"} { set colscale 1  }
    if {$but == "bi"}   { set colscale 4  }
    if {$but == "BRy"}  { set colscale 11 }  ;# redef'd (was 1+statflag)
    if {$but == "BRw"}  { set colscale 6  }
    if {$but == "fs"}   { set colscale 9  }
    if {$but == "lut"}  { set colscale 12 }
    if {$but == "jet"}  { set colscale 15 }
    if {$but == "vd"}   { set colscale 17 }
    if {$but == "bi" || $but == "fs"} {  ;# unsqueeze a few
      $f.g add $colscale \
        -text $but -font $hfont -width 0 -bg $bgcol -pady 1 -padx 2
    } else {  ;# squeeze
      $f.g add $colscale \
        -text $but -font $hfont -width 0 -bg $bgcol -pady 1 -padx 0
    }
  }
  $f.g config -variable renderscanlists($page,colscale)

  ### smoothing -- surface and 3D
  frame $f.h -bg $bgcol
  label $f.h.la0 -text "Smooth: Surf(val,stat)" -bg $bgcol -font $tfont
  checkbutton $f.h.ck0 -text "" -selectcolor $selcol -bg $bgcol \
   -variable renderscanlists($page,cpxangrealampflag) \
   -highlightbackground $bgcol -font $ffont -bd 0 -padx 0
  $f.h.ck0 config -command {
    set page [demanglepath [.setuppopup.to.no raised]] ;# called: global context
    if {$renderscanlists($page,cpxangrealampflag)} {
      confirmalert "Complex smoothing will use funct:\
          \n\n    smooth_complexang_realamp (=type \"cr\" on large F3 panel)\
          \n\nIgnore dispersion: average complex angle, avg real amplitude"
    } else {
      confirmalert "Complex smoothing will use funct:\
                \n\n    smooth_val (=smoothing type \"val\")\
                \n\nStandard: vector average with neighbors"
    }
  }
  entry $f.h.e0 -width 3 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,smoothstepsrend) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  entry $f.h.e3 -width 3 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,smoothstepsstat) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.h.la1 -text "  3D(cells,fwhm)" -bg $bgcol -font $tfont
  entry $f.h.e1 -width 2 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,kcnt) \
    -highlightbackground $bgcol -font $ffont -selectforeground black ;#blk:linux
  entry $f.h.e2 -width 3 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,kfwhm) \
    -highlightbackground $bgcol -font $ffont -selectforeground black

  ### amplitude and mask contrast (fslope) and midpoint (soft thresh)
  set statmaskparmslist($page) ""  ;# page specific
  tixLabelEntry $f.i -label \
    "Contrast: DataAmpli.,StatMask (fslope,sfslope):" -labelside left
  #gets mangled as: -options "entry.textVariable renderscanlists($page,fslope)"
  $f.i subwidget entry config -textvariable renderscanlists($page,fslope)
  $f.i subwidget label config -width 41  ;# 39
  $f.i subwidget entry config -width 4
  entry $f.i.e -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,sfslope) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  set statmaskparmslist($page) "$statmaskparmslist($page) $f.i.e"
  tixLabelEntry $f.j -label \
    "Midpoint: DataAmplitude,StatMask (fmid,sfmid):" -labelside left \
    -options "entry.textVariable renderscanlists($page,fmid)"
  $f.j subwidget label config -width 41  ;# 39
  $f.j subwidget entry config -width 4
  entry $f.j.e -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,sfmid) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  set statmaskparmslist($page) "$statmaskparmslist($page) $f.j.e"

  ### tix select optional mask complex + 4th basic parm (thresh)
  frame $f.k -bg $bgcol
  if {$renderscanlists($page,complexampmodtype) == "none"} {
    set renderscanlists($page,complexampmodtype) "off"   ;# tmp bak compat
  }
  tixLabelEntry $f.k.e -label "(fthresh,sfthr.):" -labelside left \
    -options "entry.textVariable renderscanlists($page,fthresh)"
  $f.k.e subwidget entry config -width 4
  $f.k.e subwidget label config -width 13  ;# 10
  #mk entry before, pack it after, tixSelect: funct gets full statmaskparmslist
  entry $f.k.e2 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,sfthresh) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  set statmaskparmslist($page) "$statmaskparmslist($page) $f.k.e2"
  tixSelect $f.k.sel -allowzero false -radio true -label "CpxAmpMod:" \
    -orientation horizontal -options "label.width 10" \
    -command "select_complexampmodtype $page"  ;# appends butt, state
  foreach but "off repl mask mult" {  ;# was "StatMod CplxAmp"
    $f.k.sel add $but \
      -text $but -font $hfont -width 0 -bg $bgcol -pady 1 -padx 0
  }
  $f.k.sel config -disablecallback true ;# else c.b. defs sbfloatstem -no_mask-
  $f.k.sel config -variable renderscanlists($page,complexampmodtype)
  $f.k.sel config -disablecallback false

  ### TruncFS, fadef/ipsiyellowfact, Angle Cycles
  frame $f.l -bg $bgcol
  checkbutton $f.l.ck -font $tfont -text "TruncFS" \
    -selectcolor $selcol -bg $bgcol -highlightbackground $bgcol \
    -variable renderscanlists($page,nonbinaryfsflag)
  label $f.l.la2 -text " fadef:" -bg $bgcol -font $ffont
  entry $f.l.e2 -width 3 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,fadef) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.l.la3 -text " ipsiyel:" -bg $bgcol -font $ffont
  entry $f.l.e3 -width 3 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,ipsiyellowfact) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  tixLabelEntry $f.l.le1 -label "Angle Cycles:" -labelside left \
      -options "entry.textVariable renderscanlists($page,angle_cycles)"
  $f.l.le1 subwidget label config -width 13
  $f.l.le1 subwidget entry config -width 3

  ### Phase + revs/offsets
  frame $f.m -bg $bgcol
  #label $f.m.la -text "Phase Revs, Angle Offsets: " -bg $bgcol -font $tfont
  label $f.m.la -text "Revs,AngleOffsets: " -bg $bgcol -font $tfont
  checkbutton $f.m.ck0 -text "LH" -font $ffont -selectcolor $selcol \
    -bg $bgcol -variable renderscanlists($page,lh,revphaseflag) \
    -highlightbackground $bgcol
  tixLabelEntry $f.m.lh -bg $bgcol -labelside right -options "entry.width 4 \
     label.width 0 entry.textVariable renderscanlists($page,lh,angle_offset)"
  checkbutton $f.m.ck1 -text "RH" -font $ffont -selectcolor $selcol \
    -bg $bgcol -variable renderscanlists($page,rh,revphaseflag) \
    -highlightbackground $bgcol
  tixLabelEntry $f.m.rh -bg $bgcol -labelside right -options "entry.width 4 \
     label.width 0 entry.textVariable renderscanlists($page,rh,angle_offset)"
  label $f.m.la2 -text "1s=" -bg $bgcol -font $ffont
  entry $f.m.e -width 6 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable functscanlists($page,angle_offset1sec) \
    -highlightbackground $bgcol -font $ffont -selectforeground black \
    -state disabled -disabledforeground black  ;# def=#a3a3a3

  ### truncphase + limits
  frame $f.n -bg $bgcol
  # inv not hemi-specific for not
  checkbutton $f.n.ck0 -font $tfont -text "InvPh" \
    -selectcolor $selcol -bg $bgcol -highlightbackground $bgcol \
    -variable renderscanlists($page,invphaseflag)
  # next 2: hack pair of flags into switch
  checkbutton $f.n.ck -font $tfont -text "TrnPh" \
    -selectcolor $selcol -bg $bgcol -highlightbackground $bgcol \
    -variable renderscanlists($page,truncphaseflag) \
    -command "set renderscanlists($page,softtruncphaseflag) 0" -bd 0
  checkbutton $f.n.ck2 -font $tfont -text "Sft " \
    -selectcolor $selcol -bg $bgcol -highlightbackground $bgcol \
    -variable renderscanlists($page,softtruncphaseflag) \
    -command "set renderscanlists($page,truncphaseflag) 0" -bd 0
  # diff def than same-name functscanlists vars for paint (after revflag here)
  label $f.n.la1 -text "RH" -bg $bgcol -font $ffont
  entry $f.n.e1 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,rh,truncphasemin) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.n.la2 -text "to" -bg $bgcol -font $ffont
  entry $f.n.e2 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,rh,truncphasemax) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.n.la3 -text " LH" -bg $bgcol -font $ffont
  entry $f.n.e3 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,lh,truncphasemin) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.n.la4 -text "to" -bg $bgcol -font $ffont
  entry $f.n.e4 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,lh,truncphasemax) \
    -highlightbackground $bgcol -font $ffont -selectforeground black

  ### flags + offset/cvfact
  frame $f.o -bg $bgcol
  label $f.o.ck0 -text "" -bg $bgcol
  ## N.B.: fieldsignflag set by scripts (read_fieldsign)
  checkbutton $f.o.ck1 -text "cpx" -selectcolor $selcol -bg $bgcol \
    -variable renderscanlists($page,complexvalflag) \
    -highlightbackground $bgcol -font $ffont -bd 0
  checkbutton $f.o.ck2 -text "FTamp" -selectcolor $selcol -bg $bgcol \
    -variable renderscanlists($page,fourierampflag) \
    -highlightbackground $bgcol -font $ffont -bd 0 \
    -command {
      set page [demanglepath [.setuppopup.to.no raised]] ;#called global context
      askresetcmplxthresh2sane $page $renderscanlists($page,complexstatsource)
    }
  checkbutton $f.o.ck3 -text "mm" -selectcolor $selcol -bg $bgcol \
    -variable renderscanlists($page,scalebarflag) \
    -highlightbackground $bgcol -font $ffont -bd 0
  checkbutton $f.o.ck4 -text "scl" -selectcolor $selcol -bg $bgcol \
   -variable renderscanlists($page,colscalebarflag) \
   -highlightbackground $bgcol -font $ffont -bd 0
  checkbutton $f.o.ck5 -text "cv" -selectcolor $selcol -bg $bgcol \
    -variable renderscanlists($page,surfcolor) \
    -highlightbackground $bgcol -font $ffont -bd 0
  checkbutton $f.o.ck6 -text "intp" -selectcolor $selcol -bg $bgcol \
   -variable renderscanlists($page,interpolatelutflag) \
   -highlightbackground $bgcol -font $ffont -bd 0
  checkbutton $f.o.ck7 -text "bot" -selectcolor $selcol -bg $bgcol \
   -variable renderscanlists($page,botedgelutflag) \
   -highlightbackground $bgcol -font $ffont -bd 0
  checkbutton $f.o.ck8 -text "sym" -selectcolor $selcol -bg $bgcol \
   -variable renderscanlists($page,zerosymmfadeflag) \
   -highlightbackground $bgcol -font $ffont -bd 0
  #checkbutton $f.o.ck9 -text "av" -selectcolor $selcol -bg $bgcol \
  #  -variable renderscanlists($page,avgflag) \
  #  -highlightbackground $bgcol -font $ffont
  label $f.o.la1 -text " off:" -bg $bgcol -font $ffont
  entry $f.o.e1 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,offset) -highlightbackground $bgcol \
    -font $ffont -selectforeground black
  label $f.o.la2 -text "cvf:" -bg $bgcol -font $ffont
  entry $f.o.e2 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,cvfact) -highlightbackground $bgcol \
    -font $ffont -selectforeground black

  ### 3D underlay
  frame $f.o2 -bg $bgcol
  label $f.o2.la0 -text "3D Underlay Contr/MidPnt: " \
    -bg $bgcol -font $tfont
  label $f.o2.la1 -text "bwslope:" -bg $bgcol -font $ffont
  entry $f.o2.e1 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,bwslope) \
    -highlightbackground $bgcol -font $ffont -selectforeground black
  label $f.o2.la2 -text "bwmid:" -bg $bgcol -font $ffont
  entry $f.o2.e2 -width 4 -bg $entbgcol -selectbackground $selbgcol \
    -textvariable renderscanlists($page,bwmid) \
    -highlightbackground $bgcol -font $ffont -selectforeground black

  ### views + cust dropdown
  tixSelect $f.p -allowzero true -radio false -label "Views:" \
   -orientation horizontal -options "label.width 6" \
   -command "togglecustview $page"
  set viewlist$page ""
  $f.p config -variable viewlist$page
  foreach but "lat med ven pos dor cust flat" {
    $f.p add $but -text $but -font $hfont -width 1 -bg $bgcol -pady 1 -padx 11 \
       -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
    if [info exists renderscanlists($page,$but)] {
      if {$renderscanlists($page,$but)} {
        set viewlist$page "[set viewlist$page] $but"
      }
    }
  }
  if ![llength [set viewlist$page]] { set viewlist$page "lat" }
  set custpackpoint($page) $f.p
  set custxforments($page) $f.q
  frame $f.q -bg $bgcol
  foreach h "rh lh" {
    frame $f.q.$h -bg $bgcol
    if {$h == "rh"} { label $f.q.$h.l -text "RH  " -bg $bgcol }
    if {$h == "lh"} { label $f.q.$h.l -text "LH  " -bg $bgcol }
    label $f.q.$h.xrl -text "xr:" -bg $bgcol
    entry $f.q.$h.xre -textvariable renderscanlists($page,$h,customxrot) \
        -bg $entbgcol -selectbackground $selbgcol -width 4
    label $f.q.$h.yrl -text " yr:" -bg $bgcol
    entry $f.q.$h.yre -textvariable renderscanlists($page,$h,customyrot) \
        -bg $entbgcol -selectbackground $selbgcol -width 4
    label $f.q.$h.zrl -text " zr:" -bg $bgcol
    entry $f.q.$h.zre -textvariable renderscanlists($page,$h,customzrot) \
        -bg $entbgcol -selectbackground $selbgcol -width 4
    label $f.q.$h.xtl -text " xt:" -bg $bgcol
    entry $f.q.$h.xte -textvariable renderscanlists($page,$h,customxtrans) \
        -bg $entbgcol -selectbackground $selbgcol -width 3
    label $f.q.$h.ytl -text " yt:" -bg $bgcol
    entry $f.q.$h.yte -textvariable renderscanlists($page,$h,customytrans) \
        -bg $entbgcol -selectbackground $selbgcol -width 3
    label $f.q.$h.scl -text " scl:" -bg $bgcol
  entry $f.q.$h.sce -textvariable renderscanlists($page,$h,customscalepercent)\
        -bg $entbgcol -selectbackground $selbgcol -width 3
  }
  frame $f.sp -bg $bgcol

  ### scripts combos
  frame $f.r -bg $bgcol
  set viewstclcombo($page) $f.r.cbx2
  tixComboBox $f.r.cbx2 -label "3D:" -dropdown true \
    -command "cbx:select_tclscript $viewstclcombo($page)" -editable true \
    -variable renderscanlists($page,viewstcl) -listwidth 173 \
    -options "label.width 3 label.anchor e
              entry.width 14
              listbox.height 11" ;# listbox.width 11 -> 20
  set flattclcombo($page) $f.r.cbx3
  tixComboBox $f.r.cbx3 -label "Flat:" -dropdown true \
    -command "cbx:select_tclscript $flattclcombo($page)" -editable true \
    -variable renderscanlists($page,flattcl) -listwidth 173 \
    -options "label.width 5 label.anchor e
              entry.width 14
              listbox.height 11" ;# listbox.width 10 -> 20
  fixtclscripts $page 

  ### pack (indents: horiz in basic rows)
  pack $f.a -side top
    pack $f.a.cbx0 $f.a.s1 -side left
  pack $f.b -side top
    pack $f.b.cbx0 -side left
  pack $f.c -side top -padx 5 -pady 2
    pack $f.c.ck1 -side left
  pack $f.d -side top -padx 0 -pady 2
    pack $f.d.a $f.d.b $f.d.c -side left -padx 0 -pady 0
  pack $f.e -side top -padx 5 -pady 2
  pack $f.f -side top   ;# N.B.: different singlesub/xsub widget
  pack $f.g -side top -padx 0
  pack $f.h $f.i $f.j $f.k $f.l $f.m $f.n $f.o $f.o2 \
    -side top -padx 5 -pady 2
    pack $f.h.la0 $f.h.ck0 $f.h.e0 $f.h.e3 $f.h.la1 $f.h.e1 $f.h.e2 \
      -side left -padx 0
    pack $f.i.e $f.j.e $f.k.sel $f.k.e $f.k.e2 -side left
    pack $f.l.ck $f.l.la2 $f.l.e2 $f.l.la3 $f.l.e3 $f.l.le1 -side left -padx 0
    pack $f.o2.la0 $f.o2.la1 $f.o2.e1 $f.o2.la2 $f.o2.e2 -side left -padx 2
  pack $f.m -side top -padx 5 -pady 2
    pack $f.m.la $f.m.ck1 $f.m.rh $f.m.ck0 $f.m.lh $f.m.la2 $f.m.e -side left
    pack $f.n.ck0 $f.n.ck $f.n.ck2 $f.n.la1 $f.n.e1 $f.n.la2 $f.n.e2 $f.n.la3 \
      $f.n.e3 $f.n.la4 $f.n.e4 -side left
    pack $f.o.ck0 $f.o.ck1 $f.o.ck2 $f.o.ck3 $f.o.ck4 $f.o.ck5 $f.o.ck6 \
      $f.o.ck7 $f.o.ck8 $f.o.la1 $f.o.e1 $f.o.la2 $f.o.e2 -side left
  pack $f.p $f.q $f.r -side top -padx 5 -pady 2
    foreach h "rh lh" {
      pack $f.q.$h -side top
      pack $f.q.$h.l -side left
      pack $f.q.$h.xrl $f.q.$h.xre $f.q.$h.yrl $f.q.$h.yre -side left
      pack $f.q.$h.zrl $f.q.$h.zre $f.q.$h.xtl $f.q.$h.xte -side left
      pack $f.q.$h.ytl $f.q.$h.yte $f.q.$h.scl $f.q.$h.sce -side left
    }
  pack $f.sp -side top -padx 5 -pady 2
    pack $f.r.cbx2 $f.r.cbx3 -side left
  if {!$renderscanlists($page,cust)} { pack forget $custxforments($page) }

  ### omit per-scandir offset/cvfact, use space for better labels
  pack forget $f.o.la1 $f.o.e1 $f.o.la2 $f.o.e2

  set prevpage $currpage
  set currpage $page
  update idletasks  ;# fixes squished bottom buttons on Ubuntu
}

### show/hide custom view fields (on select/unselect cust view)
proc togglecustview { page buttonname selected } {
  global renderscanlists custxforments custpackpoint
  if ![info exists custpackpoint($page)] { return }
  if ![info exists custxforments($page)] { return }
  if ![winfo exists $custpackpoint($page)] { return }
  if ![winfo exists $custxforments($page)] { return }
  set renderscanlists($page,$buttonname) $selected
  if {$buttonname == "cust"} {
    if {$selected} {
      pack $custxforments($page) -after $custpackpoint($page) -pady 2
    } else {
      pack forget $custxforments($page)
    }
  }
}

### set def parms/scripts for rendering types (initial panel make + tixselect)
proc setrenderdefaults { page selectwidget rendertype selected }  {
  global sessionscanlists renderscanlists lastrendertype name

  if {!$selected} { return }
  if {$rendertype == "fs"} {  ;# special case (no *.w file), not a functscan
    if {$sessionscanlists($page,type) != "fsscan" && \
        [info exists renderscanlists($page,rendertype)] } {
      $selectwidget config -disablecallback true
      set renderscanlists($page,rendertype) $lastrendertype($page)
      $selectwidget config -disablecallback false
      return
    } else {  ;# defaults for everything not fs
      set renderscanlists($page,colscaletype)     fs
      set renderscanlists($page,bfloatstem)   -not_used-  ;# conv fs/fm -> .w
      set renderscanlists($page,samestem)         0
      set renderscanlists($page,smoothstepsrend) -not_used-  ;# srend tests
      set renderscanlists($page,smoothstepsstat) -not_used-  ;# srend tests
      set renderscanlists($page,complexvalflag)   0
      set renderscanlists($page,colscale)         9
      set renderscanlists($page,surfcolor)        1
      set renderscanlists($page,fthresh)          0.3
      set renderscanlists($page,fslope)           5.0
      set renderscanlists($page,fmid)             0.9
      set renderscanlists($page,complexvalflag)   0
      set renderscanlists($page,colscalebarflag)  0
      set renderscanlists($page,rh,revphaseflag)  0
      set renderscanlists($page,lh,revphaseflag)  0
      set renderscanlists($page,rh,angle_offset)  0.0
      set renderscanlists($page,lh,angle_offset)  0.0
      set renderscanlists($page,angle_cycles)     1.0
      set renderscanlists($page,viewstcl)    fs-views.tcl
      set renderscanlists($page,flattcl)     fs-flat.tcl
    }
  }
  if {$rendertype == "eccen" || $rendertype == "polar" || \
      $rendertype == "2cond" || $rendertype == "fstat" || \
      $rendertype == "real"  || $rendertype == "afni"} {
    if {$sessionscanlists($page,type) == "fsscan" && \
        [info exists renderscanlists($page,rendertype)] } {
      $selectwidget config -disablecallback true
      set renderscanlists($page,rendertype) $lastrendertype($page)
      $selectwidget config -disablecallback false
      return
    }
  }

  if {$rendertype == "fs"} {
    ;# special case, don't re-default to this if not already fsscan
  }
  if {$rendertype == "real"} {
    set renderscanlists($page,colscaletype)     real
    set renderscanlists($page,complexvalflag)    0
    set renderscanlists($page,colscale)          6  ;# blue/red
    set renderscanlists($page,surfcolor)         1  ;# 0=none,1=curv
    set renderscanlists($page,fthresh)          0.1
    set renderscanlists($page,fslope)           0.15 ;# 0.15, 5.0 (old fico)
    set renderscanlists($page,fmid)             7.0  ;# 7.0, 0.2
    set renderscanlists($page,sfthresh)         0.1
    set renderscanlists($page,sfslope)          0.5
    set renderscanlists($page,sfmid)            0.5
    set renderscanlists($page,smoothstepsrend)   10  ;#  5 
    set renderscanlists($page,smoothstepsstat)   10  ;#  5 
    set renderscanlists($page,rh,revphaseflag)    0
    set renderscanlists($page,lh,revphaseflag)    0
    set renderscanlists($page,rh,angle_offset)  0.0
    set renderscanlists($page,lh,angle_offset)  0.0
    set renderscanlists($page,angle_cycles)     1.0
    set renderscanlists($page,viewstcl)      real-views.tcl 
    set renderscanlists($page,flattcl)       real-flat.tcl 
  }
  if {$rendertype == "eccen"} {
    set renderscanlists($page,colscaletype)     cplx
    set renderscanlists($page,complexvalflag)    1
    set renderscanlists($page,colscale)          0  ;# R/B/G color wheel
    set renderscanlists($page,surfcolor)         1
    set renderscanlists($page,fthresh)          0.3
    set renderscanlists($page,fslope)           1.5
    set renderscanlists($page,fmid)             1.1
    set renderscanlists($page,sfthresh)         0.3
    set renderscanlists($page,sfslope)          1.5
    set renderscanlists($page,sfmid)            3.0
    set renderscanlists($page,smoothstepsrend)   20
    set renderscanlists($page,smoothstepsstat)   20
    set renderscanlists($page,rh,revphaseflag)    0
    set renderscanlists($page,lh,revphaseflag)    0
    set renderscanlists($page,invphaseflag)       0
    set renderscanlists($page,rh,angle_offset)  0.75
    set renderscanlists($page,lh,angle_offset)  0.75
    set renderscanlists($page,angle_cycles)     1.0
    set renderscanlists($page,viewstcl)      eccen-views.tcl 
    set renderscanlists($page,flattcl)       eccen-flat.tcl 
    if { "$name" == "fsaverage" } {
      set renderscanlists($page,smoothstepsrend)  2
      set renderscanlists($page,smoothstepsstat)  3
    }
  }
  if {$rendertype == "polar"} {
    set renderscanlists($page,colscaletype)     cplx
    set renderscanlists($page,complexvalflag)    1
    set renderscanlists($page,colscale)          0  ;# R/B/G color wheel
    set renderscanlists($page,surfcolor)         1
    set renderscanlists($page,fthresh)          0.3
    set renderscanlists($page,fslope)           1.5
    set renderscanlists($page,fmid)             1.1
    set renderscanlists($page,sfthresh)         0.3
    set renderscanlists($page,sfslope)          1.5
    set renderscanlists($page,sfmid)            3.0
    set renderscanlists($page,smoothstepsrend)   10
    set renderscanlists($page,smoothstepsstat)   10
    set renderscanlists($page,rh,revphaseflag)    0
    set renderscanlists($page,lh,revphaseflag)    1
    set renderscanlists($page,invphaseflag)       0
    set renderscanlists($page,rh,angle_offset)  0.0
    set renderscanlists($page,lh,angle_offset)  0.5
    set renderscanlists($page,angle_cycles)     2.2
    set renderscanlists($page,viewstcl)      polar-views.tcl 
    set renderscanlists($page,flattcl)       polar-flat.tcl 
    if { "$name" == "fsaverage" } {
      set renderscanlists($page,smoothstepsrend)  1
      set renderscanlists($page,smoothstepsstat)  2 
    }
  }
  if {$rendertype == "2cond"} {
    set renderscanlists($page,colscaletype)     cplx
    set renderscanlists($page,complexvalflag)    1
    set renderscanlists($page,colscale)          1  ;# heat (brown/white)
    set renderscanlists($page,surfcolor)         1
    set renderscanlists($page,fthresh)          0.3
    set renderscanlists($page,fslope)           1.5
    set renderscanlists($page,fmid)             1.1
    set renderscanlists($page,smoothstepsrend)   10
    set renderscanlists($page,smoothstepsstat)   10
    set renderscanlists($page,rh,revphaseflag)    0
    set renderscanlists($page,lh,revphaseflag)    0
    set renderscanlists($page,rh,angle_offset)  0.15
    set renderscanlists($page,lh,angle_offset)  0.15
    set renderscanlists($page,angle_cycles)     1.0
    set renderscanlists($page,viewstcl)      twocond-views.tcl 
    set renderscanlists($page,flattcl)       twocond-flat.tcl 
  }
  if {$rendertype == "fstat"} {
    set renderscanlists($page,colscaletype)     real
    set renderscanlists($page,complexvalflag)    0
    set renderscanlists($page,colscale)          1  ;# heat (red-org/blue-cyan)
    set renderscanlists($page,colscale)         11  ;# new tksurfer8.5 def
    set renderscanlists($page,surfcolor)         1
    set renderscanlists($page,fthresh)          0.3
    set renderscanlists($page,fslope)           0.4
    set renderscanlists($page,fmid)             1.6
    set renderscanlists($page,smoothstepsrend)   10
    set renderscanlists($page,smoothstepsstat)   10
    set renderscanlists($page,rh,revphaseflag)    0
    set renderscanlists($page,lh,revphaseflag)    0
    set renderscanlists($page,rh,angle_offset)  0.0
    set renderscanlists($page,lh,angle_offset)  0.0
    set renderscanlists($page,angle_cycles)     1.0
    set renderscanlists($page,viewstcl)      twocond-views.tcl 
    set renderscanlists($page,flattcl)       twocond-flat.tcl 
  }
  set lastrendertype($page) $rendertype
}

### reset-to-default-like button for cp render parms from prev panel
proc cpprevrenderparms { rstrend } {  ;# block various callbacks
  global renderscanlists currpage prevpage
  global viewlist$prevpage viewlist$currpage

  if {"$prevpage" == "$currpage"} { return }
  if ![okreplace "" "OK to copy Rendering parms from:\
                 \n\n    $prevpage\
                 \n\nto:\
                 \n\n    $currpage?" "Copy Render Parms"] { return }
  set cpparmlist "\
    rendertype \
    colscaletype \
    complexstatsource \
    colscale \
    smoothstepsrend smoothstepsstat kcnt kfwhm \
    fslope sfslope \
    fmid sfmid \
    complexampmodtype fthresh sfthresh \
    nonbinaryfsflag fadef ipsiyellowfact angle_cycles \
    rh,revphaseflag rh,angle_offset \
    lh,revphaseflag lh,angle_offset \
    invphaseflag truncphaseflag softtruncphaseflag \
      rh,truncphasemin rh,truncphasemax lh,truncphasemin lh,truncphasemax \
    complexvalflag fourierampflag \
      scalebarflag colscalebarflag \
      interpolatelutflag botedgelutflag zerosymmfadeflag surfcolor \
    bwslope bwmid \
    rh,customxrot rh,customyrot rh,customzrot rh,customxtrans \
      rh,customytrans rh,customscalepercent \
    lh,customxrot lh,customyrot lh,customzrot lh,customxtrans \
      lh,customytrans lh,customscalepercent \
    viewstcl flattcl"
  foreach parm $cpparmlist {
    if [info exists renderscanlists($prevpage,$parm)] {
#xxx -- may need to block other widget callbacks
      ## allow two callbacks to force consistent (if block, need pass widget)
      #if {$parm == "complexstatsource"} { $### config -disablecallback true }
      #if {$parm == "complexampmodtype"} { $### config -disablecallback true }
      if {$parm == "rendertype"} { $rstrend config -disablecallback true }
      set renderscanlists($currpage,$parm) $renderscanlists($prevpage,$parm)
      if {$parm == "rendertype"} { $rstrend config -disablecallback false }
      #if {$parm == "complexampmodtype"} { $### config -disablecallback false }
      #if {$parm == "complexstatsource"} { $### config -disablecallback false }
    } else {
      confirmalert "Can't copy Rendering parameter from prev scandir:\
                    \n\n    $prevpage\
                    \n\nScandir \"$prevpage\" not yet configured\
                    \n\n(first missing parm: $parm)"
      return
    }
  }
  set viewlist$currpage [set viewlist$prevpage]
}

### colscaletype from rendertype (bakcompat: don't redefault already config'd)
proc colscaletypefromrendertype { page } {
  global renderscanlists

  if {$renderscanlists($page,rendertype) == "eccen" || \
      $renderscanlists($page,rendertype) == "polar" || \
      $renderscanlists($page,rendertype) == "2cond"} {
    set renderscanlists($page,colscaletype) cplx
  }
  if {$renderscanlists($page,rendertype) == "fs"} {
    set renderscanlists($page,colscaletype) fs
  }
  if {$renderscanlists($page,rendertype) == "real" || \
      $renderscanlists($page,rendertype) == "fstat"} {
    set renderscanlists($page,colscaletype) real
  }
}

### update rgbname
proc setsamestem { page } {
  global renderscanlists
  if {$renderscanlists($page,samestem)} { 
    set renderscanlists($page,rgbname) $renderscanlists($page,bfloatstem)
  }
}

### update PaintedVtxPref/rgbname on renderlist change (save/restore last sing)
proc select_renderlisttype { page buname bustate } {
  global renderscanlists lastbfloatstem lastrgbname
  if {!$bustate} { return } ;# ignore duplicate unclick events
  if { "$buname" == "one" } { ;# multiple (last,all) -> one
    if [info exists lastbfloatstem($page)] {
      set renderscanlists($page,bfloatstem) $lastbfloatstem($page)
    } else {  ;# get first bfloatstem, save
      set renderscanlists($page,bfloatstem) ""
      fixwfileprefs $page
      set lastbfloatstem($page) $renderscanlists($page,bfloatstem)
      set lastrgbname($page) $renderscanlists($page,rgbname)
    }
    if [info exists lastrgbname($page)] {
      set renderscanlists($page,rgbname) $lastrgbname($page)
    }
  } else { ;# one -> multiple (last,all)
    if { $renderscanlists($page,bfloatstem) != "-multiple-" } {  ;# save
      set lastbfloatstem($page) $renderscanlists($page,bfloatstem)
      set lastrgbname($page)    $renderscanlists($page,rgbname)
    }
    set renderscanlists($page,bfloatstem) -multiple-
    set renderscanlists($page,rgbname)    -multiple-
  }
}

### View Functional Data datatype select
proc select_colscaletype { page type selected } {
  global renderscanlists statmaskparmslist

  if {!$selected} { return }
  ## change Data Type forces compatible complexvalflag/colscale/tclscripts
  # N.B.: still need surftestrender test for later incompatible colscale chng
  set colscale $renderscanlists($page,colscale)
  set viewstcl $renderscanlists($page,viewstcl)
  set flattcl $renderscanlists($page,flattcl)

  set updatemaskflag 0
  if { [info exists statmaskparmslist($page)] && \
       [llength $statmaskparmslist($page)] } {
    set updatemaskflag 1
    set toglist $statmaskparmslist($page)
    foreach ent $toglist {  ;# block callbacks at make panel time
      if { [info commands $ent] == ""} { set updatemaskflag 0 }
    }
  }

  if {$type == "real"}  {
    set renderscanlists($page,complexvalflag) 0
    if { $colscale != 6 && $colscale != 11 && $colscale != 12 } {
      set renderscanlists($page,colscale) 6   ;# pick one
    }
    if {$updatemaskflag} { foreach ent $toglist {$ent config -state disabled} }
    set renderscanlists($page,viewstcl) real-views.tcl
    set renderscanlists($page,flattcl)  real-flat.tcl
  }
  if {$type == "cplx"} {
    set renderscanlists($page,complexvalflag) 1
    if { $colscale != 0 && $colscale != 1 && $colscale != 4 } {
      set renderscanlists($page,colscale) 0   ;# pick one
    }
    if { $viewstcl != "polar-views.tcl" && $viewstcl != "eccen-views.tcl" && \
         $viewstcl != "twocond-views.tcl" } {
      set renderscanlists($page,viewstcl) polar-views.tcl   ;# pick one
    }
    if { $flattcl != "polar-flat.tcl" && $flattcl != "eccen-flat.tcl" && \
         $flattcl != "twocond-flat.tcl" } {
      set renderscanlists($page,flattcl)  polar-flat.tcl
    }
  }
  # real-{views,flat} scripts load statmask if maskfloatstem exists
  if {$type == "vstat" || $type == "fstat" || $type == "tstat"} { ;#vstat=old
    set renderscanlists($page,complexvalflag) 0
    set renderscanlists($page,colscale) 11
    if {$updatemaskflag} { foreach ent $toglist {$ent config -state normal} }
    set renderscanlists($page,viewstcl) real-views.tcl
    set renderscanlists($page,flattcl)  real-flat.tcl
  }
  if {$type == "fs"} {
    set renderscanlists($page,complexvalflag) 0
    set renderscanlists($page,colscale) 9
    if {$updatemaskflag} { foreach ent $toglist {$ent config -state disabled} }
    set renderscanlists($page,viewstcl) fs-views.tcl
    set renderscanlists($page,flattcl)  fs-flat.tcl
  }
}

### missing LUT (defaults)
proc defmissinglutfile { type } {
  global env session iscandir

  if {$type != "real" && $type != "eccen" && $type != "polar"} {
    confirmalert "Default color LUT: unknown type\n\n    $type"
    return
  }
  set val2rgblut $env(FUNCTIONALS_DIR)/$session/$iscandir/val2rgb.lut
  if [file exists $val2rgblut] {
    return
  } else {
    confirmalert " Color look-up table:\
                   \n\n     $val2rgblut\n\n\
                   not found in current scandir -- making\n\
                   default LUT file (overlay type: $type)"
  }
  if ![canwriteormakefile $val2rgblut] {
    confirmalert "Permissions don't allow create default color look-up table"
    return
  }
  set id [open $val2rgblut w 0644]
  if {$type == "real"} {
    puts $id \
      "### def val->RGB lookup table (val:float,ascending,negOK, r,g,b:0-255)"
    puts $id "# val\tred\tgreen\tblue"
    puts $id "0.0    88      88      88"
    puts $id "1.0    255     0       0"
    puts $id "2.0    0       0       255"
    puts $id "3.0    0       255     0"
    putlog "made default real LUT file: $val2rgblut"
  }
  if {$type == "eccen"} {
    puts $id "### eccen: phase->RGB (sig=5) colscale=0,ang_cyc=1.0,ang_off=0.0"
    puts $id "0.00    191     63      0"
    puts $id "0.07    242     12      0"
    puts $id "0.13    216     0       38"
    puts $id "0.20    165     0       89"
    puts $id "0.27    114     0       140"
    puts $id "0.33    63      0       191"
    puts $id "0.40    12      0       242"
    puts $id "0.47    0       38      216"
    puts $id "0.53    0       89      165"
    puts $id "0.60    0       140     114"
    puts $id "0.67    0       191     63"
    puts $id "0.73    0       242     12"
    puts $id "0.80    38      216     0"
    puts $id "0.87    89      165     0"
    puts $id "0.93    140     114     0"
    puts $id "1.00    191     63      0"
    putlog "made default eccen LUT file: $val2rgblut"
  }
  if {$type == "polar"} {
    puts $id "### polar: phase->RGB (sig=5) colscale=0,ang_cyc=2.2,ang_off=0.0"
    puts $id "0.00    76      76      76"
    puts $id "0.07    155     42      42"
    puts $id "0.13    235     8       8"
    puts $id "0.20    254     0       0"
    puts $id "0.27    254     0       0"
    puts $id "0.33    254     0       0"
    puts $id "0.40    168     0       86"
    puts $id "0.47    56      0       198"
    puts $id "0.53    0       56      198"
    puts $id "0.60    0       168     86"
    puts $id "0.67    0       254     0"
    puts $id "0.73    0       254     0"
    puts $id "0.80    0       254     0"
    puts $id "0.87    8       235     8"
    puts $id "0.93    42      155     42"
    puts $id "1.00    76      76      76"
    putlog "made default polar LUT file: $val2rgblut"
  }
  close $id
}

### for surftestrender: cleanup early return
proc clear1time { } {
  global sing2fsavgflag oppfsavghemiflag sing2singflag anothersub1time

  set sing2fsavgflag 0
  set oppfsavghemiflag 0
  set sing2singflag 0
  set anothersub1time "__nobody__"
}

###########################################################################
### SURFACE-STATS button command (View Functional/SphAvg Data panel)
###########################################################################
proc surftestrender { nbwin } {
  global surflog surfpid surfrenderbu
  global name hemi surfext patchext viewtype surfdir t1dir
  global env session iscandir etmptcl
  global sessionscanlists renderscanlists functscanlists
  global surfparms postclparms lightparms flattenparms
  global bindir savergbflag exitrenderflag logflag
  global smallscreenflag doublebufferflag minglxdepthflag
  global tiffoutflag black2transparentflag tksurferlogflag mac_appnap_hack
  global realname complexname amprealname ampcomplexname dispername
  global cplxstatname1 cplxstatname2 cplxstatname3 cplxstatname4 cplxstatname5
  global cplxstatname6 realpname datfile force
  global fsaverage sing2fsavgflag wfileprefscombo
  global oppfsavghemiflag sing2singflag anothersub1time appnapstateforced

  set page [demanglepath [$nbwin raised]]
  set iscandir $page
  if {$surfpid != -1} {
    if { [exec uname] == "Darwin" } {  ;# err to pipe for setuid/DYLD warning
      set currproc [lrange [exec ps uxww |& grep $surfpid] 10 end]  ;# BSD
    } elseif { [exec uname] == "Linux" } {
      set currproc [lrange [exec ps uxww |& grep $surfpid] 10 end]  ;# Linux
    } else {
      set currproc [lrange [exec ps af |& grep $surfpid] 7 end]     ;# old sys5
    }
    confirmalert "Start a second csurf to run a second tksurfer"
    clear1time; return
  }
  if { ![info exists wfileprefscombo($page)] ||
       ![winfo exists $wfileprefscombo($page)] } {  ;# Paintfile
    confirmalert "first configure scandir for Render (top)"
    clear1time; return
  }
  if ![info exists renderscanlists($page,rgbname)] { clear1time; return }
  if { [checknamefile] != "match" } { clear1time; return }
  #if { [checksurferlog] != "writable" } { ; } ;# new tksurfer: not writable OK
  if { [checkcorinfoFOV $t1dir] == "zerofovT1" } { clear1time; return }

  if {$sing2singflag} {
    if {!$sing2fsavgflag || $oppfsavghemiflag} { clear1time; return }
    if {$anothersub1time == "__nobody__"} { clear1time; return }
    if ![file exists $env(SUBJECTS_DIR)/$anothersub1time] {
      confirmalert \
        "Other subject to sample to:\n\n    $anothersub1time\n\nnot found"
      clear1time; return
    }
  }

  if {$viewtype == "folded"} { set libscript $renderscanlists($page,viewstcl) }
  if {$viewtype == "inflated"} {set libscript $renderscanlists($page,viewstcl)}
  if {$viewtype == "viewcuts"} {
    set viewtype inflated; set libscript $renderscanlists($page,viewstcl)
  }
  if {$viewtype == "flattened"} {set libscript $renderscanlists($page,flattcl)}

  checkbothhemi
  if {$sing2fsavgflag} { ;# fsaverage-only surf typed in w/Return accepted
    set surf $env(SUBJECTS_DIR)/$fsaverage/$surfdir/$hemi.$surfext
    set patch $env(SUBJECTS_DIR)/$fsaverage/$surfdir/$hemi.$patchext
  } else {
    set surf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$surfext
    set patch $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$patchext
  }
  if ![file exists $surf] {
    confirmalert "Surface:\n\n    $surf\n\nnot found"
    clear1time; return
  }
  if {$viewtype == "viewcuts" || $viewtype == "flattened"} {
    if ![file exists $patch] {
      confirmalert "Patch:\n\n    $patch\n\nnot found"
      clear1time; return
    }
  }
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir

  ### check stale (TODO: also check stale cond and fs)
  if { [info exists functscanlists($page,regdat)] && \
       [info exists renderscanlists($page,bfloatstem)] } {
    set fullregdat $fullscandir/$functscanlists($page,regdat)
    set winfix ""
    if { [info exists renderscanlists($page,complexvalflag)] && \
         $renderscanlists($page,complexvalflag) } { set winfix $realname }
    set fullwfile \
      $fullscandir/$renderscanlists($page,bfloatstem)$winfix-$hemi.w
    if { $name != "fsaverage" } {  ;# TODO: misses curr group surfavg
      if [checkstaleregdat $fullregdat $fullwfile] { clear1time; return }
      if [checkstalewfile $fullwfile] { clear1time; return }
    }
  }

  ### setup views
  set vlist ""  ;# used if set
  if {$renderscanlists($page,lat)} { set vlist "$vlist lat=1" }
  if {$renderscanlists($page,med)} { set vlist "$vlist med=1" }
  if {$renderscanlists($page,ven)} { set vlist "$vlist ven=1" }
  if {$renderscanlists($page,pos)} { set vlist "$vlist pos=1" }
  if {$renderscanlists($page,dor)} { set vlist "$vlist dor=1" }
  if {$renderscanlists($page,cust)} {
    foreach parm { xrot yrot zrot xtrans ytrans scalepercent } {
      set vlist "$vlist custom$parm=$renderscanlists($page,$hemi,custom$parm)"
    }
  }
  # TODO: control for same-mag fold/unfold/flat

  ### lights
  set llist ""
  foreach light { 0 1 2 3 } {
    foreach lparm { "" x y z } {
      set llist "$llist light$light$lparm=$lightparms(light$light$lparm)"
    }
  }

  ### removed old statflag mess (statflag=!complexvalflag was subtype of real!)

  ### new flag mess: set non-global flags passed to tksurfer at button press
  if { ![info exists renderscanlists($page,colscaletype)] } {
    colscaletypefromrendertype $page  ;# bak compat: don't redef config'd
  }
  if {$renderscanlists($page,colscaletype) == "cplx"} {
    set complexvalflag 1; set fieldsignflag 0; set fstatflag 0; set tstatflag 0
  }
  if {$renderscanlists($page,colscaletype) == "fs"} {
    set complexvalflag 0; set fieldsignflag 1; set fstatflag 0; set tstatflag 0
  }
  if {$renderscanlists($page,colscaletype) == "vstat"} {  ;# old: guess t
    set complexvalflag 0; set fieldsignflag 1; set fstatflag 0; set tstatflag 1
  }
  # next 2 must be passed via env (til change to -opts like medtestrender)
  if {$renderscanlists($page,colscaletype) == "fstat"} {
    set complexvalflag 0; set fieldsignflag 1; set fstatflag 1; set tstatflag 0
  }
  if {$renderscanlists($page,colscaletype) == "tstat"} {
    set complexvalflag 0; set fieldsignflag 1; set fstatflag 0; set tstatflag 1
  }
  if {$renderscanlists($page,colscaletype) == "real"} {
    set complexvalflag 0; set fieldsignflag 0; set fstatflag 0; set tstatflag 0
  }
  set rname $realname
  set iname $complexname
  if {$renderscanlists($page,fourierampflag)} {
    set rname $amprealname
    set iname $ampcomplexname
  }
  # export 2 non-global colscaletype-derived flags to update panel, used below
  set renderscanlists($page,complexvalflag) $complexvalflag
  set renderscanlists($page,fieldsignflag) $fieldsignflag

  ### check missing entries (TODO: update for new parms)
  foreach enum "smoothstepsrend smoothstepsstat \
      fthresh fslope fmid $hemi,angle_offset angle_cycles" {
    if {$sessionscanlists($page,type) == "fsscan" && \
        $enum == "smoothstepsrend"} { continue }
    set val $renderscanlists($page,$enum)
    if {$val == ""} {
      confirmalert "Render: missing value for: $enum"
      clear1time; return
    }
    if ![isnum $val] {
      confirmalert "Render: bad value ($val) for $enum"
      clear1time; return
    }
  }
  foreach estr "bfloatstem viewstcl flattcl" {
    set val $renderscanlists($page,$estr)
    if {$val == ""} {
      confirmalert "Render: missing value for: $estr"
      clear1time; return
    }
  }
  if ![info exists renderscanlists($page,renderlisttype)] {
    set renderscanlists($page,renderlisttype) one   ;# fix older csurf.dat
  }

  ### check csurf-visible ColorScale/DataType mismatches
  set colscale $renderscanlists($page,colscale)
  if {$renderscanlists($page,colscaletype) == "real"} {
    if {$colscale == 0 || $colscale == 1 || $colscale == 4 || $colscale == 14} {
      confirmalert " Render: Data Type and Color Scale mismatch:\n\n\
                     Data Type -> real-valued\n\
                     Color Scale -> complex-valued\n\n\ Change either one"
      clear1time; return
    }
  }
  if {$renderscanlists($page,colscaletype) == "cplx"} {
    if {$colscale == 6 || $colscale == 11 || $colscale == 12} {
      confirmalert " Render: Data Type and Color Scale mismatch:\n\n\
                     Data Type -> complex-valued\n\
                     Color Scale -> real-valued\n\n\ Change either one"
      clear1time; return
    }
  }
  if {$renderscanlists($page,colscaletype) == "fs"} {
    if {$colscale != 9} {
      confirmalert " Render: Data Type fieldsign -> set Color Scale \"fs\""
      clear1time; return
    }
  }

  ### warn cmplx Paintfile is *not* infix-stripped (e.g., set to real statfile)
  if {$renderscanlists($page,complexvalflag)} {
    foreach infix "$cplxstatname1 $cplxstatname2 $cplxstatname3 \
     $cplxstatname4 $cplxstatname5 $cplxstatname6 $realpname $dispername" {
      if [string match *${infix} $renderscanlists($page,bfloatstem)] {
        confirmalert " Render: Complex (2-comp) Data Type selected,\n\
                     but Paintfile infix indicates it is real-valued:\n\
                     \n    Paintfile infix is:  \"$infix\"\n\n\
                     \n    (1) Select complex Paintfile (either one of pair)\n\
                     \n             or\n\
                     \n    (2) Change Data Type to real"
        clear1time; return
      } 
    }
  }

  ### convert: sbfloatstem/cplxstatname->tcl,stat{repl/mask/mult}flag->tksurfer
#xxx -- tksurfer args:-stat $sbfloatstem-$hemi.w, add statvar, fix realscripts
  #N.B.: next currently passed to *real* tclscripts as $maskfloatstem
  set sbfloatstem $renderscanlists($page,sbfloatstem)
  ## complex: translate complexampmodtype -> tksurfer stat{repl,mask,mult}flags 
  set complexampmodtype $renderscanlists($page,complexampmodtype)
  set statreplampflag 0; set statmaskampflag 0; set statmultampflag 0
  if {$complexampmodtype == "off"} { }
  if {$complexampmodtype == "repl"} { set statreplampflag 1 }
  if {$complexampmodtype == "mask"} { set statmaskampflag 1 }
  if {$complexampmodtype == "mult"} { set statmultampflag 1 }
  ## complex: get infix from curr/fixswfileprefs-created sbfloatstem for tclenv
  set tmpcplxstatname none
  if [string match *_? $renderscanlists($page,sbfloatstem)] {
    set tmpcplxstatname [string range $renderscanlists($page,sbfloatstem) \
      [expr [string length $renderscanlists($page,sbfloatstem)] - 2] end]
  }
  ## real: tksurfer maskflag
  if {$fstatflag || $tstatflag} { set statmaskampflag 1 }

  ### check stat mod/source consistency, statfile (TODO: surftestrendernopanel)
  set complexstatsource $renderscanlists($page,complexstatsource)
  if {$renderscanlists($page,complexvalflag)} {  ;# maybe fixed above
    if {$statmultampflag || $statmaskampflag || $statreplampflag} { ;#need stat
      ## mod/source consistency (16combos)
      if {$complexstatsource == "sig"} { ;#maybe user reset can't guess correct
        confirmalert \
               " Render: CplxAmpMod is \"$complexampmodtype\", but\n\
                       CrossSubj Cmplx Stat Source is \"sig\" (i.e.,\n\
                       show complex amp data without mod):\n\n\
                       To \"$complexampmodtype\" amp of complex data, choose\n\
                       stat source other than \"sig\":\n\
                       \n    (1) \"cxF-amp\" (complex F on raw Fouier amp)\n\
                       \n             or\n\
                       \n    (2) \"cxF-sig\" (complex F on indiv sqrtF)\n\
                       \n             or\n\
                       \n    (3) \"cxR-ang\" (Rayleigh p on indiv angles)\n\
                       \n             or\n\
                       \n    (4) \"t-sig\"   (t-test on indiv sqrtF)\n\
                       \n             or\n\
                       \n    (5) \"t-pow\"   (t-test on indiv power/F)"
        clear1time; return
      }
      ## check statfile exists
      set statfile $fullscandir/${sbfloatstem}-$hemi.w
      if {$renderscanlists($page,complexampmodtype) != "off"} {
        if ![file exists $statfile] {
          confirmalert " Render: missing stat file:\n\n\    $statfile\n\n\
                         for complex amplitude replace/mask/multiply"
          clear1time; return
        }
      }
      ## warn xsub stat maybe incorrect because bfloat doesn't contain -mean-
      if { [info exists sessionscanlists($page,type)] && \
           $sessionscanlists($page,type) == "sphavgscan"} {
        set i [string first -mean- $renderscanlists($page,bfloatstem)]
        if {$i == -1} {  ;# warn maybe stat misload because subst failed, HOWTO
          confirmalert " N.B.: Paintfile has no \"-mean-\" infix:\n\n\
                         eccen/polar/twocond scripts will fail to find\n\
                         matching stats file for replace/mask/multiply\n\n\
                         To manually replace/mask/multiply the amplitude\n\
                         of complex data using surfer tools:\n\
                         \n    (1)   enter stat wfile in \"val:\" field\
                         \n    (2)   R        (read_binary_values)\
                         \n    (3)   S/V     (swap_stat_val)\
                         \n    (4)   enter imaginary wfile in \"val:\" field\
                         \n    (5)   R        (read_binary_values)\
                         \n    (6)   PUSH  (push_val_val2)\
                         \n    (7)   enter real wfile in \"val:\" field\
                         \n    (8)   R        (read_binary_values)\n\
                         \n                or\n\
                         \n    click \"CplxAmpMod\" to \"off\""
        }
      }
    } else {  ;# mod "off", but alt stat source selected, warn no effect
      if {$complexstatsource != "sig"} {
        set buttext none
        if {$complexstatsource == "fclu"}  { set buttext sig+(clust)Fmask }
        if {$complexstatsource == "famp"}  { set buttext cxF-amp }
        if {$complexstatsource == "fsig"}  { set buttext cxF-sig }
        if {$complexstatsource == "raang"} { set buttext cxR-ang }
        if {$complexstatsource == "tsig"}  { set buttext t-sig }
        if {$complexstatsource == "tpow"}  { set buttext t-pow }
        confirmalert " Render: CrossSubj Cmplx Stat Source selected,\n\
                       (\"$buttext\"), but CplxAmpMod is \"off\":\n\n\
                       Complex data display will ignore selected\n\
                       stat source w/o one of the following:\n\
                       \n    (1) \"repl\"     (replace amp w/stat)\n\
                       \n             or\n\
                       \n    (2) \"mask\"   (fthresh mask amp w/stat)\n\
                       \n             or\n\
                       \n    (3) \"mult\"    (multiply amp by stat)\n\n\
                       \n    Viewing complex data without modification\
                       \n    (resetting stat source to \"sig\")"
        set renderscanlists($page,complexstatsource) sig
        set tmpcplxstatname none
      }
    }
  } else { ;# real data: warn no effect of complex mod/source
    if { $complexampmodtype == "repl" || $complexampmodtype == "mask" || \
         $complexampmodtype == "mult" || \
         $complexstatsource == "famp" || $complexstatsource == "fsig" || \
         $complexstatsource == "tsig" || $complexstatsource == "raang" || \
         $complexstatsource == "tpow" } {
      confirmalert " Render: real-valued data:\n\n\
                     Complex Stat Mod/Source settings ignored"
    }
    if {$fstatflag || $tstatflag} {  ;# req statmask
      set statfile $fullscandir/${sbfloatstem}-$hemi.w
      if ![file exists $statfile] {
        confirmalert " Render: missing stat file:\n\n\    $statfile\n\n\
                       for Data Type: real+Fmsk or real+tmsk"
        clear1time; return
      }
    }
  } ;# real/cplx consistency/file checks

  ### finally make tksurfer command line (some vars always passed via env)
  ## surferdir: scan1=>scan1, image/scan1=>scan1, 10764/003/scan1=>003/scan1
  set dir [trimoneparent $page]   ;# tksurfer's sessiondir child of $session

  ## default rawdata args if missing or empty (e.g.,surfavg scandir, notfour)
  if { ![info exists functscanlists($page,imagepatt)] || \
        $functscanlists($page,imagepatt) == ""} {
    set functscanlists($page,imagepatt) NO-RAW-IMAGE-DATA
    putlog "### imagepatt for $page set to \"NO-RAW-IMAGE-DATA\""
  }
  if { ![info exists functscanlists($page,regdat)] || \
        $functscanlists($page,regdat) == ""} {
    set functscanlists($page,regdat) register.dat
    putlog "### regdat for $page set to \"register.dat\""
  }
  if { ![info exists functscanlists($page,stimcycles)] || \
        $functscanlists($page,stimcycles) == ""} {
    set functscanlists($page,stimcycles) 1
    putlog "### stimcycles for $page set to \"1\""
  }
  if { ![info exists functscanlists($page,paintnormtype)] || \
       $functscanlists($page,paintnormtype) == ""} {
    set functscanlists($page,paintnormtype) mm
    putlog "### paintnormtype for $page set to \"mm\""
  }
  if { ![info exists functscanlists($page,paintdmin)] || \
       $functscanlists($page,paintdmin) == ""} {
    set functscanlists($page,paintdmin) 0.0
    putlog "### paintdmin for $page set to \"0.0\""
  }
  if { ![info exists functscanlists($page,paintdmax)] || \
       $functscanlists($page,paintdmax) == ""} {
    set functscanlists($page,paintdmax) 2.0
    putlog "### paintdmax for $page set to \"2.0\""
  }
  # next only affects rawdata timecourse dump
  set midsamp [expr $functscanlists($page,paintdmin) + \
                    ( ($functscanlists($page,paintdmax) - \
                       $functscanlists($page,paintdmin) ) / 2.0)]

  ## current colscale-sensitive default missing LUT file
  if {$colscale == 12} {
    defmissinglutfile real  ;# won't overwrite existing
  }
  if {$colscale == 13 && $renderscanlists($page,colscaletype) == "cplx"} {
    confirmalert "TODO: auto-default missing complex amp LUT\n\n\
                  For now: use tksurfer \"ED\" to create/edit default"
  }
  if {$colscale == 14 && $renderscanlists($page,colscaletype) == "cplx"} {
    if {$renderscanlists($page,rendertype) == "eccen"} {
      defmissinglutfile eccen
    }
    if {$renderscanlists($page,rendertype) == "polar"} {
      defmissinglutfile polar
    }
  }

  ## get floatstem{list}: selected *.w file, last-extracted-list, all-list
  # start w/single bfloatstem in list
  set floatstemlist floatstem=$renderscanlists($page,bfloatstem)
  # errors
  if {$renderscanlists($page,renderlisttype) == "one"} {
    if {$floatstemlist == "floatstem=-multiple-"} {
      confirmalert "Multi Render: use \"last\" or \"all\", or select\
                    one Painted VertexList Prefix"
      clear1time; return
    }
    if {$renderscanlists($page,rgbname) == "-multiple-"} {
      confirmalert "Render: enter a Saved Images Prefix"
      clear1time; return
    }
  }
  if {$renderscanlists($page,renderlisttype) != "one" && \
      $libscript != "real-views.tcl" && $libscript != "real-flat.tcl"} {
    confirmalert "Multi Render: \"last\",\"all\" only work \
                  with \"real\" scripts: \n\nreal-{views,flat}.tcl"
    clear1time; return
  }
  # overwrite single w/"last"-list if *.w multi-brik extract
  if {$renderscanlists($page,renderlisttype) == "last"} {
    if { ![info exists functscanlists($page,statformat)] || \
         $functscanlists($page,statformat) != "brikmulti"} {
      confirmalert "Multi Render: imported stats extraction to render:\n\
                    \"last\" is for rendering multiple sub-briks\
                    extracted from imported AFNI stats brik"
      clear1time; return
    }
    set multiprefix $functscanlists($page,multiprefix)
    set multiinfix $functscanlists($page,multiinfix)
    set floatstemlist ""
    set stemcnt 0
    foreach valuefile [getsortedvaluefilelist $page] {
      if {$functscanlists($page,$valuefile,extractflag)} { ;# => not -unset-
        set bfloatstem $functscanlists($page,$valuefile,bfloatstem)
        set infixedfloatstem ${multiprefix}${bfloatstem}${multiinfix}
        lappend floatstemlist \
          floatstem[format "%03d" $stemcnt]=[file tail $infixedfloatstem]
        incr stemcnt
      }
    }
    if {$floatstemlist == ""} {
      confirmalert "Multi Render: empty list for last extraction\n\
                    use \"all\", or select one Painted VertexList Prefix"
      clear1time; return
    }
  }
  # overwrite single w/all *.w's list (ignoring complex) if "all"
  if {$renderscanlists($page,renderlisttype) == "all"} {
    set floatstemlist ""
    set stemcnt 0
    #TODO: skip non-complex if complex, fix cplx scripts to accept list
    foreach fullfloatstem [rmcomplexstems [getuniqwfilelist $page]] {
      lappend floatstemlist \
        floatstem[format "%03d" $stemcnt]=[file tail $fullfloatstem]
      incr stemcnt
     }
    if {$floatstemlist == ""} {
      confirmalert "Multi Render: empty list for render \"all\"\
                    (N.B. complex stems from Fourier analysis ignored)"
      clear1time; return
    }
  }

  ### optional surf2surf wfiles to ico, setup display on fsaverage
  set name2 $name  ;# don't change global (callbacks)
  if {$sing2fsavgflag} {
    foreach path "$env(FUNCTIONALS_DIR) $env(SUBJECTS_DIR)" {
      ### hash in path breaks mri_surf2surf (weird error: bad RAS to RAS xform)
      if { [string first "#" $path] != -1 } {  ;# discovered Jul 2021
        confirmalert "Re-sample to $fsaverage: \"#\" found in input file path:\
                  \n\n    $path\
                  \n\nwhich will cause mri_surf2surf to fail.\
                  \n\nMove this dir to location without a \"#\"\
                   \nin path, and try again"
        return
      }
    }
    set srchemi $hemi
    set trghemi $hemi
    if {$oppfsavghemiflag} {
      if {$srchemi == "rh"} { set trghemi lh }
      if {$srchemi == "lh"} { set trghemi rh }
#xxxxxxxx -- opphemi: unfinished
      set fsavgsurf $env(SUBJECTS_DIR)/${fsaverage}_sym/surf/$trghemi.$surfext
    } else {
      set fsavgsurf $env(SUBJECTS_DIR)/$fsaverage/surf/$trghemi.$surfext
    }
    if ![file exists $fsavgsurf] {
      confirmalert "Re-sample to $fsaverage: target surface missing:\
                    \n\n    $fsavgsurf\
                    \n\nFirst copy subject $fsaverage (and ${fsaverage}_sym)\
                    \nto SUBJECTS_DIR \"$env(SUBJECTS_DIR)\""
      clear1time; return
    }
    ## resample real or cplx (N.B. -trg_type curv -> out: $hemi.<stem>[nosuff])
    if {$complexvalflag} {
      set infixlist "$rname $iname"
    } else {
      set infixlist { "" }  ;# one empty element
    }
    set bfloatstem [lindex [split $floatstemlist "="] 1]  ;# rm "floatstem="
    # check overwrite (first file only), allow reuse
    set infix0 [lindex $infixlist 0]
    set found 0
    set firstout $fullscandir/fsavg-${bfloatstem}${infix0}-$trghemi.w
    if [file exists $firstout] { set found 1 }
    set dosurf2surf 1
    if {!$force && $found} {
      set resp [okreplace "" \
          "Re-sampled-to-$fsaverage file:\n\n    $firstout\n\nalready exists" \
          "Use Existing" "Re-sample Again"]
      if {$resp == 0} { clear1time; return }  ;# cancel
      if {$resp == 1} { set dosurf2surf 0 }     ;# use existing
      if {$resp == 2} { set dosurf2surf 1 }     ;# redo re-sample
    }
    if {$dosurf2surf} {
      foreach infix $infixlist {  ;# resamp infix="" or real/cplx
        set fullwfile $fullscandir/${bfloatstem}${infix}-$srchemi.w
        if ![file exists $fullwfile] {
          confirmalert "Re-sample to $fsaverage: infile missing:\
                        \n\n    $fullwfile\n\nfirst do PAINT"
          clear1time; return
        }
        if {!$oppfsavghemiflag} {
          ### TODO: write a full-rank output so can use ico 2nd resamp
          set command "$bindir/mri_surf2surf \
            --srcsubject $name \
            --hemi $hemi \
            --srcsurfval [backslashspaces $fullwfile] \
            --src_type w \
            --trgsubject ico \
            --trgsurfval [backslashspaces \
                $fullscandir/fsavg-${bfloatstem}${infix}-$trghemi] \
            --trgicoorder 7 \
            --trg_type w \
            --frame 0 \
            --mapmethod nnfr \
            --noreshape"
        } else {
#xxxxxxxx -- opphemi: unfinished: reg to fsaverage_sym must be there, TODO:path
          set fullflipfile "#############"   ;# TODO: in subject dir??
          if ![file exists $fullflipfile] {
            confirmalert "Re-sample to opp hemi ${fsaverage}_sym: missing:\
                          \n\n    $fullflipfile\n\nfirst do Register->Sym"
            clear1time; return
          }
#xxxxxxxx -- opphemi: unfinished: reg to fsaverage_sym has to be there,flip hemi
# N.B.:  --{src,trg}hemi => requires sym reg output: lh.rh.$surf
# TODO: use reg to sym w/appropriate flags for mri_surf2surf
          set command "$bindir/mri_surf2surf"  ;# TODO: cmdline
        }
        runacmd \
          "$command" $surfrenderbu "SURFACE-STATS  " surfinput $surflog surfpid
        tkwait variable surfpid
      }
      # resample optional stats
      if {$sbfloatstem != "-no_mask-"} {
        set fullwfile $fullscandir/${sbfloatstem}-$srchemi.w
        if ![file exists $fullwfile] {
          confirmalert "Re-sample to $fsaverage: infile missing:\
                        \n\n    $fullwfile\n\nfirst do PAINT"
        }
        if {!$oppfsavghemiflag} {
          ### TODO: write a full-rank output so can use ico 2nd resamp
          set command "$bindir/mri_surf2surf \
            --srcsubject $name \
            --hemi $hemi \
            --srcsurfval [backslashspaces $fullwfile] \
            --src_type w \
            --trgsubject ico \
            --trgsurfval \
                [backslashspaces $fullscandir/fsavg-${sbfloatstem}-$trghemi] \
            --trgicoorder 7 \
            --trg_type w \
            --frame 0 \
            --mapmethod nnfr \
            --noreshape"
        } else {
#xxxxxxxx -- opphemi: unfinished: TODO: as above
        }
        runacmd \
          "$command" $surfrenderbu "SURFACE-STATS  " surfinput $surflog surfpid
        tkwait variable surfpid
      }
    }
    ## reset localvars ($name2,$floatstemlist,$sbfloatstem) for cmdline below
#xxxxxxxx -- opphemi: unfinished
    if {!$oppfsavghemiflag} {
      set name2 $fsaverage
    } else {
      set name2 ${fsaverage}_sym
    }
    set floatstemlist floatstem=fsavg-$bfloatstem  ;# real or complex
    if {$sbfloatstem != "-no_mask-"} { set sbfloatstem fsavg-$sbfloatstem }

    ### optional 2nd surf2surf to other sub after samp2ico, setup disp other
    if {$sing2singflag} {  ;# req sing2fsavgflag && !oppfsavghemiflag above
      set infix0 [lindex $infixlist 0]
      set found 0
      set firstout \
        $fullscandir/$anothersub1time-${bfloatstem}${infix0}-$trghemi.w
      if [file exists $firstout] { set found 1 }
      set dosurf2surf 1
      if {!$force && $found} {
        set resp [okreplace "" \
   "Re-sampled-to-$anothersub1time file:\n\n    $firstout\n\nalready exists" \
          "Use Existing" "Re-sample Again"]
        if {$resp == 0} { clear1time; return }  ;# cancel
        if {$resp == 1} { set dosurf2surf 0 }     ;# use existing
        if {$resp == 2} { set dosurf2surf 1 }     ;# redo re-sample
      }
      if {$dosurf2surf} {
        confirmalert "Re-sample fsaverage surface data:\
                  \n\n    $bfloatstem\
                  \n\na second time, back to different subject:\
                  \n\n    $name  ->  fsaverage  ->  $anothersub1time"
        foreach infix $infixlist {  ;# resamp infix="" or real/cplx
          set fullwfile $fullscandir/fsavg-${bfloatstem}${infix}-$srchemi.w
          if ![file exists $fullwfile] {
            confirmalert "Re-sample to $anothersub1time: infile missing:\
                          \n\n    $fullwfile\n\nfirst do PAINT"
            clear1time; return
          }
#xxx -- sing2sing: TODO: write all vertices so can use ico, rev face ord
          ### TODO: if start w/notfullrank sing subj wfile, can't use ico (rev)
          #--srcsubject ico: ERROR: nIcoVtxs = 163498 does not match an IcoOrder
          set command "$bindir/mri_surf2surf \
            --srcsubject fsaverage \
            --hemi $hemi \
            --srcsurfval [backslashspaces $fullwfile] \
            --src_type w \
            --trgsubject $anothersub1time \
            --trgsurfval [backslashspaces \
                $fullscandir/$anothersub1time-${bfloatstem}${infix}-$trghemi \
            --trg_type w \
            --frame 0 \
            --mapmethod nnfr"
          runacmd \
           "$command" $surfrenderbu "SURFACE-STATS  " surfinput $surflog surfpid
          tkwait variable surfpid
        }
      }
      # resample optional stats
      if {$sbfloatstem != "-no_mask-"} {
        set fullwfile $fullscandir/fsavg-${sbfloatstem}-$srchemi.w
        if ![file exists $fullwfile] {
          confirmalert "Re-sample to $anothersub1time: infile missing:\
                        \n\n    $fullwfile\n\nfirst do PAINT"
          clear1time; return
        }
        ### TODO: starting w/not-full-rank sing subj wfile, can't use ico (rev)
        # --srcsubject ico: ERROR: nIcoVtxs = 163498 does not match an IcoOrder
#xxx -- sing2sing: TODO: write all vertices so can use ico, rev face ord
        set command "$bindir/mri_surf2surf \
          --srcsubject fsaverage \
          --hemi $hemi \
          --srcsurfval [backslashspaces $fullwfile] \
          --src_type w \
          --trgsubject $anothersub1time \
          --trgsurfval [backslashspaces \
              $fullscandir/$anothersub1time-${sbfloatstem}${infix}-$trghemi] \
          --trgfmt paint \
          --frame 0 \
          --mapmethod nnfr"
        runacmd \
          "$command" $surfrenderbu "SURFACE-STATS  " surfinput $surflog surfpid
        tkwait variable surfpid
      }
      ## 2nd reset localvars ($name2,$floatstemlist,$sbfloatstem) cmdline below
      set name2 $anothersub1time
      set floatstemlist floatstem=$anothersub1time-$bfloatstem ;# real or cmplx
      if {$sbfloatstem != "-no_mask-"} {
        set sbfloatstem $anothersub1time-$sbfloatstem
      }
    }

  }  ;# finally ready to start
  clear1time

  ### make tksurfer cmdline (only 1 vers: most by options, a few via env)
  ## NOTES on non-tksurfer vars passed to tcl scripts via readenv.tcl
  # patchname -- multi-part suffix: e.g., $hemi.occip.patch.flat
  # dir -- no-image scandir, typically subdir of $session/image
  # floatstem/floatstemlist -- wfiles stem: $floatstem$infix-$hemi.w
  # realname/complexname/cplxstatname -- wfile infix: _r, _i, _f, _g, _a, _b
  # smoothsteps -- passed to scripts
  # rgbname -- stem for rgb bitmaps: $rgbname-$hemi-$surfext-$view.rgb
  # vlist -- list of env vars indicating which views to render
  # rgbname via env (vs. -rgbname) since tcl scripts override init C val
  ### pass a few vars to tcl render scripts via env+readenv.tcl
  set tclenv " \
    patchname=$patchext \
    dir=$dir \
    scandir=$dir \
    $floatstemlist \
    maskfloatstem=$sbfloatstem \
    realname=$rname \
    complexname=$iname \
    cplxstatname=$tmpcplxstatname \
    smoothsteps=$renderscanlists($page,smoothstepsrend) \
    smoothstepsstat=$renderscanlists($page,smoothstepsstat) \
    cpxangrealampflag=$renderscanlists($page,cpxangrealampflag) \
    rgbname=$renderscanlists($page,rgbname) \
    $vlist \
    $llist \
    "
  if {!$exitrenderflag} { set tclenv "$tclenv noexit=1" }
  if {!$savergbflag} { set tclenv "$tclenv nosave=1" }
  ### pass most vars to tksurfer via options
  set glxdepthopt ""
  if {$minglxdepthflag} { set glxdepthopt "-glxdepth 12" }
  set normdsampopts ""
  if {$functscanlists($page,normdsampsearchflag)} {
    ## search along normal
    set normdsampopts "-normdsampsearchflag 1 \
                       -normddstep $functscanlists($page,paintdstep) \
                       $normdsampopts"
    if {$functscanlists($page,paintnormtype) == "mm"} {
      set normdsampopts "-normdfracflag 0 \
                         -normdsamp $functscanlists($page,paintdmin) \
                         -normdmax $functscanlists($page,paintdmax) \
                         $normdsampopts"
    }
    if {$functscanlists($page,paintnormtype) == "frac"} {
      set normdsampopts "-normdfracflag 1 \
                         -normdfracsamp $functscanlists($page,paintdmin) \
                         -normdfracmax $functscanlists($page,paintdmax) \
                         $normdsampopts"
    }
  } else {
    ## single samp pnt (warn use midpoint b/c of non-zero range => too naggy?)
    #if {$functscanlists($page,paintdmin) != $functscanlists($page,paintdmax)} {
    #  if {!$force} {
    #    confirmalert "For live sample/PAINT 3D Timeseries/Stats to surf:\
    #              \n\nnorm search OFF, but non-zero range:\
    #                \n(settings on Setup Align/Funct panel):\
    #              \n\n    min = $functscanlists($page,paintdmin)\
    #                \n    max = $functscanlists($page,paintdmax)\
    #              \n\nN.B.: using midpoint = $midsamp"
    #  }
    #}
    ## 160527: also set maxs so defs don't cause accidental midpoint
    if {$functscanlists($page,paintnormtype) == "mm"} {
      set normdsampopts "-normdfracflag 0 \
                         -normdsamp $midsamp \
                         -normdmax $midsamp"
    }
    if {$functscanlists($page,paintnormtype) == "frac"} {
      set normdsampopts "-normdfracflag 1 \
                         -normdfracsamp $midsamp \
                         -normdfracmax $midsamp"
    }
  }
  # TODO: merge next two flags when write_label_timecourses rewritten
  if {$functscanlists($page,normdsampuniqvoxflag) ||
      $functscanlists($page,normdsampuniqvtxflag)} {  ;# force like tksurfer.c
    set normdsampopts "$normdsampopts -normdsampuniqvoxflag 1"
  }
  if {$functscanlists($page,normdsampuniqvtxflag)} {
    set normdsampopts "$normdsampopts -normdsampuniqvtxflag 1"
  }
  if {$functscanlists($page,normdsampallflag)} {
    set normdsampopts "$normdsampopts -normdsampallflag 1"
  }
  if {$functscanlists($page,samevtxthickflag)} {
    set normdsampopts "$normdsampopts -samevtxthickflag 1"
  }
  if {!$appnapstateforced} {
    set appnaparg -1  ;# let tksurfer decide
  } else {
    set appnaparg $mac_appnap_hack
  }
  # hack^2: on 10.15, very slow log hangs GLwin open if appnap hack because
  #   final tksurfer.tcl tkwait hangs/blocks even tho tk win completely drawn
  #   (GLwin not drawn til tksurfer.tcl returns, tksurfer.c event loop entered)
  if {$logflag == 1 && $appnaparg == 1} { set appnaparg 0 }
  set opts " \
    -tksurferinterface mini \
    -scandir $dir \
    -wmgmext $functscanlists($page,paintext) \
    -dividequadsflag $surfparms(dividequadsflag) \
    -undividequadsflag $surfparms(undividequadsflag) \
    -newquadoutputflag $surfparms(newquadoutputflag) \
    -newcurvareaoutputflag $surfparms(newcurvareaoutputflag) \
    -writefloatpatchflag $flattenparms(writefloatpatchflag) \
    -overlayflag 1 \
    -regdat $functscanlists($page,regdat) \
    -rawdata $functscanlists($page,imagepatt) \
    -stimcycles $functscanlists($page,stimcycles) \
    -cslope 3.0 \
    -cmid 0.0 \
    -colscale $renderscanlists($page,colscale) \
    -interpolatelutflag $renderscanlists($page,interpolatelutflag) \
    -botedgelutflag $renderscanlists($page,botedgelutflag) \
    -zerosymmfadeflag $renderscanlists($page,zerosymmfadeflag) \
    -complexvalflag $complexvalflag \
    -invphaseflag $renderscanlists($page,invphaseflag) \
    -revphaseflag $renderscanlists($page,$hemi,revphaseflag) \
    -truncphaseflag $renderscanlists($page,truncphaseflag) \
    -softtruncphaseflag $renderscanlists($page,softtruncphaseflag) \
    -truncphasemin $renderscanlists($page,$hemi,truncphasemin) \
    -truncphasemax $renderscanlists($page,$hemi,truncphasemax) \
    -nonbinaryfsflag $renderscanlists($page,nonbinaryfsflag) \
    -statreplampflag $statreplampflag \
    -statmaskampflag $statmaskampflag \
    -statmultampflag $statmultampflag \
    -fthresh $renderscanlists($page,fthresh) \
    -fslope $renderscanlists($page,fslope) \
    -fmid $renderscanlists($page,fmid) \
    -sfthresh $renderscanlists($page,sfthresh) \
    -sfslope $renderscanlists($page,sfslope) \
    -sfmid $renderscanlists($page,sfmid) \
    -angle_offset $renderscanlists($page,$hemi,angle_offset) \
    -angle_cycles $renderscanlists($page,angle_cycles) \
    -fadef $renderscanlists($page,fadef) \
    -ipsiyellowfact $renderscanlists($page,ipsiyellowfact) \
    -surfcolor $renderscanlists($page,surfcolor) \
    -offset $lightparms(offset) \
    -cvfact $lightparms(cvfact) \
    -fontfile $postclparms(fontfile) \
    -fullpolrectflag 0 \
    -noninteccendiskflag 0 \
    -scalebarflag $renderscanlists($page,scalebarflag) \
    -colscalebarflag $renderscanlists($page,colscalebarflag) \
    -smallscreenflag $smallscreenflag \
    -doublebufferflag $doublebufferflag \
    $glxdepthopt \
    $normdsampopts \
    -tiffoutflag $tiffoutflag \
    -black2transparentflag $black2transparentflag \
    -tksurferlogflag $tksurferlogflag \
    -renderoffscreen 0 \
    -macappnaphackflag $appnaparg \
    "
  #-offset $renderscanlists($page,offset) -> now subj-specific ExpertParms
  #-cvfact $renderscanlists($page,cvfact) -> now subj-specific ExpertParms
#xxx -- next MacOSX 10.11 fail: can't use env: PATH/DYLD not passed to subshell
  #set command \
  #  "env $tclenv $bindir/tksurfer $name2 $hemi $surfext -tcl $libscript $opts"
  set id [open $etmptcl w 0666]
  foreach line $tclenv { puts $id $line }  ;# bypass Mac 10.11+ env block
  close $id
  set command "$bindir/tksurfer $name2 $hemi $surfext -tcl $libscript $opts \
    -csurftclenv $etmptcl"
  cdfunctscripts
  runacmd "$command" $surfrenderbu "SURFACE-STATS  " surfinput $surflog surfpid
  tkwait variable surfpid

  writearrayparms $datfile render  ;# save on purple kill (prev commented out)
}

###########################################################################
### VOLUME-STATS button command (View Functional Data panel)
###########################################################################
proc medtestrender { nbwin } {
  global medlog medpid medrenderbu
  global name hemi patchext env session iscandir mtmptcl surfdir volumedir
  global medsurfflag origdir origext statname realfname realfclustname
  global bindir sessionscanlists renderscanlists functscanlists
  global subjectscombo tiffoutflag savergbflag
  global realname complexname amprealname ampcomplexname realfname
  global smallscreenflag doublebufferflag minglxdepthflag tkmeditlogflag
  global wfileprefscombo mac_appnap_hack appnapstateforced

  set page [demanglepath [$nbwin raised]]
  set iscandir $page
  if {$medpid != -1} {
    if { [exec uname] == "Darwin" } {  ;# err to pipe for setuid/DYLD warning
      set currproc [lrange [exec ps uxww |& grep $medpid] 10 end]  ;# BSD
    } elseif { [exec uname] == "Linux" } {
      set currproc [lrange [exec ps uxww |& grep $medpid] 10 end]  ;# Linux
    } else {
      set currproc [lrange [exec ps af |& grep $medpid] 7 end]     ;# old sys5
    }
    confirmalert "Csurf: Start a second csurf to run a second tkmedit"
    return
  }
  if { ![info exists wfileprefscombo($page)] ||
       ![winfo exists $wfileprefscombo($page)] } {  ;# Paintfile
    confirmalert "first configure scandir for Render (top)"
    return
  }
  if ![info exists renderscanlists($page,rgbname)] { return }
  if { [checknamefile] != "match" } { return }
  if {$hemi == "both"} { set hemi rh }   ;# skip checkbothhemi

  ### check underlay (COR first, then .mgz -- like VOLUME button)
  set tkregtargdir orig
  if [info exists functscanlists($page,tkregtargdir)] { ;# for old csurf.dat
    set tkregtargdir $functscanlists($page,tkregtargdir) ;# on Setup Funct panel
  }
  set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$tkregtargdir/COR-001
  #set undertype $origdir        ;# original: hard-coded
  set undertype $tkregtargdir    ;# undertype will be passed to tkmedit
  set try1 $undertype/COR-001    ;# record for pop-up
  if ![file exists $firstim] {
    set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$tkregtargdir.mgz
    #set undertype $origdir.mgz
    set undertype $tkregtargdir.mgz
    set try2 $undertype
    if ![file exists $firstim] {
      set firstim $env(SUBJECTS_DIR)/$name/$volumedir/$tkregtargdir.mgh
      #set undertype $origdir.mgh
      set undertype $tkregtargdir.mgh
      set try3 $undertype
      if ![file exists $firstim] {
        confirmalert "Underlay volume not found in:\
                  \n\n$env(SUBJECTS_DIR)/$name/$volumedir\
                   \n\nLooked for:\
                   \n\n(1) $try1  (COR dir)\
                     \n(2) $try2\
                     \n(3) $try3"
        return
      }
    }
  }

  set surfexists 0
  set surf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$origext
  if [file exists $surf] { set surfexists 1 }

  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  set fullbfloatstem $fullscandir/$renderscanlists($page,bfloatstem)

  ### new flag mess: set non-global flags passed to tkmedit at button press
  if { ![info exists renderscanlists($page,colscaletype)] } {
    colscaletypefromrendertype $page  ;# bak compat: don't redef config'd
  } 
  set complexvalflag 0; set fieldsignflag 0; set vstatflag 0  ;# def is real
  if {$renderscanlists($page,colscaletype) == "cplx"} { ;# resets checkbox
    set complexvalflag 1; set fieldsignflag 0; set vstatflag 0
  }
  if {$renderscanlists($page,colscaletype) == "fs"} {
    set complexvalflag 0; set fieldsignflag 1; set vstatflag 0
  } 
  if {$renderscanlists($page,colscaletype) == "vstat" || \
      $renderscanlists($page,colscaletype) == "fstat" || \
      $renderscanlists($page,colscaletype) == "tstat"} {
    set complexvalflag 0; set fieldsignflag 0; set vstatflag 1
  } 
  if {$renderscanlists($page,colscaletype) == "real"} {
    set complexvalflag 0; set fieldsignflag 0; set vstatflag 0
  }
  set rname $realname
  set iname $complexname
  set fname $realfname
  set fname2 $realfclustname
  if {$renderscanlists($page,fourierampflag)} {
    set rname $amprealname
    set iname $ampcomplexname 
  }

  ### construct filename args passed to tkmedit
  $subjectscombo config -state disabled
  set statfilearg ""   ;# next 6 empty if reading upsamp
  set maskfilearg ""
  set statresargs ""
  set nslicesarg ""
  set regdatarg ""
  set rawdataarg ""
  set upstatfilearg ""
  set upmaskfilearg ""
  if {$sessionscanlists($page,type) == "sphavgscan"} {
    ### cross-subj volavg: -upreal/-upimag to load upsamp name if found
    # name convention: from volavgcxcmd
    if {$complexvalflag} {
      if {$renderscanlists($page,fourierampflag)} {
        set rfilebrikpatt "*-stats-vol_x+orig.BRIK"  ;# any real amp
        set ifilebrikpatt "*-stats-vol_y+orig.BRIK"  ;# any imag amp
      } else {
        set rfilebrikpatt "*-stats-vol_r+orig.BRIK"  ;# any real sig
        set ifilebrikpatt "*-stats-vol_i+orig.BRIK"  ;# any imag sig
      }
      set rupstatlist [glob -nocomplain $fullscandir/$rfilebrikpatt]
      set iupstatlist [glob -nocomplain $fullscandir/$ifilebrikpatt]
      # take first found (complex pair or real)
      if { [llength $rupstatlist] && [llength $iupstatlist] } {
        set upstatfilearg "-upreal [backslashspaces [lindex $rupstatlist 0]] \
                           -upimag [backslashspaces [lindex $iupstatlist 0]]"
        putlog "found complex volavg: $upstatfilearg"
      }
    } else { ;# real
      set rfilebrikpatt "*-stats-vol+orig.BRIK"  ;# no infix: real-valued
      set rupstatlist [glob -nocomplain $fullscandir/$rfilebrikpatt]
      if [llength $rupstatlist] {
        set upstatfilearg "-upreal [backslashspaces [lindex $upstatlist 0]]"
        putlog "found real volavg: $upstatfilearg"
      }
    }
  } else {  ;# single subject
    ### pick/chk non-upsamp infiles (tkmedit mk upsamp name from nonsub)
    #set statresargs "-statxres $functscanlists($page,xres) \
    #                 -statyres $functscanlists($page,yres)"
    #set nslicesarg "-nslices $functscanlists($page,slices)"
    ## Sep2013: tkmedit now reads HEAD (or count bfloats, read .hdr)
    set statresargs ""
    set nslicesarg ""
    ## Sep2013: next changed to relative, like surftestrender
    set regdatarg "-regdat $functscanlists($page,regdat)"
    set rawdataarg "-rawdata $functscanlists($page,imagepatt)"
    # name convention from: fourier.c
    if {$complexvalflag} {  ;# orig complex amp/stat
      if ![info exists functscanlists($page,phasestatformat)] {
        confirmalert " 3dRender: Phase Stat Format (Fourier panel)\n\
                       not yet set:\n\
                       Does scandir actually contain complex-valued stats?"
      } else {
        set phasestatformat $functscanlists($page,phasestatformat)
      }
      # ugh: *complex* bfloatstem *lacks* +orig
      if {$phasestatformat == "bfloat"} { set stemendpatt _%03d.bfloat }
      if {$phasestatformat == "afnibrik"} { set stemendpatt +orig.BRIK }
      # next (in case type .BRIK into entry)
      if [string match *.BRIK $fullbfloatstem] { set stemendpatt "" }
      set rfileformat ${fullbfloatstem}${rname}${stemendpatt}
      set ifileformat ${fullbfloatstem}${iname}${stemendpatt}
      if {$phasestatformat == "bfloat"} {
        set firstrfile [format "$rfileformat" 0]
        set firstifile [format "$ifileformat" 0]
      }
      if {$phasestatformat == "afnibrik"} {
        set firstrfile $rfileformat
        set firstifile $ifileformat
      }
      if { ![file exists $firstrfile] || ![file exists $firstifile] } {
        confirmalert " 3dRender: real or imag statfile not found:\n\n\
                       $firstrfile\n $firstifile"
        return
      }
      #set statfilearg "-complex $rfileformat $ifileformat" ;#old arg stillworks
      set statfilearg "-real [backslashspaces $rfileformat] \
                       -imag [backslashspaces $ifileformat]"
      if { [info exists renderscanlists($page,complexstatsource)] && \
           $renderscanlists($page,complexstatsource) == "fclu" } {
        # mask: look-for/require matching _f (cf. surf look order: _f,_h,_p,_q)
        set mfileformat ${fullbfloatstem}${fname}${stemendpatt}  ;# infix=_f
        if {$phasestatformat == "bfloat"} {
          set firstmfile [format "$mfileformat" 0]
        }
        if {$phasestatformat == "afnibrik"} { set firstmfile $mfileformat }
        if { ![file exists $firstmfile] } {
          confirmalert " 3dRender: mask statfile not found:\n\n\   $firstmfile"
          return
        }
        set maskfilearg "-mask [backslashspaces $mfileformat]"
        # then look for matching _h, use instead of _f if found
        set mfileformat ${fullbfloatstem}${fname2}${stemendpatt}  ;# infix=_h
        if {$phasestatformat == "bfloat"} {
          set firstmfile [format "$mfileformat" 0]
        }
        if {$phasestatformat == "afnibrik"} { set firstmfile $mfileformat }
        if [file exists $firstmfile] {
          if { [info exists renderscanlists($page,sbfloatstem)] && \
               [string match *${fname} $renderscanlists($page,sbfloatstem)] } {
            ;# don't replace _f with _h if StatMask Paintfile (wfile) is _f
          } else {
            set maskfilearg "-mask [backslashspaces $mfileformat]"
          }
        }
      }
    } elseif {$fieldsignflag} {
      confirmalert "3dRender: fieldsign has no 3d volume dataset"
      #return   ;# allow to display fieldsign on surface ribbon
    } elseif {$vstatflag} { ;# real + "Data Type" F/t statmask
      if ![info exists functscanlists($page,realstatformat)] {
        confirmalert " 3dRender: Real Output Stat Format (ExtStats panel)\n\
                       not yet set:\n\
                       Does scandir actually contain real-valued stats?"
        return
      } else {
        set realstatformat $functscanlists($page,realstatformat)
      }
      # ugh: real/mask bfloatstem *has* +orig
      if {$realstatformat == "bfloat"} { set stemendpatt _%03d.bfloat }
      if {$realstatformat == "afnibrik"} { set stemendpatt .BRIK }
      set rfileformat ${fullbfloatstem}${stemendpatt}
      set mfileformat $rfileformat
      # 3dDeconvolve: old/new versions of auto-gen BRICK_LAB label stems
      # convertfunctcmd: "thresh"->mask coef by clust, "clust"->clust stat
#xx -- TODO: run old 3dDeconvolve on buc05 to see if next 2 lines correct
      set tlistver1 { _coef-thresh+orig _t-st-clust+orig }
      set flistver1 { _LC@0@_coef-thresh+orig _F-stat-clust+orig }
      set tlistver2 { _GLT@0_Coef-clust+orig _GLT@0_Tstat-clust+orig }
      set flistver2 { _GLT@0_Coef-clust+orig _GLT_Fstat-clust+orig }
      if {$renderscanlists($page,colscaletype) == "tstat"} {
        set verlist [list $tlistver1 $tlistver2]
      }
      if {$renderscanlists($page,colscaletype) == "fstat"} {
        set verlist [list $flistver1 $flistver2]
      }
      set foundboth 0
      foreach pair $verlist {
        set coefsuff [lindex $pair 0]
        set clustsuff [lindex $pair 1]
        if [string match *$coefsuff $fullbfloatstem] {
          set mfileformat [string range $fullbfloatstem 0 \
                   [expr [string length $fullbfloatstem] - 1 - \
                   [string length $coefsuff]]]${clustsuff}${stemendpatt}
        }
        if { [file exists [format "$rfileformat" 0]]  && \
             [file exists [format "$mfileformat" 0]] } {
          set foundboth 1
          break
        }
      }
      if {!$foundboth} {
        confirmalert " 3dRender: coef/mask file pair not found:\n\n\
                       [format "$rfileformat" 0]\n\n\
                       [format "$mfileformat" 0]\n\n\
                       (to view unmasked real, Data Type: -> real)"
        return
      }
      set statfilearg "-real [backslashspaces $rfileformat]"
      set maskfilearg "-mask [backslashspaces $mfileformat]"
    } else {  ;# real, no mask
      set realstatformat afnibrik   ;# guess
      if [info exists functscanlists($page,realstatformat)] {
        set realstatformat $functscanlists($page,realstatformat)
      }
      if {$realstatformat == "bfloat"} { set stemendpatt _%03d.bfloat }
      if {$realstatformat == "afnibrik"} { set stemendpatt .BRIK }
      set rfileformat ${fullbfloatstem}${stemendpatt} ;# no realfname infix
      if ![file exists [format "$rfileformat" 0] ] {
        confirmalert " 3dRender: real overlay file not found:\n\n\
                       [format "$rfileformat" 0]"
        return
      }
      set statfilearg "-real [backslashspaces $rfileformat]"
    }
  } ;# single subject
  set followarg ""
  set doublebufferarg ""
  set glxdeptharg ""
  if {$smallscreenflag}   { set followarg "-followglwinflag 0" }
  if {!$doublebufferflag} { set doublebufferarg "-doublebufferflag 0" }
  if {$minglxdepthflag}   { set glxdeptharg "-glxdepth 12" }
  ### tkmedit script (for optional read surf)
  set id [open $mtmptcl w 0644]
  puts $id "source \"$env(CSURF_DIR)/lib/tcl/readenv.tcl\"" ;# space
  puts $id "open_window"
  puts $id "set plane \$cor"
  if {$surfexists} { puts $id "read_binary_surface" }
  puts $id "redraw"
  close $id
  # copy tkmedit script to (top/cmd) log
  putlog "\n# tkmedit tcl script: $mtmptcl"
  putlog "source \"$env(CSURF_DIR)/lib/tcl/readenv.tcl\""   ;# space
  putlog "open_window"
  putlog "set plane \$cor"
  if {$surfexists} { putlog "read_binary_surface" }
  putlog "redraw\n"
  ### default rawdata args if missing or empty (e.g.,surfavg scandir, notfour)
  if { ![info exists functscanlists($page,stimcycles)] || \
        $functscanlists($page,stimcycles) == ""} {
    set functscanlists($page,stimcycles) 1
    putlog "### stimcycles for $page set to \"1\""
  }
  ### appnap hack
  if {!$appnapstateforced} {
    set appnaparg -1  ;# let tksurfer decide
  } else {
    set appnaparg $mac_appnap_hack
  }
  ### pass all by options, run from scripts dir (allow spaces cmd path)
  # tkmedit defs $rgb to sess rgb if overlayflag (set by -real,-complex)
  set dir [trimoneparent $page]   ;# tkmedit's sessiondir child of $session
#xxx -- next MacOSX 10.11 fail: can't use env: PATH/DYLD not passed to subshell
  #set tclenv ""   ;# keep tclenv for tkmedit tcl script hacking
  #set command \
  #  "env $tclenv $bindir/tkmedit $name $undertype $hemi.$origext ... "
  set command \
    "$bindir/tkmedit $name $undertype $hemi.$origext \
      -tcl $mtmptcl \
      -tkmeditinterface mini2 \
      -scandir $dir \
      -complexvalflag $complexvalflag \
      $statfilearg \
      $maskfilearg \
      $statresargs \
      $nslicesarg \
      $regdatarg \
      $rawdataarg \
      $upstatfilearg \
      $upmaskfilearg \
      -stimcycles $functscanlists($page,stimcycles) \
      -kfwhm $renderscanlists($page,kfwhm) \
      -kcnt $renderscanlists($page,kcnt) \
      -smoothmaskflag $renderscanlists($page,smoothoverlaymaskflag) \
      -colscale $renderscanlists($page,colscale) \
      -revphaseflag $renderscanlists($page,$hemi,revphaseflag) \
      -truncphaseflag $renderscanlists($page,truncphaseflag) \
      -truncphasemin $renderscanlists($page,$hemi,truncphasemin) \
      -truncphasemax $renderscanlists($page,$hemi,truncphasemax) \
      -fthresh $renderscanlists($page,fthresh) \
      -fslope $renderscanlists($page,fslope) \
      -fmid $renderscanlists($page,fmid) \
      -sfthresh $renderscanlists($page,sfthresh) \
      -sfslope $renderscanlists($page,sfslope) \
      -sfmid $renderscanlists($page,sfmid) \
      -bwslope $renderscanlists($page,bwslope) \
      -bwmid $renderscanlists($page,bwmid) \
      -angle_offset $renderscanlists($page,$hemi,angle_offset) \
      -angle_cycles $renderscanlists($page,angle_cycles) \
      -fadef $renderscanlists($page,fadef) \
      -ipsiyellowfact $renderscanlists($page,ipsiyellowfact) \
      -rgbname $renderscanlists($page,rgbname) \
      -tiffoutflag $tiffoutflag \
      -tkmeditlogflag $tkmeditlogflag \
      -macappnaphackflag $appnaparg \
      $followarg \
      $doublebufferarg \
      $glxdeptharg \
    "
  runacmd "$command" $medrenderbu "VOLUME-STATS  " medinput $medlog medpid
  tkwait variable medpid
  rmlog $mtmptcl
  cdfunctscripts
}

### Unset Dir button (Setup Functional Scan Parameters panel)
proc unsetscan { nbwin aspect } {
  global structscanlists
  global sessionscanlists functscanlists renderscanlists
  global currpage prevpage

  set mpage [$nbwin raised]
  if {$mpage == ""} { return }
  set f [$nbwin subwidget $mpage]
  set page [demanglepath $mpage]
  if { [info commands $f.la] != "" } { destroy $f.la }

  # just unset flags so previous state will return if directory reconfig'd
  if {$aspect == "struct"} {
    if [info exists structscanlists($page,type)] {
      unset structscanlists($page,type)
    }
  }
  if {$aspect == "alignfunct"} {
    if [info exists sessionscanlists($page,type)] {
      if ![info exists functscanlists($page,extstatfunctims)] {
        unset sessionscanlists($page,type)
      } else {
        set functscanlists($page,extstatfunctims) 0
      }
    }
  }
  if {$aspect == "calcfield" || $aspect == "extstat"} {
    if [info exists sessionscanlists($page,type)] {
      unset sessionscanlists($page,type)
    }
  }
  if {$aspect == "rawavg"}    { set functscanlists($page,rawavgflag) 0 }
  if {$aspect == "calcfour"}  { set functscanlists($page,fourflag)   0 }
  if {$aspect == "calcrand"}  { set functscanlists($page,randflag)   0 }
  if {$aspect == "sigavg"}    { set functscanlists($page,sigavgflag) 0 }
  if {$aspect == "surfavg"}   { set functscanlists($page,surfavgflag) 0 }
  if {$aspect == "render"}    { set functscanlists($page,renderflag) 0 }

  set currpage $prevpage
  set prevpage def
}

### SPHEREAVG button command (Cross Sess Spherical Average panel)
proc sphavgcxcmd { } {
  global cmdlog sphereavgbu sphavgjob purplekillseq force
  global env session hemi surfdir bindir afnibindir bgcol runbgcol ffont
  global realname complexname amprealname ampcomplexname
  global cplxstatname1 cplxstatname2 cplxstatname4
  global amplname powname dispername ;# cplxstatname3->amplname, ...5->powname
  global sphereext regext
  global spgnums sphavgdir sphavglists
  global spgsessions spgsubjects spgscandirs spgvtxlistprefs spgmorphsurfs
  global spgstatbrikprefs
  global onearch

  if {$sphavgdir == "image/__no_dir__"} {
    confirmalert " Sphere Average:  No scandir for average\n\n\
                   Replace name:\n\n\     __no_dir__\n\n\
                   Make SphereAvg dir, try again"
    return
  }
  if ![info exists spgnums(00)] {
    confirmalert " Sphere Average:  no scans to average:\n\n\
                   For each session to average:\n\n\
                   (1) click ADD SESS button to make new blank line\n\
                   (2) select Session,Scandir,VtxListPref dropdowns\n\
                   (blank StatBrikStem OK)"
    return
  }
  ### hash in path breaks mri_surf2surf (weird error: bad RAS to RAS xform)
  foreach path "$env(FUNCTIONALS_DIR) $env(SUBJECTS_DIR)" { 
    if { [string first "#" $path] != -1 } {
      confirmalert "Sphere Average: \"#\" found in an input file path:\
                \n\n    $path\
                \n\nwhich will cause mri_surf2surf to fail.\
                \n\nMove this dir to location without a \"#\"\
                 \nin path, and try again"
      return
    }
  }
  set currhemi $hemi    ;# detach from main panel hemi

  ### conservative (in case it breaks something)
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog "sphavg: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  ### first check fields filled
  foreach num [lsort [array names spgnums]] {
    set n $num
    while { [string match 0* $n] } { set n [string range $n 1 end] } ;# fixhex
    set onebased [format "%02d" [expr $n + 1]]  ;# empty n OK
    if {$spgsessions($num) == ""} \
      { confirmalert "line $onebased: empty Session entry";     return }
    if {$spgsubjects($num) == ""} \
      { confirmalert "line $onebased: empty Subject entry";     return }
    if {$spgscandirs($num) == ""} \
      { confirmalert "line $onebased: empty Scandir entry";     return }
    if {$spgvtxlistprefs($num) == ""} \
      { confirmalert "line $onebased: empty VtxListPref entry"; return }
    if {$spgmorphsurfs($num) == ""} \
      { confirmalert "line $onebased: empty MorphSurf entry";   return }
    if {$spgmorphsurfs($num) == "not_found"} \
      { confirmalert "line $onebased: missing MorphSurf entry"; return }
    # empty spgstatbrikprefs OK (used by VOLAVG button)
  }
  ### re-check files exist (chk'd at select_ but may have changed w/reopen sess)
  set phasetype $sphavglists(00,phasetype) ;# if "real", truncate r,i,a,d loops
  foreach num [lsort [array names spgnums]] {
    set n $num
    while { [string match 0* $n] } { set n [string range $n 1 end] } ;# fixhex
    set onebased [format "%02d" [expr $n + 1]]  ;# empty n OK
    set fullscandir $env(FUNCTIONALS_DIR)/$spgsessions($num)/$spgscandirs($num)
    set fullsurfdir $env(SUBJECTS_DIR)/$spgsubjects($num)/$surfdir
    foreach hem { rh lh } {
      if {$currhemi == "rh" && $hem == "lh"} { continue }
      if {$currhemi == "lh" && $hem == "rh"} { continue }
      set infixlist "$amprealname $ampcomplexname $realname $complexname"
      if {$phasetype == "real"} { set infixlist " {} " }  ;# 1 empty entry
      foreach infix $infixlist {
        set fullvtxlistpref $fullscandir/$spgvtxlistprefs($num)$infix-$hem.w
        if ![file exists $fullvtxlistpref] {
          confirmalert "line $onebased: missing file:\
                    \n\n    $fullvtxlistpref\
                    \n\n(N.B.: indiv session directories must be in same\
                      \nFUNCTIONALS_DIR as cross-session directory)"
          return 
        }
      }
      set fullmorphsurf $fullsurfdir/$hem.$sphereext.$regext
      if ![file exists $fullmorphsurf] {
        confirmalert "line $onebased: missing file:\
                  \n\n    $fullmorphsurf\
                  \n\n(wrong current SUBJECTS_DIR?)"
        return 
      }
    }
  }

  ### new popup for meter
  set pr .sphavgprogress
  if [winfo exists $pr] { destroy $pr }
  toplevel $pr -bg $bgcol   ;# next: move aside so clickable if read log
  wm geometry $pr +[expr [winfo rootx .]-10]+[expr [winfo rooty .]+50]
  wm title $pr "Spherical Avg -- 1: Resample Progress"
  tixMeter $pr.me -value 0 -bg $bgcol -highlightbackground $bgcol \
    -fillcolor $runbgcol -width 350 -bd 2 -relief sunken
  pack $pr.me -side top -padx 80 -pady 5
  set sphavgjob "starting samp2ico... ($spgsubjects(00))                     " 
  label $pr.la0 -textvariable sphavgjob -font $ffont -bg $bgcol
  pack $pr.la0 -side top -pady 10

  ### global parms re-used in several steps
  set smoothsteps2ico $sphavglists(00,smoothsteps2ico)
  set smoothsteps2sub $sphavglists(00,smoothsteps2sub)
  set mapmethod $sphavglists(00,mapmethod)
  set ttestcompval $sphavglists(00,ttestcompval)
  # bresize: sphere surf = 163842 vertices, folded sphere surf = 167936 'vox'
  set numtotrunc 4094    ;# TODO: put-into/get-from HEAD to avoid mishap!
  set newnslices 41      ;# TODO: same
  set tmppref tmpdir     ;# for indiv sub calculations
  if {$currhemi == "both"} { set hemiticks 2 } else { set hemiticks 1 }
  set avgcnt [array size spgnums]
  # phasetype: already set above, finalstem: set beginning of 2nd pass

  ### cleanup tmpdirs
  cdlog $env(FUNCTIONALS_DIR)/$session/$sphavgdir
  set tmpdirlist [glob -nocomplain $tmppref-???-*]
  if { $tmpdirlist != "" } {
    set fmtdirlist ""
    foreach dir $tmpdirlist { set fmtdirlist "    $fmtdirlist\n    $dir" }
    set action [okreplace "" \
       " Sphere Average: stale tmpdirs exist:\n$fmtdirlist\n\n\
         OK to remove/remake?" "Remove/Remake"]
    if {$action == 0} {
      cdfunctscripts
      if [winfo exists $pr] { destroy $pr }
      return
    }
    if {$action == 1} {
      foreach dir $tmpdirlist {
        set ret [catch { exec rm -rf $dir } err]
        putlog "rm -rf $dir"
        if {$ret} { putlog "error: ### $ret" }
      }
    }
  }

  ###### 1st pass: foreach subj/hemi(s)/real-imag: sample data onto ico
  set infixticks 4   ;# _x, _y, _r, _i
  if {$phasetype == "real"} { set infixticks 1 }
  set totalticks [expr $avgcnt*$infixticks*$hemiticks]
  set ticks 0
  set purplekillseq 0
  cdlog $env(FUNCTIONALS_DIR)/$session/$sphavgdir
  foreach num [lsort [array names spgnums]] { ;# outer loop: linenums-to-avg
    set subjname $spgsubjects($num)
    set morphsurf $spgmorphsurfs($num)
    set inscandir $env(FUNCTIONALS_DIR)/$spgsessions($num)/$spgscandirs($num)
    set inpref $spgvtxlistprefs($num)   ;# typically stim progname
    set n $num
    while { [string match 0* $n] } { set n [string range $n 1 end] } ;#fixhex
    if { $n == "" } { set n 0 }
    set fnum [format "%03d" $n]
    set workdir \
      $env(FUNCTIONALS_DIR)/$session/$sphavgdir/$tmppref-$fnum-$subjname
    mkdirlog $workdir
    foreach hem { rh lh } { ;# next loop: hemi
      if {$currhemi == "rh" && $hem == "lh"} { continue }
      if {$currhemi == "lh" && $hem == "rh"} { continue }
      set infixlist "$amprealname $ampcomplexname $realname $complexname"
      if {$phasetype == "real"} { set infixlist " {} " }  ;# 1 empty entry
      foreach infix $infixlist {  ;# inner loop: infixes
        if {$purplekillseq} { continue }  ;# curr coarse-grained interrupt

        ### (1) surf2surf -- sample r,i,x,y wfiles to MSB ico bfloat wfile
        set instem $inscandir/$inpref$infix-$hem
        set outstem $workdir/$inpref-sph-sm$smoothsteps2ico$infix-$hem
        # TODO: option "--surfreg $morphsurf" not recognized despite help msg
        # 111006: new mri_surf2surf requires .w suffix, old OK w/suff
        # -nsmooth-out: smooth after resample (on ico surf, same as -nsmooth)
        # -nsmooth-in: smooth on input surface before resample
        set command "$bindir/mri_surf2surf \
          --srcsubject $subjname \
          --srcsurfval [backslashspaces ${instem}.w] \
          --src_type w \
          --trgsubject ico \
          --trgsurfval [backslashspaces $outstem] \
          --trgicoorder 7 \
          --trg_type bfloat \
          --hemi $hem \
          --frame 0 \
          --mapmethod $mapmethod \
          --nsmooth $smoothsteps2ico \
          --noreshape"
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid

        ### (2) bresize -- wrap/pad 1D r,i,x,y ico bfloat wfiles to MSB bfloats
        # bresize: also: -indir -outdir
        set instem $inpref-sph-sm$smoothsteps2ico$infix-$hem
        set outstem $inpref-sph-sm$smoothsteps2ico-fold$infix-$hem
        if ![file exists $workdir/${instem}_000.bfloat] {
          confirmalert " Sphere Average: subj $subjname: resample step 2:\n\n\
                         bresize input missing:\n\n\
                         $workdir/${instem}_000.bfloat\n\n\
                         (output of mri_surf2surf)"
          cdfunctscripts
          if [winfo exists $pr] { destroy $pr }
          return
        }
        set command "$bindir/bresize \
          $instem \
          -indir [backslashspaces $workdir] \
          -newx 64 \
          -newy 64 \
          -outstem $outstem \
          -outdir [backslashspaces $workdir]"
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid

        ### (3) to3d -- conv wrap/pad'd r,i,x,y bfloat ico wfiles to float BRIK
        set locinstem $inpref-sph-sm$smoothsteps2ico-fold$infix-$hem
        set locinpatt ${locinstem}_\?\?\?.bfloat
        set locoutstem $inpref-sph-sm$smoothsteps2ico-fold$infix-$hem
        cdlog $workdir  ;# AFNI must write locally, won't overwrite
        if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD}
        if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK}
        if ![file exists ${locinstem}_000.bfloat] {
          confirmalert " Sphere Average: subj $subjname: resample step 3:\n\n\
                         to3d input missing:\n\n\
                         $workdir/${locinstem}_000.bfloat\n\n\
                         (output of bresize)"
          cdfunctscripts
          if [winfo exists $pr] { destroy $pr }
          return
        }
        set swaparg ""
        if {$onearch == "Linux-i386" || $onearch == "Linux-x86_64" || \
            $onearch == "Darwin-i386" || $onearch == "Darwin-x86_64" } {
           set swaparg "-4swap"
        }
        ## N.B.: Intel: swap csurf/MSB infile on input, LSB BRIK written
        set command "env AFNI_VERSION_CHECK=NO $afnibindir/to3d \
          -prefix $locoutstem \
          -fbuc \
          $swaparg \
          -view orig \
          -xFOV 120L-R \
          -yFOV 120P-A \
          -zFOV 60S-I \
          -datum float \
          3Df:0:0:64:64:1:$locinpatt"  ;# 3Df -> float in -> out=type-1st-in
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        cdfunctscripts

        ### (4) 3dcalc -- get indiv ampl ico (infix _i implies _r and _i done)
        # indiv ampl (_a) for _d (can't use avg_a from avg_r,i), save pow (_b)
        if {$infix == $complexname} {  ;# relies on loop order: n=real,n+1=cplx
          set locinstem1 $inpref-sph-sm$smoothsteps2ico-fold$realname-$hem 
          set locinstem2 $inpref-sph-sm$smoothsteps2ico-fold$complexname-$hem 
          set locoutstem1 $inpref-sph-sm$smoothsteps2ico-fold$amplname-$hem 
          set locoutstem2 $inpref-sph-sm$smoothsteps2ico-fold$powname-$hem 
          cdlog $workdir  ;# AFNI must write locally, won't overwrite
          if [file exists $locoutstem1+orig.HEAD] {rmlog $locoutstem1+orig.HEAD}
          if [file exists $locoutstem1+orig.BRIK] {rmlog $locoutstem1+orig.BRIK}
          if [file exists $locoutstem2+orig.HEAD] {rmlog $locoutstem2+orig.HEAD}
          if [file exists $locoutstem2+orig.BRIK] {rmlog $locoutstem2+orig.BRIK}
          foreach locinstem "$locinstem1 $locinstem2" {
            if ![file exists $locinstem+orig.BRIK] {
              confirmalert " Sphere Avg: subj $subjname: resample step 4:\n\n\
                             3dcalc input missing:\n\n\
                             $workdir/$locinstem+orig.BRIK\n\n\
                             (output of to3d amp)"
              cdfunctscripts
              if [winfo exists $pr] { destroy $pr }
              return
            }
          }
          # N.B.: runacmd won't accept single quotes: pass back-slashed doubleq
          set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -prefix $locoutstem1 \
            -a $locinstem1+orig \
            -b $locinstem2+orig \
            -expr \"sqrt((a^2)+(b^2))\" \
            -datum float"  ;#111006:short->float, 111007:rm prob ignored fscale
          runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
#xx -- power t-test IN PROG
          # also save individual power for alternate t-test
          set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -prefix $locoutstem2 \
            -a $locinstem1+orig \
            -b $locinstem2+orig \
            -expr \"((a^2)+(b^2))\" \
            -datum float"
          runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          cdfunctscripts
        }

        # cleanup ico bfloats
        if [file exists  ${locinstem}_000.bfloat] {
          rmlog [glob ${locinstem}_???.bfloat]
        }
        if [file exists  ${locinstem}_000.hdr] {
          rmlog [glob ${locinstem}_???.hdr]
        }
        cdfunctscripts

        ### update meter
        incr ticks
        if [winfo exists $pr] {
          $pr.me config -value [expr $ticks/$totalticks.0]
          set sphavgjob \
            "finished samp2ico: $inpref$infix-$hem ($spgsubjects($num))"
          update idletasks
        }
      } ;# for infixes
    } ;# for hemis
  } ;# for subjects

  ###### 2nd pass: calculate avgs,t-stats, dispersion index (real or complex)
  set finalstem [file tail $sphavgdir]  ;# final visible pref (strip image/)
  set infixticks 7   ;# _x, _y, _r, _i, _a, _b, _d
  if {$phasetype == "real"} { set infixticks 1 }
  set totalticks [expr $infixticks*$hemiticks]
  set ticks 0
  after 500
  if [winfo exists $pr] {
    wm title $pr "Spherical Avg -- 2: Average (r/i/a, x/y, dispersion) Progress"
    $pr.me config -value 0.0
    set sphavgjob "starting average1... ($finalstem)                          "
    update idletasks
  }
  cdlog $env(FUNCTIONALS_DIR)/$session/$sphavgdir

  foreach hem { rh lh } {
    if {$currhemi == "rh" && $hem == "lh"} { continue }
    if {$currhemi == "lh" && $hem == "rh"} { continue }
#xxx -- power t-test IN PROG
    set infixlist "$amprealname $ampcomplexname \
                   $realname $complexname \
                   $amplname $powname $dispername"
    if {$phasetype == "real"} { set infixlist " {} " }  ;# 1 empty entry
    foreach infix $infixlist {
      if {$purplekillseq} { continue }

      ### (1) 3dttest -- cross sub mean,ttest on folded ico (x,y,r,i,a,b) BRIKs
      if { $infix != $dispername } {  ;# dispername doesn't exist yet
        # construct avglist from subj subdirs (for one hemi/infix combo)
        set inlist {}
        foreach num [lsort [array names spgnums]] {
          set subjname $spgsubjects($num)
          set inpref $spgvtxlistprefs($num)
          set n $num
          while {[string match 0* $n]} {set n [string range $n 1 end]} ;#fixhex
          if { $n == "" } { set n 0 }
          set fnum [format "%03d" $n]
          set workdir \
            $env(FUNCTIONALS_DIR)/$session/$sphavgdir/$tmppref-$fnum-$subjname
          set instem $workdir/$inpref-sph-sm$smoothsteps2ico-fold$infix-$hem
          if ![file exists ${instem}+orig.BRIK] {
            confirmalert " Sphere Average: cross subj avg step 1:\n\n\
                           3dttest input missing:\n\n\
                           ${instem}+orig.BRIK\n\n\
                           (output of sample $subjname to ico)"
            cdfunctscripts
            if [winfo exists $pr] { destroy $pr }
            return
          }
          lappend inlist $instem+orig
        }
        set locoutstem $finalstem-stats-sph-sm$smoothsteps2ico-fold$infix-$hem
        # rm prev outbrik if there (AFNI won't overwrite)
        if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD} 
        if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK} 
       ## 3dttest++ -- TODO: outputs avg? HOWTO test against non-zero?
       #set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dttest++ \
       #  -prefix $locoutstem \
       #  -setA [lbackslashspaces $inlist]"   ;# float-only out format
        ## 3dttest
        set tmpttestcompval 0.0  ;# nonzero comp t's only for _a,_b,noinfix
        if {$infix == $amplname || $infix == ""} {
          set tmpttestcompval $ttestcompval
        }
#xxx -- power t-test IN PROG
        if {$infix == $powname} {
          set tmpttestcompval [expr $ttestcompval**2]  ;# square curr entry
        }
        set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dttest \
          -prefix $locoutstem \
          -base1 $tmpttestcompval \
          -datum float \
          -set2 [lbackslashspaces $inlist]"
        # outformat above: short if 1st inp byte/short else float
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        # convert to output to bucket
        set locinstem $finalstem-stats-sph-sm$smoothsteps2ico-fold$infix-$hem
        set locoutstem temp
        # rm prev temp outbrik (e.g., from interrupt)
        if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD} 
        if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK} 
        # to bucket
        set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dbucket \
          -prefix $locoutstem \
          -fbuc \
          ${locinstem}+orig\[0\] \
          ${locinstem}+orig\[1\]"
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        # fix labels
        set locinstem temp  ;# fix HEAD in place (in=out)
        set command "env AFNI_VERSION_CHECK=NO $afnibindir/3drefit \
          -sublabel 0 ${finalstem}:mean \
          -sublabel 1 ${finalstem}:t-stat \
          $locinstem+orig"
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        # move output (temp) on top of input (orig output of 3dttest)
        set locinstem $finalstem-stats-sph-sm$smoothsteps2ico-fold$infix-$hem
        set locoutstem temp 
        if [file exists $locoutstem+orig.BRIK] {
          mvlog $locoutstem+orig.BRIK $locinstem+orig.BRIK
          mvlog $locoutstem+orig.HEAD $locinstem+orig.HEAD
        }
      } ;# all but $dispername, which doesn't exist until following step

#xxxxxxxxxxxxx -- what to call file? do all files?
#      ### (1a) variance -- cross sub var on folded ico (x,y,r,i,a,b) BRIKs
#      if { $infix == $amprealname || $infix == $ampcomplexname ||
#           $infix == $realname || $infix == $complexname } {
#      } ;# omit $amplname $powname $dispername

      ### (2) -- dispersion (ratio: ampvectavg/avgvectamp -> colinear=1) folded
      ##TODO: looks sensible, but d occasionally (slightly) over 1.0 (?!)
#xxxxxxxxxxx -- do for _x,_y,_c -> _l or _w or _s
#available infixes: _l,_m,_n,_o,_s,_u,_v,_w,_z (TODO: amp(_x,_y) -> _c
      # use 3dttest _a mean from above and _r,_i means from prev loop passes
      if {$infix == $dispername} {  ;# only for $dispername
        set locinstem1 \
          $finalstem-stats-sph-sm$smoothsteps2ico-fold$realname-$hem
        set locinstem2 \
          $finalstem-stats-sph-sm$smoothsteps2ico-fold$complexname-$hem
        set locinstem3 \
          $finalstem-stats-sph-sm$smoothsteps2ico-fold$amplname-$hem
        # next is "-stat-" because only one member, unlike above 3 -stats-
        set locoutstem \
          $finalstem-stat-sph-sm$smoothsteps2ico-fold$dispername-$hem
        if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD} 
        if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK} 
        foreach instem "$locinstem1 $locinstem2 $locinstem3" {
          if ![file exists ${instem}+orig.BRIK] {
            confirmalert " Sphere Average: cross subj avg step 2:\n\n\
                           3dcalc input missing:\n\n\
                           ${instem}+orig.BRIK\n\n\
                           (output of 3dttest -- r,i,amp)"
            cdfunctscripts
            if [winfo exists $pr] { destroy $pr }
            return
          }
        }
        # each first input subbrik is mean
        set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
          -prefix $locoutstem \
          -a $locinstem1+orig\[0\] \
          -b $locinstem2+orig\[0\] \
          -c $locinstem3+orig\[0\] \
          -expr \"(sqrt((a^2)+(b^2)))/c\" \
          -datum float"  ;#111006:short->float, 111007:rm prob ignored fscale
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }

      ### (3) brik2bfloat -- conv (x,y,r,i,a,b,d) avg+tstat->folded ico bfloats
      # dispername input is 1brik "stat", input for others is 2brik "stats"
      if {$infix == $dispername} { ;# 1 dispersion from 3dcalc (vs. mean+tstat)
        set locinstem $finalstem-stat-sph-sm$smoothsteps2ico-fold$infix-$hem
        set locoutstem0 $finalstem-stat-sph-sm$smoothsteps2ico-fold$infix-$hem
      } else {
        set locinstem $finalstem-stats-sph-sm$smoothsteps2ico-fold$infix-$hem
        set locoutstem0 $finalstem-mean-sph-sm$smoothsteps2ico-fold$infix-$hem
        set locoutstem1 $finalstem-tstat-sph-sm$smoothsteps2ico-fold$infix-$hem
      }
      if ![file exists $locinstem+orig.BRIK] {
        confirmalert " Sphere Average: cross subj avg step 3:\n\n\
                       brik2bfloat input missing:\n\n\
                       ${locinstem}+orig.BRIK\n\n\
                       (output of 3dttest)"
        cdfunctscripts
        if [winfo exists $pr] { destroy $pr }
        return
      }
      forcebrikMSBfirst $locinstem+orig nowarn $sphereavgbu "SPHEREAVG  "
      # mk folded bfloats from 2-vol BRIK (N.B.: brik2bfloat detects byteorder)
      set command "$bindir/brik2bfloat \
        $locinstem+orig \
        $locoutstem0 \
        0" ;# 0=first=mean
      runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
      # all infixes mean+tstat except dispersion just -stat- from 3dcalc
      if {$infix != $dispername} {
        set command "$bindir/brik2bfloat \
          $locinstem+orig \
          $locoutstem1 \
          1" ;# 1=second=tstat
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }

      ### (4) bresize -- unfold ico bfloats (x,y,r,i,a,b,d) for samp->dispsubj
      set indir $env(FUNCTIONALS_DIR)/$session/$sphavgdir
      if {$infix == $dispername} { ;# 1 dispersion from 3dcalc (vs. mean+tstat)
        set locinstem0 $finalstem-stat-sph-sm$smoothsteps2ico-fold$infix-$hem
      } else {
        set locinstem0 $finalstem-mean-sph-sm$smoothsteps2ico-fold$infix-$hem
        set locinstem1 $finalstem-tstat-sph-sm$smoothsteps2ico-fold$infix-$hem
      }
      set outdir $indir
      if {$infix == $dispername} {
        set locoutstem0 $finalstem-stat-sph-sm$smoothsteps2ico$infix-$hem
      } else {
        set locoutstem0 $finalstem-mean-sph-sm$smoothsteps2ico$infix-$hem
        set locoutstem1 $finalstem-tstat-sph-sm$smoothsteps2ico$infix-$hem
      }
      if ![file exists $indir/${locinstem0}_000.bfloat] {
        confirmalert " Sphere Average: cross subj avg step 4:\n\n\
                       bresize input missing:\n\n\
                       $indir/${locinstem0}_000.bfloat\n\n\
                       (output of brik2bfloat)"
        cdfunctscripts
        if [winfo exists $pr] { destroy $pr }
        return
      }
      set command "$bindir/bresize \
        $locinstem0 \
        -indir [backslashspaces $indir] \
        -nslices $newnslices \
        -trunc $numtotrunc \
        -unfold \
        -outstem $locoutstem0 \
        -outdir [backslashspaces $outdir]"
      runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid
      # all infixes mean+tstat except dispersion just -stat- from 3dcalc
      if {$infix != $dispername} {
        set command "$bindir/bresize \
          $locinstem1 \
          -indir [backslashspaces $indir] \
          -nslices $newnslices \
          -trunc $numtotrunc \
          -unfold \
          -outstem $locoutstem1 \
          -outdir [backslashspaces $outdir]"
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
      }
      # clean up folded bfloats (using locinstem's from prev step)
      if { [file exists  $outdir/${locinstem0}_000.bfloat] } {
        rmlog [glob $outdir/${locinstem0}_???.bfloat]
        rmlog [glob $outdir/${locinstem0}_???.hdr]
      }
      if { [file exists  $outdir/${locinstem1}_000.bfloat] } {
        rmlog [glob $outdir/${locinstem1}_???.bfloat]
        rmlog [glob $outdir/${locinstem1}_???.hdr]
      }
      ### leave 6 rh/lh two-comp (avg,tstat) and 1 one-comp (d) folded ico BRIK
      # e.g. 1step: $finalstem-stats-sph-sm1-fold_(r,i,x,y,a,d)-$hemi+orig.BRIK

      ### update meter
      incr ticks
      if [winfo exists $pr] {
        $pr.me config -value [expr $ticks/$totalticks.0]
        set sphavgjob "finished average: $locoutstem0"
        update idletasks
      }

    } ;# infixes (_x,_y,_r,_i,_a,_b plus _a->_d) *or* no infix
  } ;# hemis

  ###### 3rd pass: if not real, calc Hagler2007-cmplx-F and Rayleigh-p-expon
  # (xav^2 + yav^2)/2 / (((sumsub(_x-xav)^2)/n + sumsub(_y-yav)^2/n) / (2*n-2))
  # pos-p-exp = -log10(exp(sqrt(1 + 4*n + 4*(n^2-R^2)) - (1+2n)))
  #   where R = n*complexamp(vectavg((r/a,i/a)))
  if {$phasetype == "polar" || $phasetype == "eccen" || $phasetype == "2cond"} {
    after 500
    if [winfo exists $pr] {
      wm title $pr \
        "Spherical Avg -- 3: F-From-Complex + p-from-Rayleigh Progress"
      $pr.me config -value 0.0
      set sphavgjob \
        "starting average2... ($finalstem)                            "
      update idletasks
    }
    cdlog $env(FUNCTIONALS_DIR)/$session/$sphavgdir

    foreach avgtype "rawamp sigamp" {  ;# two passes: rawF,sigF
      if {$avgtype == "rawamp"} {
        set tmprealname     $amprealname     ;# _x
        set tmpcomplexname  $ampcomplexname  ;# _y
        set tmpcplxstatname $cplxstatname1   ;# _f
      }
      if {$avgtype == "sigamp"} {
        set tmprealname     $realname        ;# _r
        set tmpcomplexname  $complexname     ;# _i
        set tmpcplxstatname $cplxstatname2   ;# _g
      }

      ### (1) get numerator from overall _x,_y and _r,_i avgs calc'd above
      # numerator = (xav^2 + yav^2)/2
      foreach hem { rh lh } {
        if {$currhemi == "rh" && $hem == "lh"} { continue }
        if {$currhemi == "lh" && $hem == "rh"} { continue }
        if {$purplekillseq} { continue }
        # next two avg ico folded BRIKs have both 0=mean,1=tstat -- use mean
        set locinstem1 \
          $finalstem-stats-sph-sm$smoothsteps2ico-fold$tmprealname-$hem
        set locinstem2 \
          $finalstem-stats-sph-sm$smoothsteps2ico-fold$tmpcomplexname-$hem
        set locoutstem numerator-$hem
        # check input: x and y avgs
        foreach instem "$locinstem1 $locinstem2" {
          if ![file exists ${instem}+orig.BRIK] {
            confirmalert " Sphere Average: cross subj F-from-complex calc:\n\n\
                           3dcalc input missing:\n\n\
                           ${instem}+orig.BRIK\n\n\
                           (output of 3dcalc -- x,y/r,i Fourier component avgs)"
            cdfunctscripts
            if [winfo exists $pr] { destroy $pr }
            return
          }
        }
        # rm prev outbrik if there from interrupt (AFNI won't overwrite)
        if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD}
        if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK}
        # go: first subbrik of each input is mean
        putlog "\n(1) get F numerator from _x,_y/_r,_i avgs calc'd above"
        set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
          -prefix $locoutstem \
          -a $locinstem1+orig\[0\] \
          -b $locinstem2+orig\[0\] \
          -expr \"((a^2)+(b^2))/2.0\" \
          -datum float"  ;# float during calc
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        # LSBfirst output on Intel: skip forcebrikMSB here, swap at end
      }
      if [winfo exists $pr] {
        $pr.me config -value 0.1
        set sphavgjob "finished calculate numerator of F-from-complex"
        update idletasks
      }
  
      ### (2) sum squared _x,_y/_r,_i residuals (2 demon terms) + normed _r,_i
      # get sums: xsum = sum(sub(_x-xav)^2)/n), ysum = sum(sub(_y-yav)^2/n)
      # TODO: loop to 3dcalc sub(_x-xav)^2's, 3dMean tmpouts, 3dcalc div by n
      set infixticks 2   ;# _x/_r, _y,_i
      set totalticks [expr 2*$avgcnt*$infixticks*$hemiticks]  ;# 2 passes
      set ticks 0
      foreach num [lsort [array names spgnums]] { ;#outerloop: subj/lines toavg
        set subjname $spgsubjects($num)
        set inpref $spgvtxlistprefs($num)
        set n $num
        while {[string match 0* $n]} {set n [string range $n 1 end]} ;#fixhex
        if { "$n" == "" } { set n 0 }
        set fnum [format "%03d" $n]
        set workdir \
          $env(FUNCTIONALS_DIR)/$session/$sphavgdir/$tmppref-$fnum-$subjname
        foreach hem { rh lh } {
          if {$currhemi == "rh" && $hem == "lh"} { continue }
          if {$currhemi == "lh" && $hem == "rh"} { continue }
          foreach infix "$tmprealname $tmpcomplexname" {
            if {$purplekillseq} { continue }
            ## 2a: runningsums F-denom--3dcalc a-z symbols might overflow 1shot
            set locinstem1 sumsqresid-previous$infix-$hem             ;#prev tot
            set locinstem2 \
              $workdir/$inpref-sph-sm$smoothsteps2ico-fold$infix-$hem ;#currsub
            set locinstem3 \
              $finalstem-stats-sph-sm$smoothsteps2ico-fold$infix-$hem ;#avg=brk1
            set locoutstem sumsqresid-current$infix-$hem              ;# currtot
            if {"$fnum" == "000"} {  ;# mk cmd first pass (both infixes)
              # rm any tmpbriks from interrupt, check inp, start running avg
              foreach tmpbrikhead \
                  [glob -nocomplain sumsqresid-previous$infix-$hem+orig* \
                                    sumsqresid-current$infix-$hem+orig*] {
                if [file exists $tmpbrikhead] { rmlog $tmpbrikhead }
              }
              foreach instem "$locinstem2 $locinstem3" {
                if ![file exists ${instem}+orig.BRIK] {
                  confirmalert \
                    " Sphere Average: sub-by-sub sumsq residuals:\n\n\
                      3dcalc input missing (begin run total):\n\n\
                      ${instem}+orig.BRIK\n\n\
                      (output of 3dcalc -- curr resid tot, currsub, avg)"
                  cdfunctscripts
                  if [winfo exists $pr] { destroy $pr }
                  return
                }
              }
              putlog "\n(2) start $infix running sum sq resid ($locinstem2)"
              set eq "\"0.0+(((b-c)^2)/$avgcnt.0)\""
              set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
                -prefix $locoutstem \
                -b $locinstem2+orig \
                -c $locinstem3+orig\[0\] \
                -expr $eq \
                -datum float"  ;# float for calc
            } else { ;# mk cmd not first pass
              # rm "prev" (=prevprevloop), mv "curr" (=prevloop out)->new input
              if [file exists $locinstem1+orig.HEAD] {
                rmlog $locinstem1+orig.HEAD
              }
              if [file exists $locinstem1+orig.BRIK] {
                rmlog $locinstem1+orig.BRIK
              }
              set command "env AFNI_VERSION_CHECK=NO $afnibindir/3drename \
                $locoutstem $locinstem1"
              runacmd \
                "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
              tkwait variable cmdpid
              # check inputs, continue running avg/total
              foreach instem "$locinstem1 $locinstem2 $locinstem3" {
                if ![file exists ${instem}+orig.BRIK] {
                  confirmalert \
                    " Sphere Average: sub-by-sub sumsq residuals:\n\n\
                      3dcalc input missing (continue run total):\n\n\
                      ${instem}+orig.BRIK\n\n\
                      (output of 3dcalc -- curr resid tot, currsub, avg)"
                  cdfunctscripts
                  if [winfo exists $pr] { destroy $pr }
                  return
                }
              }
              putlog "\n(2a) continue $infix running sum sq resid ($locinstem2)"
              set eq "\"a+(((b-c)^2)/$avgcnt.0)\""
              set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
                -prefix $locoutstem \
                -a $locinstem1+orig \
                -b $locinstem2+orig \
                -c $locinstem3+orig\[0\] \
                -expr $eq \
                -datum float"  ;# float for calc
            } ;# not first pass
            # go
            runacmd \
              "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
            tkwait variable cmdpid
            # update meter
            incr ticks
            if [winfo exists $pr] {
              $pr.me config -value [expr $ticks/$totalticks.0]
              set sphavgjob \
                "finished sq residuals: $locoutstem ($spgsubjects($num))"
              update idletasks
            }
            ## 2b: get running sums normed _r,_i (_r/_a, _i/_a) for Rayleigh
            # N.B.: complex amp of final sum is already nr 
            if {$tmprealname == "$realname"} {  ;# ignore rawF pass
              set locinstem1 sumnorm-previous$infix-$hem               ;#prevtot
              set locinstem2 \
               $workdir/$inpref-sph-sm$smoothsteps2ico-fold$infix-$hem ;# _r,_i
              set locinstem3 \
               $workdir/$inpref-sph-sm$smoothsteps2ico-fold$amplname-$hem ;# _a
              set locoutstem sumnorm-current$infix-$hem                ;#currtot
              if {"$fnum" == "000"} {  ;# first pass (both infixes)
                # rm any tmpbriks from interrupt, check inp, start running avg
                foreach tmpbrikhead \
                    [glob -nocomplain sumnorm-previous$infix-$hem+orig* \
                                      sumnorm-current$infix-$hem+orig*] {
                  if [file exists $tmpbrikhead] { rmlog $tmpbrikhead }
                }
                # check input
                foreach instem "$locinstem2 $locinstem3" {
                  if ![file exists ${instem}+orig.BRIK] {
                    confirmalert \
                      " Sphere Average: sub-by-sub normed r,i components:\n\n\
                        3dcalc input missing (begin run total):\n\n\
                        ${instem}+orig.BRIK\n\n\
                        (output of 3dcalc -- curr norm comp tot, currsub r,i+a)"
                    cdfunctscripts
                    if [winfo exists $pr] { destroy $pr }
                    return
                  }
                }
                # go (sum of components of indiv subj norms: _r/_a, _i/_a)
                putlog "\n(2b) start $infix running sum normed ($locinstem2)"
                set eq "\"0.0+(b/c)\""
                set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
                  -prefix $locoutstem \
                  -b $locinstem2+orig \
                  -c $locinstem3+orig \
                  -expr $eq \
                  -datum float"  ;# float for calc
              } else {
                # rm "prev" (=prevprevloop), mv "curr" (=prevloop out)->new inp
                if [file exists $locinstem1+orig.HEAD] {
                  rmlog $locinstem1+orig.HEAD
                }
                if [file exists $locinstem1+orig.BRIK] {
                  rmlog $locinstem1+orig.BRIK
                }
                set command "env AFNI_VERSION_CHECK=NO $afnibindir/3drename \
                  $locoutstem $locinstem1"
                runacmd \
                  "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
                tkwait variable cmdpid
                # check inputs, continue running avg/total
                foreach instem "$locinstem1 $locinstem2 $locinstem3" {
                  if ![file exists ${instem}+orig.BRIK] {
                    confirmalert \ 
                      " Sphere Average: sub-by-sub normed r,i components:\n\n\
                        3dcalc input missing (continue run total):\n\n\
                        ${instem}+orig.BRIK\n\n\
                        (output of 3dcalc -- curr norm comp tot, currsub r,i+a)"
                    cdfunctscripts
                    if [winfo exists $pr] { destroy $pr }
                    return
                  }
                }
                # go
                putlog "\n(2b) continue $infix running sum normed ($locinstem2)"
                set eq "\"a+(b/c)\""
                set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
                  -prefix $locoutstem \
                  -a $locinstem1+orig \
                  -b $locinstem2+orig \
                  -c $locinstem3+orig \
                  -expr $eq \
                  -datum float"  ;# float for calc
              }
              runacmd \
                "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
              tkwait variable cmdpid
              # update meter
              incr ticks
              if [winfo exists $pr] {
                $pr.me config -value [expr $ticks/$totalticks.0]
                set sphavgjob \
                  "finished sum normed r,i: $locoutstem ($spgsubjects($num))"
                update idletasks
              }
            } ;# Rayleigh running sums: if _r (implies _i)
  
          } ;# for infixes _x,_y and _r,_i
        } ;# for hemis
      } ;# for subjects
  
      ### (3) final F-from-complex calc
      # final = numerator/((xsum+ysum)/(2*n-2))
      set infix $tmpcplxstatname  ;# _f or _g
      foreach hem { rh lh } {
        if {$currhemi == "rh" && $hem == "lh"} { continue }
        if {$currhemi == "lh" && $hem == "rh"} { continue }
        if {$purplekillseq} { continue }
        set locinstem1 numerator-$hem
        set locinstem2 sumsqresid-current${tmprealname}-$hem
        set locinstem3 sumsqresid-current${tmpcomplexname}-$hem
        set locoutstem \
          $finalstem-stat-sph-sm${smoothsteps2ico}-fold${infix}-$hem
        # rm prev outbrik if there from interrupt (AFNI won't overwrite)
        if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD}
        if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK}
        # check input: numerator, real/complex sum sq residuals
        foreach instem "$locinstem1 $locinstem2 $locinstem3" {
          if ![file exists ${instem}+orig.BRIK] {
            confirmalert " Sphere Average: cross subj F-from-complex calc:\n\n\
                           3dcalc input missing:\n\n\
                           ${instem}+orig.BRIK\n\n\
                           (output of 3dcalc -- numer, sum sq x,y residuals)"
            cdfunctscripts
            if [winfo exists $pr] { destroy $pr }
            return
          }
        }
        # go
        putlog "\n(3) final F-from-complex calc for $avgcnt subjects"
        set eps 0.0   ;# or 0.00000001 to stop div by zero (e.g. infiles ident)
        set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
          -prefix $locoutstem \
          -a $locinstem1+orig \
          -b $locinstem2+orig \
          -c $locinstem3+orig \
          -expr \"a/((b+c+$eps)/((2.0*$avgcnt.0)-2.0))\" \
          -datum float" ;# -fscale -datum short=>trunc 82% misfit lost num prec
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        # clean up tmp BRIK's
        foreach tmpbrikhead \
           "sumsqresid-previous${tmprealname}-$hem+orig.HEAD \
            sumsqresid-previous${tmprealname}-$hem+orig.BRIK \
            sumsqresid-previous${tmpcomplexname}-$hem+orig.HEAD \
            sumsqresid-previous${tmpcomplexname}-$hem+orig.BRIK \
            $locinstem1+orig.HEAD $locinstem2+orig.HEAD $locinstem3+orig.HEAD \
           $locinstem1+orig.BRIK $locinstem2+orig.BRIK $locinstem3+orig.BRIK" {
          if [file exists $tmpbrikhead] { rmlog $tmpbrikhead }
        }
      } ;# hemis: calc complex-F
      ## conv final calc -> folded bfloat -> unfolded bfloat (for resamp2subj)
      set infix $tmpcplxstatname  ;# _f or _g
      foreach hem { rh lh } {
        if {$currhemi == "rh" && $hem == "lh"} { continue }
        if {$currhemi == "lh" && $hem == "rh"} { continue }
        if {$purplekillseq} { continue }
        # BRIK -> folded bfloat
        set locinstem \
          $finalstem-stat-sph-sm${smoothsteps2ico}-fold${infix}-$hem
        set locoutstem \
          $finalstem-stat-sph-sm${smoothsteps2ico}-fold${infix}-$hem
        if ![file exists ${locinstem}+orig.BRIK] {
          confirmalert \
            " Sphere Average: conv F-from-complex BRIK to bfloat:\n\n\
              3dcalc input missing:\n\n\
              ${locinstem}+orig.BRIK\n\n\
              (output of 3dcalc -- F-from-complex float BRIK)"
          cdfunctscripts
          if [winfo exists $pr] { destroy $pr }
          return
        }
        forcebrikMSBfirst $locinstem+orig nowarn $sphereavgbu "SPHEREAVG  "
        set command "$bindir/brik2bfloat \
          $locinstem+orig \
          $locoutstem \
          0"
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        # folded bfloat -> bfloat
        set indir $env(FUNCTIONALS_DIR)/$session/$sphavgdir
        set outdir $indir
        set locinstem \
          $finalstem-stat-sph-sm${smoothsteps2ico}-fold${infix}-$hem
        set locoutstem \
          $finalstem-stat-sph-sm${smoothsteps2ico}${infix}-$hem
        if ![file exists ${locinstem}+orig.BRIK] {
          confirmalert \
            " Sphere Average: unfold F-from-complex bfloat:\n\n\
              3dcalc input missing:\n\n\
              ${locinstem}+orig.BRIK\n\n\
              (output of brik2bfloat -- F-from-complex folded bfloat)"
          cdfunctscripts
          if [winfo exists $pr] { destroy $pr }
          return
        }
        set command "$bindir/bresize \
          $locinstem \
          -indir [backslashspaces $indir] \
          -nslices $newnslices \
          -trunc $numtotrunc \
          -unfold \
          -outstem $locoutstem \
          -outdir [backslashspaces $outdir]"
        runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        # clean up folded bfloats
        if { [file exists $outdir/${locinstem}_000.bfloat] } {
          rmlog [glob $outdir/${locinstem}_???.bfloat]
          rmlog [glob $outdir/${locinstem}_???.hdr]
        }
      } ;# hemis: BRIK -> folded bfloat -> unfolded bfloat
      if [winfo exists $pr] {
        $pr.me config -value 1.0
        set sphavgjob "finished calculate F-from-complex"
        update idletasks
      }

      ### (4) final p-from-Rayleigh calc
      # R = nr, where r is avg ampl unit cpx vectsum (=cmplxamp-sum-normed-r,i)
      if {$tmprealname == "$realname"} {  ;# Rayleigh ignores rawF pass
        set infix $cplxstatname4  ;# _e
        foreach hem { rh lh } {
          if {$currhemi == "rh" && $hem == "lh"} { continue }
          if {$currhemi == "lh" && $hem == "rh"} { continue }
          if {$purplekillseq} { continue }
          set locinstem1 sumnorm-current${tmprealname}-$hem
          set locinstem2 sumnorm-current${tmpcomplexname}-$hem
          set locoutstem \
            $finalstem-stat-sph-sm${smoothsteps2ico}-fold${infix}-$hem
          # rm prev outbrik if there from interrupt (AFNI won't overwrite)
          if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD}
          if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK}
          # check input
          foreach instem "$locinstem1 $locinstem2" {
            if ![file exists ${instem}+orig.BRIK] {
              confirmalert " Sphere Average: cross subj Rayleigh test:\n\n\
                             3dcalc input missing:\n\n\
                             ${instem}+orig.BRIK\n\n\
                             (output of 3dcalc -- summed norm r,i components)"
              cdfunctscripts
              if [winfo exists $pr] { destroy $pr }
              return
            }
          }
          # go
          putlog "\n(4) final p-from-Rayleigh calc for $avgcnt subjects"
          #### final paintable stat is pos p exponent (e.g., 0.01 -> 2)
          # N.B.: R^2 = sum_norm_r^2 + sum_norm_i^2 (omit sqrt)
          ## debug: nr (e.g., with n=14, nr>8 (57%) around 0.01)
          #set eq "\"sqrt((a^2)+(b^2))\""
          ## simple p: exp(-(R^2)/n)==exp(-n*(R/n)^2)==exp(-(a^2+b^2)/n)
          #set eq "\"-log10(exp(-((a^2)+(b^2))/$avgcnt.0))\""
          ## corrected p: -log10(exp(sqrt(1 + 4*n + 4*(n^2 - R^2)) - (1+2n)))
          set eq "\"-(log10(exp(sqrt((1.0) + (4.0*$avgcnt.0) +
                                     (4.0*(($avgcnt.0*$avgcnt.0) - 
                                           ((a^2)+(b^2)))) )
                              - (1.0 + (2.0*$avgcnt.0)) ) ) )\""
          set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -prefix $locoutstem \
            -a $locinstem1+orig \
            -b $locinstem2+orig \
            -expr $eq \
            -datum float"  ;# float for calc
          runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          # clean up tmp BRIK's
          foreach tmpbrikhead \
             "sumnorm-previous${tmprealname}-$hem+orig.HEAD \
              sumnorm-previous${tmprealname}-$hem+orig.BRIK \
              sumnorm-previous${tmpcomplexname}-$hem+orig.HEAD \
              sumnorm-previous${tmpcomplexname}-$hem+orig.BRIK \
              $locinstem1+orig.HEAD $locinstem2+orig.HEAD \
              $locinstem1+orig.BRIK $locinstem2+orig.BRIK" {
            if [file exists $tmpbrikhead] { rmlog $tmpbrikhead }
          }         
        } ;# hemis: calc Rayleigh p
        ## conv final calc -> folded bfloat -> unfolded bfloat (for resamp2subj)
        foreach hem { rh lh } {
          if {$currhemi == "rh" && $hem == "lh"} { continue }
          if {$currhemi == "lh" && $hem == "rh"} { continue }
          if {$purplekillseq} { continue }
          # BRIK -> folded bfloat
          set locinstem \
            $finalstem-stat-sph-sm${smoothsteps2ico}-fold${infix}-$hem
          set locoutstem \
            $finalstem-stat-sph-sm${smoothsteps2ico}-fold${infix}-$hem
          if ![file exists ${locinstem}+orig.BRIK] {
            confirmalert \
              " Sphere Average: conv p-from-Rayeigh BRIK to bfloat:\n\n\
                3dcalc input missing:\n\n\
                ${locinstem}+orig.BRIK\n\n\
                (output of 3dcalc -- p-from-Rayleigh float BRIK)"
            cdfunctscripts
            if [winfo exists $pr] { destroy $pr }
            return
          }
          forcebrikMSBfirst $locinstem+orig nowarn $sphereavgbu "SPHEREAVG  "
          set command "$bindir/brik2bfloat \
            $locinstem+orig \
            $locoutstem \
            0"
          runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          # folded bfloat -> bfloat
          set indir $env(FUNCTIONALS_DIR)/$session/$sphavgdir
          set outdir $indir
          set locinstem \
            $finalstem-stat-sph-sm${smoothsteps2ico}-fold${infix}-$hem
          set locoutstem \
            $finalstem-stat-sph-sm${smoothsteps2ico}${infix}-$hem
          if ![file exists ${locinstem}+orig.BRIK] {
            confirmalert \
              " Sphere Average: unfold p-from-Rayleigh bfloat:\n\n\
                3dcalc input missing:\n\n\
                ${locinstem}+orig.BRIK\n\n\
                (output of brik2bfloat -- p-from-Rayleigh folded bfloat)"
            cdfunctscripts
            if [winfo exists $pr] { destroy $pr }
            return
          }
          set command "$bindir/bresize \
            $locinstem \
            -indir [backslashspaces $indir] \
            -nslices $newnslices \
            -trunc $numtotrunc \
            -unfold \
            -outstem $locoutstem \
            -outdir [backslashspaces $outdir]"
          runacmd "$command" $sphereavgbu "SPHEREAVG  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          # clean up folded bfloats
          if { [file exists $outdir/${locinstem}_000.bfloat] } {
            rmlog [glob $outdir/${locinstem}_???.bfloat]
            rmlog [glob $outdir/${locinstem}_???.hdr]
          }
        } ;# hemis: BRIK -> folded bfloat -> unfolded bfloat
      } ;# Rayleigh final calc: if _r (implies _i)
      if [winfo exists $pr] {
        $pr.me config -value 1.0
        set sphavgjob "finished calculate p-from-Rayleigh-test"
        update idletasks
      }
  
    } ;# two passes: rawF,sigF
    # end complex-F/p-Rayleigh if avg is complex-valued
  } else {
    # real: unfolded bfloat already made from 3dttest output 
  }

  ###### 4th pass: optional permutation test
  # (xav^2 + yav^2)/2 / (((sumsub(_x-xav)^2)/n + sumsub(_y-yav)^2/n) / (2*n-2))
  if {$sphavglists(00,permtestcnt) &&
      $phasetype == "polar" || $phasetype == "eccen" || $phasetype == "2cond"} {
    after 500
confirmalert "TODO: xsubj permtest"
    if [winfo exists $pr] {
      wm title $pr \
        "Spherical Avg -- 4: Phase-scramble Permutation test on F-From-Complex"
      $pr.me config -value 0.0
      set sphavgjob \
        "starting permutation test... ($finalstem)                            "
      update idletasks
    }
    cdlog $env(FUNCTIONALS_DIR)/$session/$sphavgdir
    set permtestcnt 0
    while {$permtestcnt < $sphavglists(00,permtestcnt) } {
#xxxxx -- TODO: permtest (prob not a big win here either...)
#     foreach subject
#       3dcalc add diff random phase to each voxel _x,_y
#     3dMean of shuffled to get perm numerator
#     foreach subject
#       3dcalc sub(_x-xav)^2's, 3dMean tmpouts, 3dcalc div by n to get denom
#     3dcalc numer/denom final stat
#     3dcalc accumulate higher than original F
      incr permtestcnt
    }
# 3dcalc generate p pseudo BRIK
  } ;# end xsubj perm test

  ### cleanup indiv subj+sess subdirs
  cdlog $env(FUNCTIONALS_DIR)/$session/$sphavgdir
  set rmlist [glob -nocomplain $tmppref-???-*]
  foreach dir $rmlist {
    putlog "rm -rf $dir"
    exec rm -rf $dir
  }
  cdfunctscripts

  # explicit name (not $pr) because 'after' executes in global context
  after 1000 { if [winfo exists .sphavgprogress] {destroy .sphavgprogress} }
  if {!$purplekillseq} { savesphavgcxparms } else { set purplekillseq 0 }
}

### SAMP2SUBJ button command (Cross Sess Spherical Average panel)
proc sphavgcxsamp2subj  { } {
  global env bindir datfile surfdir
  global realname complexname dispername amprealname ampcomplexname
  global cplxstatname1 cplxstatname2 amplname cplxstatname4 powname
  global cplxstatname6
  global cmdlog samp2subjbu bgcol runbgcol ffont sphavgjob
  global dispname session hemi sphavgdir sphavglists spgnums

  if ![info exists spgnums(00)] {
    confirmalert " Sphere Average:  no average to sample onto surf:\n\n\
                   First, generate average:\n\n\
                   (1) click ADD SESS button to make new blank line\n\
                   (2) select Session,Scandir,VtxListPref dropdowns\n\
                   (3) when done, click SPHEREAVG"
    return
  }
  ### hash in path breaks mri_surf2surf (weird error: bad RAS to RAS xform)
  foreach path "$env(FUNCTIONALS_DIR) $env(SUBJECTS_DIR)" {
    if { [string first "#" $path] != -1 } {  
      confirmalert "Sphere Average: \"#\" found in an input file path:\
                \n\n    $path\
                \n\nwhich will cause mri_surf2surf to fail.\
                \n\nMove this dir to location without a \"#\"\
                 \nin path, and try again"
      return
    }
  }

  ###### 1st pass: sample to subject
  set pr .sphavgprogress
  if [winfo exists $pr] { destroy $pr }
  toplevel $pr -bg $bgcol
  wm geometry $pr +[expr [winfo rootx .]-10]+[expr [winfo rooty .]+50]
  wm title $pr "Spherical Avg -- Avg=>DisplaySubj Progress"
  tixMeter $pr.me -value 0 -bg $bgcol -highlightbackground $bgcol \
    -fillcolor $runbgcol -width 350 -bd 2 -relief sunken
  pack $pr.me -side top -padx 80 -pady 5
  set sphavgjob "starting sample avg->${dispname}...                         "
  label $pr.la0 -textvariable sphavgjob -font $ffont -bg $bgcol
  pack $pr.la0 -side top -pady 10

  set finalstem [file tail $sphavgdir]      ;# image/avgname -> avgname
  set smoothsteps2ico $sphavglists(00,smoothsteps2ico)
  set mapmethod $sphavglists(00,mapmethod)
  set morphsurf $sphavglists(00,morphsurf)  ;# assume same for all subjects
  set phasetype $sphavglists(00,phasetype)  ;# if "real", truncate r,i,d loops
  set indir $env(FUNCTIONALS_DIR)/$session/$sphavgdir
  set currhemi $hemi    ;# detach from main panel hemi
  if {$currhemi == "both"} { set hemiticks 2 } else { set hemiticks 1 }
  set infixticks 10   ;# _r, _i, _a, _b, _d, _x, _y, _f, _g, _e
  if {$phasetype == "real"} { set infixticks 1 }
  set avgticks 2  ;# mean,tstat (only 1: dispersion, no tstat for r,i,x,y)
  set totalticks [expr $avgticks*$infixticks*$hemiticks - 5*1*$hemiticks]
  # tmphack (TODO: figure out 5, put in correct adj for real)
  if {$totalticks < 1} {set totalticks [expr $avgticks*$infixticks*$hemiticks]}
  set ticks 0
  set purplekillseq 0
  foreach hem { rh lh } {
    if {$currhemi == "rh" && $hem == "lh"} { continue }
    if {$currhemi == "lh" && $hem == "rh"} { continue }
    set fullmorphsurf $env(SUBJECTS_DIR)/$dispname/$surfdir/$hem.$morphsurf
    if ![file exists $fullmorphsurf] {
      confirmalert " Sample To Subject: morphed surface for\n\
                     display subject is missing:\n\n\
                     $fullmorphsurf\n\n\
                     (run SubjectTools -> Register Surface)"
      cdfunctscripts
      if [winfo exists $pr] { destroy $pr }
      return
    }
    # amplname (_a) used next for tstat on amp (elsewhere: cplxstatname3 -> _a)
    set infixlist "$realname $complexname \
                   $amplname $powname $dispername \
                   $amprealname $ampcomplexname \
                   $cplxstatname1 $cplxstatname2 $cplxstatname4"
    if {$phasetype == "real"} { set infixlist " {} " } ;# else 1 empty entry
    foreach infix $infixlist {
      ### surf2surf -- resample unfolded bfloat wfile back onto current subject
#xx -- power t-test IN PROG
      if {$infix == "$dispername" || $infix == "$cplxstatname1" || \
          $infix == "$cplxstatname2" || $infix == "$cplxstatname4"} {
        set instem0 $indir/$finalstem-stat-sph-sm$smoothsteps2ico$infix-$hem
      } else {
        set instem0 $indir/$finalstem-mean-sph-sm$smoothsteps2ico$infix-$hem
      }
      set instem1 $indir/$finalstem-tstat-sph-sm$smoothsteps2ico$infix-$hem
      foreach instem "$instem0 $instem1" {  ;# mean, tstat
        if {$purplekillseq} { continue }
#xx -- power t-test IN PROG
        # DON'T resample (_r,_i) and (_x,_y) *t-tests* to surface
        # DO resample: amp, power, tstat from real-valued
        if {$instem == $instem1 && \
            $infix != $amplname && $infix != $powname && $infix != ""} {
#xx -- real t-test IN PROG
          continue   ;# resample all avgs, 3 t-stats (ampl, pow, real)
        }
        set outstem $instem.w
        if ![file exists ${instem}_000.bfloat] {
          confirmalert " Sample To Subject: mri_surf2surf input missing:\n\n\
                         ${instem}_000.bfloat\n\n\
                         (unfolded output of bresize)"
          if {$infix == $powname} {
            confirmalert " If resampling an old SPHEREAVG run,\n\
                           re-run SPHEREAVG to generate $powname file"
          }
          if [winfo exists $pr] { destroy $pr }
          cdfunctscripts
          return
        }
        # TODO: option "--surfreg $morphsurf" not recog despite help msg
        # no smoothing on sample back
        set command "$bindir/mri_surf2surf \
          --srcsubject ico \
          --srcsurfval [backslashspaces $instem] \
          --srcfmt bfloat \
          --trgsubject $dispname \
          --trgsurfval [backslashspaces $outstem] \
          --trgfmt paint \
          --hemi $hem \
          --frame 0 \
          --mapmethod $mapmethod"
        runacmd "$command" $samp2subjbu "SAMP2SUBJ  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid

        incr ticks
        if [winfo exists $pr] {
          $pr.me config -value [expr $ticks/$totalticks.0]
         set sphavgjob "finished sample avg->${dispname}: [file tail $outstem]"
          update idletasks
        }
      } ;# instems
    } ;# infixes
  } ;# hemis

  ###### 2nd pass: surf-clust-filter final stats
  if {$sphavglists(00,clustarea) > 0.0} {
    after 500
    if [winfo exists $pr] {
      wm title $pr "Spherical Avg -- Cluster Filter F-From-Complex"
      $pr.me config -value 0.0
      set sphavgjob \
        "starting clust correct... ($finalstem)                            "
      update idletasks
    }
    set totalticks $hemiticks
    set ticks 0

    cdlog $env(FUNCTIONALS_DIR)/$session/$sphavgdir
    set preclustfthr $sphavglists(00,preclustfthr)
    set clustarea $sphavglists(00,clustarea)
    set clustsurf $sphavglists(00,clustsurf)
    set infix  $cplxstatname1  ;# _f
    # next no-infix a tstat but trunc'd w/"F:"! => outp to _h (TODO: _t => _v)
#xx -- real t-test IN PROG
    if {$phasetype == "real"} { set infix "" }
    set outfix $cplxstatname6  ;# _h
    set clustfix f${preclustfthr}a${clustarea} ;# prethresh plus area
    foreach hem { rh lh } {
      if {$purplekillseq} { continue }
      if {$currhemi == "rh" && $hem == "lh"} { continue }
      if {$currhemi == "lh" && $hem == "rh"} { continue }
      # check input
#xx -- real t-test IN PROG
      set statinfix "stat"  ;# csurf-internal 
      if {$phasetype == "real"} { set statinfix "tstat" }  ;# AFNI
      set locinstem $finalstem-$statinfix-sph-sm${smoothsteps2ico}${infix}
      set locoutstem \
        $finalstem-$statinfix-sph-sm${smoothsteps2ico}-${clustfix}${outfix}
      if ![file exists $locinstem-$hem.w] {
        confirmalert " Sample To Subject: Cluster Filter:\n\n\
                       surfclust input missing:\n\n\
                       ${locinstem}-$hem.w\n\n\
                       (output of mri_surf2surf)"
        cdfunctscripts
        if [winfo exists $pr] { destroy $pr }
        return
      }
      # go: 
      set command "$bindir/surfclust \
        -instem $locinstem \
        -name $dispname \
        -outstem $locoutstem \
        -hemi $hem \
        -threshabs \
        -thresh $preclustfthr \
        -minarea $clustarea \
        -surf $clustsurf"   ;# now adjustable: was hard-coded to: smoothwm
      runacmd "$command" $samp2subjbu "SAMP2SUBJ  " cmdinput $cmdlog cmdpid
      tkwait variable cmdpid

      #TODO: also filter Rayleigh F (F -> p -> equiv F for surfstat)

      ### update meter
      incr ticks
      if [winfo exists $pr] {
        $pr.me config -value [expr $ticks/$totalticks.0]
        set sphavgjob "finished average: $locoutstem"
        update idletasks
      }
    } ;# hemis
  } ;# end maybe skip surfclust

#xxxxxxxxxxx no-window tksurfer script -> write to saveable panel parm
# --use panel smoothsteps, scandir
# --no way to constrain w/cut or label
# --no way to enter noisedf, desired p-val
# --hack required for picking a 'representative' volume for uniqvtx
# --for now, just do interactively, as w/single sub
#
#  global hemisurfext stmptcl3 cmdsonlyid
# 
#  ###### 3rd pass: TODO: calc FDR from F->p
#  ## make non-window standalone tksurfer script (750 msec w/single subj)
#  set id [open $stmptcl3 w 0644]
#  puts $id "set scandir 1-polletdilima1"
#  puts $id "set stem polletdilima1-1-vreg+orig"
#  puts $id "set smoothsteps 0"
#  puts $id "setfile val */\$scandir/\${stem}_f-\$hemi.w"
#  puts $id "read_binary_values"
#  puts $id "smooth_val \$smoothsteps"
#  puts $id "swap_stat_val"
#  puts $id "setfile stat \$val"
#  puts $id "set noisedf 245"
#  puts $id "setfile label */\$scandir/\$hemi-UniqSampVtxs.label"
#  #puts $id "read_uniqsamp_vertices"  ;# need this optional, which volume?
#  puts $id "pval_from_fourier_fstat"
#  puts $id "find_FDR_from_pvals 0.05"
#  puts $id "set id [open $tmpdir/TmpFDROutput.txt w 0644]"  ;# 1 outval here
#  puts $id "puts \$id \$pval_FDR"
#  puts $id "exit"
#  close $id
#  ## dump script (commented out) to live log else csurf log
#  set id [open $stmptcl3 r]
#  if {$cmdsonlyid != "fileNONE"} {  ;# if log open, dump tcl script into it
#    puts $cmdsonlyid "### made tmp tksurfer tcl script: ${stmptcl3}"
#    foreach line [split [read $id] "\n"] { puts $cmdsonlyid "# $line" }
#  } else {  ;# dump to csurf log (N.B.: cmdlog, not surflog)
#    putlog "### made tmp tksurfer tcl script: ${stmptcl3}"
#    foreach line [split [read $id] \n] { putlog "# $line" }
#  }
#  close $id
#  ## make, run cmd
#  set command "$bindir/tksurfer $dispname $hemi $surfext -tcl $stmptcl3"
#  runacmd "$command" $samp2subjbu "SAMP2SUBJ  " cmdinput $cmdlog cmdpid
#  tkwait variable cmdpid
#  rmlog $stmptcl3

  after 1000 { if [winfo exists .sphavgprogress] {destroy .sphavgprogress} }
  if {!$purplekillseq} {
    writearrayparms $datfile sphavg
  } else {
    set purplekillseq 0
  }
}

### VOLAVG button command (Cross Sess Spherical Average panel)
proc volavgcxcmd { } {
  global cmdlog volavgbu volavgjob purplekillseq
  global env session afnibindir bgcol runbgcol ffont
  global realname complexname amprealname ampcomplexname
  global cplxstatname1
  global sphavgdir sphavglists
  global spgnums spgsessions spgsubjects spgscandirs spgstatbrikprefs
  global onearch

  if {$sphavgdir == "image/__no_dir__"} {
    confirmalert " Volume Average:  No scandir for average\n\n\
                   Replace name:\n\n\     __no_dir__\n\n\
                   Make SphereAvg dir, try again"
    return
  }
  if ![info exists spgnums(00)] {
    confirmalert " Volume Average:  no scans to average:\n\n\
                   For each session to average:\n\n\
                   (1) click ADD SESS button to make new blank line\n\
                   (2) select Session,Scandir,StatBrikStem dropdowns\n\
                   (blank VtxListPref OK)"
    return
  }
  set spacesOK ""
  if [string match "* *" $env(FUNCTIONALS_DIR)] {
    putlog "volavgcx: ### found env path spaces: using AFNI_PATH_SPACES_OK=YES"
    set spacesOK AFNI_PATH_SPACES_OK=YES
  }

  ### some re-used vars
  set finalstem [file tail $sphavgdir]     ;# image/avgname -> avgname
  set phasetype $sphavglists(00,phasetype) ;# real/polar/eccen/2cond
  set ttestcompval $sphavglists(00,ttestcompval)
  set tmppref tmpdir                       ;# for indiv sub calculations
  set avgcnt [array size spgnums]

  ### first check fields filled
  foreach num [lsort [array names spgnums]] {
    set n $num
    while { [string match 0* $n] } { set n [string range $n 1 end] } ;# fixhex
    set onebased [format "%02d" [expr $n + 1]]  ;# empty n OK
    if {$spgsessions($num) == ""} \
      { confirmalert "line $onebased: empty Session entry";      return }
    if {$spgsubjects($num) == ""} \
      { confirmalert "line $onebased: empty Subject entry";      return }
    if {$spgscandirs($num) == ""} \
      { confirmalert "line $onebased: empty Scandir entry";      return }
    # empty spgvtxlistprefs OK (for SPHEREAVG)
    # empty spgmorphsurfs OK (for SPHEREAVG)
    if {$spgstatbrikprefs($num) == ""} \
      { confirmalert "line $onebased: empty StatBrikStem entry"; return }
  }

  ### re-check infiles exist (checked at select_ but may have changed)
  foreach num [lsort [array names spgnums]] {
    set n $num
    while { [string match 0* $n] } { set n [string range $n 1 end] } ;# fixhex
    set onebased [format "%02d" [expr $n + 1]]  ;# empty n OK
    set fullscandir $env(FUNCTIONALS_DIR)/$spgsessions($num)/$spgscandirs($num)
    set infixlist "$amprealname $ampcomplexname $realname $complexname"
    if {$phasetype == "real"} { set infixlist " {} " }  ;# 1 empty entry
    foreach infix $infixlist {
      set fullstatbrik $fullscandir/$spgstatbrikprefs($num)${infix}+orig.BRIK
      if ![file exists $fullstatbrik] {
        if { $infix == "$realname" || $infix == "$complexname" } {
         confirmalert "line $onebased: missing sqrtF file:\n\n\  $fullstatbrik"
        } else {
         confirmalert "line $onebased: missing rawamp file:\n\n\  $fullstatbrik"
        }
        return
      }
    }
  }

  ### new popup for meter
  set pr .volavgprogress
  if [winfo exists $pr] { destroy $pr }
  toplevel $pr -bg $bgcol   ;# next: move aside so clickable if read log
  wm geometry $pr +[expr [winfo rootx .]-10]+[expr [winfo rooty .]+50]
  wm title $pr "Volume Avg -- Progress"
  tixMeter $pr.me -value 0 -bg $bgcol -highlightbackground $bgcol \
    -fillcolor $runbgcol -width 350 -bd 2 -relief sunken
  pack $pr.me -side top -padx 80 -pady 5
  set volavgjob \
    "starting 1st pass stats (avg,t)... ($spgsubjects(00))                     "
  label $pr.la0 -textvariable volavgjob -font $ffont -bg $bgcol
  pack $pr.la0 -side top -pady 10

  ###### 1st pass: 3ttest(avg+ttst) _x,_y,_r,_i => $finalstem-stats-vol${infix}
  set infixticks 4   ;# _x, _y, _r, _i
  if {$phasetype == "real"} { set infixticks 1 }
  set totalticks $infixticks
  set ticks 0
  set purplekillseq 0
  cdlog $env(FUNCTIONALS_DIR)/$session/$sphavgdir
  set infixlist "$amprealname $ampcomplexname $realname $complexname"
  if {$phasetype == "real"} { set infixlist " {} " }  ;# 1 empty entry
  foreach infix $infixlist {
    if {$purplekillseq} { continue }  ;# curr coarse-grained interrupt
    # construct avglist for one infix
    set inlist {}
    foreach num [lsort [array names spgnums]] {
      set fullscandir \
        $env(FUNCTIONALS_DIR)/$spgsessions($num)/$spgscandirs($num)
      set fullinstem $fullscandir/$spgstatbrikprefs($num)${infix}
      lappend inlist $fullinstem+orig
    }
    set locoutstem $finalstem-stats-vol${infix}
    # rm prev outbrik if there (AFNI won't overwrite)
    if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD}
    if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK}
    set tmpttestcompval 0.0   ;# comp t's only used no-infix wfile
    if {$infix == ""} {
      set tmpttestcompval $ttestcompval
    }
    set command "env $spacesOK AFNI_VERSION_CHECK=NO $afnibindir/3dttest \
      -prefix $locoutstem \
      -base1 $tmpttestcompval \
      -datum float \
      -set2 [lbackslashspaces $inlist]"   
    # prev outformat: short if 1st inp byte/short else float
    runacmd "$command" $volavgbu "VOLAVG  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    # LSBfirst output on Intel
    forcebrikMSBfirst $locoutstem+orig nowarn $volavgbu "VOLAVG  "
    # update meter
    incr ticks
    if [winfo exists $pr] {
      $pr.me config -value [expr $ticks/$totalticks.0]
      set volavgjob "finished stats (avg,t): infix: $infix ($spgsubjects($num))"
      update idletasks
    }
  } ;# infixes (_x,_y,_r,_i)

  ###### 2nd pass: if not real, calc Hagler2007-cmplx-F (TODO:Rayleigh-p-expn)
  # (xav^2 + yav^2)/2 / (((sumsub(_x-xav)^2)/n + sumsub(_y-yav)^2/n) / (2*n-2))
  if {$phasetype == "polar" || $phasetype == "eccen" || $phasetype == "2cond"} {
    after 500    
    if [winfo exists $pr] {
      wm title $pr "Volume Avg -- F-From-Complex (TODO: Rayleigh)"
      $pr.me config -value 0.0
      set volavgjob \
        "starting average2... ($finalstem)                            "
      update idletasks
    }

    ### (1) get numerator from overall _x,_y avgs calc'd above (one-time)
    cdlog $env(FUNCTIONALS_DIR)/$session/$sphavgdir
    # next two BRIKs have both 0=mean,1=tstat -- use mean
    set locinstem1 $finalstem-stats-vol${amprealname}
    set locinstem2 $finalstem-stats-vol${ampcomplexname}
    set locoutstem numerator
    # check input
    foreach instem "$locinstem1 $locinstem2" {
      if ![file exists ${instem}+orig.BRIK] {
        confirmalert " Volume Average: cross subj F-from-complex calc:\n\n\
                       3dcalc input missing:\n\n\
                       ${instem}+orig.BRIK\n\n\
                       (output of 3dttest -- x,y Fourier component avgs)"
        cdfunctscripts
        if [winfo exists $pr] { destroy $pr }
        return
      }
    }
    # rm prev outbrik if there from interrupt (AFNI won't overwrite)
    if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD}
    if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK}
    # go: first subbrik of each input is mean
    putlog "\n(1) get F numerator (vol) from _x,_y avgs calc'd above"
    set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
      -prefix $locoutstem \
      -a $locinstem1+orig\[0\] \
      -b $locinstem2+orig\[0\] \
      -expr \"((a^2)+(b^2))/2.0\" \
      -datum float"  ;# float during calc
    runacmd "$command" $volavgbu "VOLAVG  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    if [winfo exists $pr] {
      $pr.me config -value 0.1
      set volavgjob "finished calculate numerator of F-from-complex"
      update idletasks
    }
    # don't swap, used as AFNI input only

    ### (2) sum squared _x,_y residuals (2 demon terms) + normed _x,_y
    # get sums: xsum = sum(sub(_x-xav)^2)/n), ysum = sum(sub(_y-yav)^2/n)
    set infixticks 2   ;# _x, _y
    set totalticks [expr $avgcnt*$infixticks]
    set ticks 0
    foreach num [lsort [array names spgnums]] { ;#outerloop: subj/lines toavg
      set subjname $spgsubjects($num)
      set inpref $spgstatbrikprefs($num) ;# e.g.: eccletdilim2sm-1-vreg+orig
      set n $num
      while {[string match 0* $n]} {set n [string range $n 1 end]} ;#fixhex
      if { "$n" == "" } { set n 0 }
      set fnum [format "%03d" $n]  ;# 000,001,...
      foreach infix "$amprealname $ampcomplexname" {
        if {$purplekillseq} { continue }
        set fullscandir \
          $env(FUNCTIONALS_DIR)/$spgsessions($num)/$spgscandirs($num)
        set fullinstem $fullscandir/$spgstatbrikprefs($num)
        ## 2a: runningsums F-denom b/c 3dcalc a-z symbols might overflow 1shot
        set locinstem1 sumsqresid-previous${infix}  ;# prev tot
        set locinstem2 ${fullinstem}${infix}        ;# currsub
        set locinstem3 $finalstem-stats-vol${infix} ;# avg=brk1
        set locoutstem sumsqresid-current${infix}   ;# currtot
        if {"$fnum" == "000"} {  ;# mk cmd, first pass (both infixes)
          # rm any tmpbriks from interrupt, check inp, start running avg
          foreach tmpbrikhead \
              [glob -nocomplain sumsqresid-previous${infix}+orig* \
                                sumsqresid-current${infix}+orig*] {
            if [file exists $tmpbrikhead] { rmlog $tmpbrikhead }
          }
          foreach instem "$locinstem2 $locinstem3" {
            if ![file exists ${instem}+orig.BRIK] {
              confirmalert \
                " Volume Average: sub-by-sub sumsq residuals:\n\n\
                  3dcalc input missing (begin run total):\n\n\
                  ${instem}+orig.BRIK\n\n\
                  (output of 3dcalc -- curr resid tot, currsub, avg)"
              cdfunctscripts
              if [winfo exists $pr] { destroy $pr }
              return
            }
          }
          putlog "\n(2) start $infix (vol) running sum sq resid ($locinstem2)"
          set eq "\"0.0+(((b-c)^2)/$avgcnt.0)\""
          set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -prefix $locoutstem \
            -b $locinstem2+orig \
            -c $locinstem3+orig\[0\] \
            -expr $eq \
            -datum float"  ;# float for calc
        } else { ;# mk cmd, not first pass
          # rm "prev" (=prevprevloop), mv "curr" (=prevloop out)->new input
          if [file exists $locinstem1+orig.HEAD] { rmlog $locinstem1+orig.HEAD}
          if [file exists $locinstem1+orig.BRIK] { rmlog $locinstem1+orig.BRIK}
          set command "env AFNI_VERSION_CHECK=NO $afnibindir/3drename \
            $locoutstem $locinstem1"
          runacmd "$command" $volavgbu "VOLAVG  " cmdinput $cmdlog cmdpid
          tkwait variable cmdpid
          # check inputs, continue running avg/total
          foreach instem "$locinstem1 $locinstem2 $locinstem3" {
            if ![file exists ${instem}+orig.BRIK] {
              confirmalert \
                " Volume Average: sub-by-sub sumsq residuals:\n\n\
                  3dcalc input missing (continue run total):\n\n\
                  ${instem}+orig.BRIK\n\n\
                  (output of 3dcalc -- curr resid tot, currsub, avg)"
              cdfunctscripts
              if [winfo exists $pr] { destroy $pr }
              return
            }
          }
          putlog \
            "\n(2a) continue $infix (vol) running sum sq resid ($locinstem2)"
          set eq "\"a+(((b-c)^2)/$avgcnt.0)\""
          set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
            -prefix $locoutstem \
            -a $locinstem1+orig \
            -b $locinstem2+orig \
            -c $locinstem3+orig\[0\] \
            -expr $eq \
            -datum float"  ;# float for calc
        } ;# not first pass
        # go
        runacmd "$command" $volavgbu "VOLAVG  " cmdinput $cmdlog cmdpid
        tkwait variable cmdpid
        ## 2b: TODO: get running sums normed _r,_i (_r/_a, _i/_a) for Rayleigh
        # update meter
        incr ticks
        if [winfo exists $pr] {
          $pr.me config -value [expr $ticks/$totalticks.0]
          set volavgjob \
            "finished sq residuals: $locoutstem ($spgsubjects($num))"
          update idletasks
        }
      } ;# for infixes _x,_y
    } ;# subjects

    ### (3) final F-from-complex calc
    # final = numerator/((xsum+ysum)/(2*n-2))
    set infix $cplxstatname1  ;# _f (Rayleigh = _g)
    set locinstem1 numerator
    set locinstem2 sumsqresid-current${amprealname}
    set locinstem3 sumsqresid-current${ampcomplexname}
    set locoutstem $finalstem-stat-vol${infix}
    # rm prev outbrik if there from interrupt (AFNI won't overwrite)
    if [file exists $locoutstem+orig.HEAD] {rmlog $locoutstem+orig.HEAD}
    if [file exists $locoutstem+orig.BRIK] {rmlog $locoutstem+orig.BRIK}
    # check input: numerator, real/complex sum sq residuals
    foreach instem "$locinstem1 $locinstem2 $locinstem3" {
      if ![file exists ${instem}+orig.BRIK] {
        confirmalert " Volume Average: cross subj F-from-complex calc:\n\n\
                       3dcalc input missing:\n\n\
                       ${instem}+orig.BRIK\n\n\
                       (output of 3dcalc -- numer, sum sq x,y residuals)"
        cdfunctscripts
        if [winfo exists $pr] { destroy $pr }
        return
      }
    }
    # go
    putlog "\n(3) final F-from-complex calc (vol) for $avgcnt subjects"
    set eps 0.0   ;# or 0.00000001 to stop div by zero (e.g. infiles ident)
    set command "env AFNI_VERSION_CHECK=NO $afnibindir/3dcalc \
      -prefix $locoutstem \
      -a $locinstem1+orig \
      -b $locinstem2+orig \
      -c $locinstem3+orig \
      -expr \"a/((b+c+$eps)/((2.0*$avgcnt.0)-2.0))\" \
      -datum float" ;# -fscale -datum short=>trunc 82% misfit lost num prec
    runacmd "$command" $volavgbu "VOLAVG  " cmdinput $cmdlog cmdpid
    tkwait variable cmdpid
    # clean up tmp BRIK's
    foreach tmpbrikhead \
       "sumsqresid-previous${realname}+orig.HEAD \
        sumsqresid-previous${realname}+orig.BRIK \
        sumsqresid-previous${complexname}+orig.HEAD \
        sumsqresid-previous${complexname}+orig.BRIK \
        sumsqresid-previous${amprealname}+orig.HEAD \
        sumsqresid-previous${amprealname}+orig.BRIK \
        sumsqresid-previous${ampcomplexname}+orig.HEAD \
        sumsqresid-previous${ampcomplexname}+orig.BRIK \
        $locinstem1+orig.HEAD $locinstem2+orig.HEAD $locinstem3+orig.HEAD \
        $locinstem1+orig.BRIK $locinstem2+orig.BRIK $locinstem3+orig.BRIK" {
      if [file exists $tmpbrikhead] { rmlog $tmpbrikhead }
    }
    forcebrikMSBfirst $locoutstem+orig nowarn $volavgbu "VOLAVG  "
  } ;# complex-F: skipped if avg not complex-valued
  cdfunctscripts

  # explicit name (not $pr) because 'after' executes in global context
  after 1000 { if [winfo exists .volavgprogress] {destroy .volavgprogress} }
  if {!$purplekillseq} { savesphavgcxparms } else { set purplekillseq 0 }
}

### Make SphereAvg Dir button -- mkdir if need, set sphavgdir,sessionscanlists
proc mksphavgdir { newdir } {
  global env session sphavgdir newsphavgdir sphavglists sessionscanlists

  # check config'd dir
  if {$sphavgdir != "image/__no_dir__"} {
    if { [file exists $env(FUNCTIONALS_DIR)/$session/$sphavgdir] } {
      confirmalert " Make SphereAvg Dir: using existing dir: $sphavgdir"
      set newsphavgdir $sphavgdir
      set sphavglists(00,sphavgdir) $sphavgdir
      unset sessionscanlists
      set sessionscanlists($sphavgdir,type) sphavgscan
      return
    } else {
      confirmalert "Make SphereAvg Dir: saved dir $sphavgdir not found, unset"
      set sphavgdir image/__no_dir__
      return
    }
  }

  # check proposed dir
  if {$newdir == "image/__no_dir__"} {
    confirmalert "Make SphereAvg Dir:  Replace name:\
              \n\n    __no_dir__\
              \n\nwith something more informative and try again"
    return
  }
  if {$newdir == "image/prf"} {  ;# block in case funct prf never opened/saved
    confirmalert "Make SphereAvg Dir:  bad directory name:\
              \n\n    image/prf\
              \n\n(reserved for single-subject SamSrf conversions)\
              \n\nChange name and try again (e.g., use image/prf-avg)"
    return
  }
  set fullnewdir $env(FUNCTIONALS_DIR)/$session/$newdir ;# newdir incl "image"
  if ![file exists $fullnewdir] {   ;# proposed scandir doesn't exist -> make
    if [canwriteormakefile $fullnewdir] {
      mkdirlog $fullnewdir
      set sphavgdir $newdir           ;# newsphavgdir (=newdir) already same
      set sphavglists(00,sphavgdir) $sphavgdir ;# index sessscanlists
      unset sessionscanlists                   ;# assumes 1 scandir/$session
      set sessionscanlists($sphavgdir,type) sphavgscan ;# for render w/o Save
      confirmalert "Make SphereAvg Dir: created: $fullnewdir"
    } else {
      confirmalert "Make SphereAvg Dir: can't create: $fullnewdir"
      set sphavgdir image/__no_dir__
      return
    }
  } else {  ;# proposed scandir exists -> use
    confirmalert "Make SphereAvg Dir: using existing dir: $sphavgdir"
    set newsphavgdir $sphavgdir
    set sphavglists(00,sphavgdir) $sphavgdir
    unset sessionscanlists
    set sessionscanlists($sphavgdir,type) sphavgscan
    return
  }
}

### ADD, DEL button cmds (Cross Sess Spherical Avg panel)
proc sphavgcxwline { action enswin } {
  global sessionscombo spgnums
  global spgsessions spgsubjects spgscandirs spgvtxlistprefs spgmorphsurfs
  global spgstatbrikprefs
  global bgcol selbgcol entbgcol ffont ffontb hfont smallscreenflag

  set sesslistheight 25; set scanlistheight 15; set vtxlistheight 15
  if {$smallscreenflag} {
    set sesslistheight 10; set scanlistheight 10; set vtxlistheight 10
  }
  set spglinelist [lsort [info commands $enswin.li??]]
  if {$action == "add"} {
    set num [format "%02d" [llength $spglinelist]]
    if {$num >= 99} {
      confirmalert "too many sessions to average ($num)" 
      return
    }
    frame $enswin.li$num -bg $bgcol
    if [info exists spgnums($num)]          { unset spgnums($num)          }
    if [info exists spgsessions($num)]      { unset spgsessions($num)      }
    if [info exists spgsubjects($num)]      { unset spgsubjects($num)      }
    if [info exists spgscandirs($num)]      { unset spgscandirs($num)      }
    if [info exists spgvtxlistprefs($num)]  { unset spgvtxlistprefs($num)  }
    if [info exists spgmorphsurfs($num)]    { unset spgmorphsurfs($num)    }
    if [info exists spgstatbrikprefs($num)] { unset spgstatbrikprefs($num) }
    # label -- intern %02d 0-based, display %02d 1-based (hexfix, reformat)
    set spgnums($num) $num
    set n $num
    while { [string match 0* $n] } { set n [string range $n 1 end] } ;# fixhex
    set onebased [format "%02d" [expr $n + 1]]  ;# empty n OK
    label $enswin.li$num.l0 -text $onebased -bg $bgcol
    # 1: session (select gets passed scandirs combo)
    # Notes: next has min color opts for bgcol change w/o wrappers fixcolors
    # Notes: native tix font here vs. {entry,label,listbox}.font $ffont
    tixComboBox $enswin.li$num.cbx0 -dropdown true \
      -command "cbx:select_sphavgsess $num $enswin.li$num.cbx2" \
      -editable true \
      -variable spgsessions($num) -listwidth 208 \
      -options "entry.width 11 listbox.height $sesslistheight"
      # listbox.width 18 -> 25
    # 2: subject (not editable)
    entry $enswin.li$num.e1 -textvariable spgsubjects($num) -state disabled \
     -bg $bgcol -selectbackground $selbgcol -width 10 -selectforeground black \
      -highlightbackground $bgcol -disabledforeground #555555 -font $hfont
    # 3: scandir (select gets passed wfile combo)
    tixComboBox $enswin.li$num.cbx2 -dropdown true \
      -command \
      "cbx:select_sphavgscandir $num $enswin.li$num.cbx3 $enswin.li$num.cbx4" \
      -editable true \
      -variable spgscandirs($num) -listwidth 278 \
      -options "entry.width 21 listbox.height $scanlistheight"
      # listbox.width 35
    # 4: wfile
    tixComboBox $enswin.li$num.cbx3 -dropdown true \
      -command "cbx:select_sphavgwfile $num" -editable true \
      -variable spgvtxlistprefs($num) -listwidth 278 \
      -options "entry.width 23 listbox.height $vtxlistheight"
      # listbox.width 35
    # 5: morph surf (not editable)
    entry $enswin.li$num.e4 -textvariable spgmorphsurfs($num) -state disabled \
      -bg $bgcol -selectbackground $selbgcol -width 9 -selectforeground black \
      -highlightbackground $bgcol -disabledforeground #555555 -font $hfont
    # 6: stats BRIK -- added after sphere avg working
    tixComboBox $enswin.li$num.cbx4 -dropdown true \
      -command "cbx:select_volavgstatbrik $num" -editable true \
      -variable spgstatbrikprefs($num) -listwidth 278 \
      -options "entry.width 15 listbox.height $vtxlistheight"
      # listbox.width 35
    # inits
    set sesslist [$sessionscombo subwidget listbox get 0 end]
    foreach sess $sesslist { $enswin.li$num.cbx0 insert end $sess }
    pack $enswin.li$num -side top
    pack $enswin.li$num.l0 $enswin.li$num.cbx0 $enswin.li$num.e1 \
         $enswin.li$num.cbx2 $enswin.li$num.cbx3 $enswin.li$num.e4 \
         $enswin.li$num.cbx4 -side left -padx 5
  }
  if {$action == "delete" && "$spglinelist" != ""} {
    set lastnum [format "%02d" [expr [llength $spglinelist] - 1]]
    destroy [lindex $spglinelist end]
    unset spgsessions($lastnum) spgsubjects($lastnum) spgscandirs($lastnum)
    unset spgvtxlistprefs($lastnum) spgmorphsurfs($lastnum) spgnums($lastnum)
    unset spgstatbrikprefs($lastnum)
  }
}

### Cross Sess Spherical Average panel Save,Save/Close: panelconfigs->csurf.dat
proc savesphavgcxparms { } {
  global spgnums hemi sphavgdir
  global spgsessions spgsubjects spgscandirs spgvtxlistprefs spgmorphsurfs
  global spgstatbrikprefs sphavglists datfile

  # currpanel -> sphavglists
  set sessionscanlists($sphavgdir,type) sphavgscan  ;# set
  set sphavglists(00,hemi) $hemi           ;# cp curr global
  set sphavglists(00,sphavgdir) $sphavgdir ;# cp curr global
  #sphavglists(00,smoothsteps2ico) -- curr state from textvar will be saved
  #sphavglists(00,mapmethod)       -- curr state from selectvar will be saved
  #sphavglists(00,phasetype)       -- curr state from selectvar will be saved
  #sphavglists(00,ttestcompval)    -- curr state from textvar will be saved
  # clear all widgetline sphavglists vars (prev config maybe had more lines)
  foreach index [array names sphavglists] {
    #N.B.: 01,scandir is actually 01,iscandir, left because saved in csurf.dats
    foreach indextail \
      "session subject scandir vtxlistpref morphsurf statbrikpref" {
      #if [string match ??,$indextail $index] { unset sphavglists($index) }
      if [string match \[0123456789\]\[0123456789\],$indextail $index] {
        unset sphavglists($index)
      }
    }
  }
  foreach num [array names spgnums] {
    set sphavglists($num,session)      $spgsessions($num)
    set sphavglists($num,subject)      $spgsubjects($num)
    set sphavglists($num,scandir)      $spgscandirs($num)
    set sphavglists($num,vtxlistpref)  $spgvtxlistprefs($num)
    set sphavglists($num,morphsurf)    $spgmorphsurfs($num)
    set sphavglists($num,statbrikpref) $spgstatbrikprefs($num)
  }

  writearrayparms $datfile sphavg

  if {$sphavgdir == "image/__no_dir__"} {
    confirmalert "N.B.: Use Make SphereAvg Dir to create dir to hold avg" 
  }
}

### make Cross Sess Spherical Average popup (parallel to setupscans, not add*)
proc setupsphavgcx { } { 
  global name env hemi session sessionscanlists dispname datfile
  global sphavglists sphavgdir newsphavgdir
  global subjectscombo surfacescombo sessionscombo scandirscombo
  global sphereavgbu avgsurfbu samp2subjbu volavgbu
  global pfont ffont ffontb sfont tfont hfont
  global bgcol selbgcol hilcol hilbgcol actbgcol entbgcol logflag
  global spgnums
  global spgsessions spgsubjects spgscandirs spgvtxlistprefs spgmorphsurfs
  global spgstatbrikprefs dispnamecombo helpwinlines xcmd

  if {$session == "__nosession__"} { return }
  if [winfo exists .sphavgdialog] {
    raise .sphavgdialog
    confirmalert "Finish current CrossSessTools avg first\n(or start 2nd csurf)"
    return
  }
  if [winfo exists .setuppopup] {
    raise .setuppopup
    confirmalert "Close current SessionTools panel first"
    return
  }
  set f [toplevel .sphavgdialog -bg $bgcol]
  ::tk::classic::restore  ;# newpkgtix
  configtixbookcbxent $f
  positionpopup $f
  wm protocol $f WM_DELETE_WINDOW "killsphavgcx $f"  ;# popup killboxOK proc
  wm title $f "Cross Sess Spherical Average"

  ### read datfile if there (may contain configs for no-longer-existing dirs)
  if [file exists $datfile] {
    readarrayparms $datfile sphavg    ;# does cleararrays first
  } else {
    cleararrays sphavg
  }

  ### default any missing (*after* cleararrays)
  # for distinguishing from single-subject session at addrenderscan time
  if [info exists sphavglists(00,sphavgdir)] {
    set sessionscanlists($sphavglists(00,sphavgdir),type) sphavgscan
  } else {
    set sessionscanlists(00,type) sphavgscan  ;# init unset at mksphavdir time
  }
  # this panel
  if ![info exists sphavglists(00,smoothsteps2ico)] {
    set sphavglists(00,smoothsteps2ico) 1
  }
  if ![info exists sphavglists(00,smoothsteps2sub)] {
    set sphavglists(00,smoothsteps2sub) 0
  }
  if ![info exists sphavglists(00,phasetype)] {
    set sphavglists(00,phasetype) polar
  }
  if ![info exists sphavglists(00,mapmethod)] {
    set sphavglists(00,mapmethod) nnfr
  }
  if ![info exists sphavglists(00,ttestcompval)] {
    set sphavglists(00,ttestcompval) 0.0
  }
  if ![info exists sphavglists(00,clustarea)] {
    set sphavglists(00,clustarea) 130
  }
  if ![info exists sphavglists(00,preclustfthr)] {
    set sphavglists(00,preclustfthr) 5.0 
  }
  if ![info exists sphavglists(00,permtestcnt)] {
    set sphavglists(00,permtestcnt) 0 
  }
  if ![info exists sphavglists(00,clustsurf)] {
    set sphavglists(00,clustsurf) smoothwm
  }

  ### main frames
  # action
  set a [frame $f.ac -bg $bgcol -bd 10 -bg $bgcol]
  pack $a -side top
  # main (inside scrolled window: -shrink y breaks, newpkgtix: -scrollbar auto)
  set scr [tixScrolledWindow $f.sw -height 475 -scrollbar auto] ;# 15 lines
  $scr.f1 config -bd 2 -relief sunken ;# -highlightbackground $bgcol ;#thkbord
  $scr subwidget vsb config -highlightbackground $bgcol
  pack $scr -side top -padx 0 -expand yes -fill y ;# for resizable y, min y
  set scrw [$scr subwidget window]
  $scrw config -bg $bgcol
  set m [frame $scrw.f1 -bd 0 -bg $bgcol]  ;# was -bd 5, test: -bg green
  pack $m -side top -fill both
  # response
  set r [frame $f.re -bd 10 -bg $bgcol]
  pack $r -side top

  ### top action frame
  frame $a.se -bd 2 -relief groove
  # corner label
  label $a.se.t0 -text "AvgSess:" -font $ffontb -pady 7 -padx 4
  label $a.se.t1 -textvariable session -font $ffontb -pady 7 -padx 4
  pack $a.se -side left -padx 10
  pack $a.se.t0 $a.se.t1 -side left
  # Make SphereAvg Dir, entry
  set scandirslist [getfunctiscandirslist]
  set tmplist { }
  foreach scan $scandirslist {
    if ![string match *~ $scan] { lappend tmplist $scan }
  }
  set scandirslist $tmplist
  set scandircnt [llength $scandirslist]
  if {$scandircnt == 0} { set sphavgdir image/__no_dir__ }
  if {$scandircnt == 1} {
    set sphavgdir [lindex $scandirslist 0]
    foreach scantype [array names sessionscanlists *,type] {
      if [string match "image/*" $scantype] {
        if {$sessionscanlists($scantype) == "functscan"} {
          tkwait visibility $f
          destroy $f
          confirmalert "A scandir in this session:\
                    \n\n    $scantype\
                    \n\nis already configured as a single-subject\
                      \nfunctional scandir.  First, use:\
                    \n\n    File -> New SphereAvg\
                    \n\nto create a new empty Spherical Average\
                      \nsession, and try again with it"
          return
        }
      }
    }
    if {$sphavgdir == "image/prf"} {  ;# block in case funct never opened/saved
      tkwait visibility $f
      destroy $f
      confirmalert "A single scandir in this session already exists:\
                \n\n    image/prf\
                \n\nThis name is reserved for single-subj SamSrf conversions\
                \n\n(1) Use  File -> New SphereAvg  to create\
                  \n      new empty Spherical Average session\
                \n\n(2) Create scandir in it with  \"Make SphereAvg Dir\"\
                  \n      (e.g., use name:  image/prf-avg)"
      return
    }
  }
  if {$scandircnt >= 2} {
    tkwait visibility $f
    destroy $f
    set formatlist "    "
    foreach sdir $scandirslist { set formatlist "${formatlist}\n    ${sdir}" }
    confirmalert "These scandirs already exist:\n\
        $formatlist\n\n\
        ...not a Spherical Average session?\n\n\
        Only 1 scandir allowed in this kind of session"
    return
  }
  set newsphavgdir $sphavgdir
  button $a.bu0 -text "Make SphereAvg Dir" -padx 1 -pady 5 -font $hfont \
    -highlightbackground $bgcol -command { mksphavgdir $newsphavgdir }
  entry $a.e0 -textvariable newsphavgdir -width 21 -font $hfont \
    -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
    -selectforeground black  ;# linux
  pack $a.bu0 $a.e0 -side left
  # action buttons
  frame $a.sp -width 10 -bg $bgcol
  pack $a.sp -side left
  button $a.bu1 -text "SPHEREAVG" -padx 2 -pady 5 -font $ffontb \
       -command "sphavgcxcmd" -highlightbackground $bgcol
  set sphereavgbu $a.bu1
  button $a.bu2 -text "AVGSURF" -padx 2 -pady 5 -font $ffontb \
       -command "avgsurfcmd" -highlightbackground $bgcol
  set avgsurfbu $a.bu2
  button $a.bu3 -text "SAMP2SUBJ" -padx 2 -pady 5 -font $ffontb \
       -command "sphavgcxsamp2subj" -highlightbackground $bgcol
  set samp2subjbu $a.bu3
  button $a.bu4 -text "VOLAVG" -padx 2 -pady 5 -font $ffontb \
       -command "volavgcxcmd" -highlightbackground $bgcol
  set volavgbu $a.bu4
  pack $a.bu1 $a.bu2 $a.bu3 $a.bu4 -padx 2 -side left ;#  -anchor e

  ### main panel frame
  frame $m.l -bg $bgcol
  pack $m.l -side top -pady 8
  label $m.l.la1 -bg $bgcol -font $tfont -bg $bgcol -text \
    "(1) \"Make SphereAvg Dir\" above to create\
     single informatively-named scandir for average data"
  label $m.l.la2 -bg $bgcol -font $tfont -bg $bgcol -text \
    "(2) \"ADD\" below for empty line(s),\
     select Session, Scandir, VtxListPref, (StatBrikStem) from dropdowns"
  pack $m.l.la1 $m.l.la2 -side top -anchor w -padx 10

  ## main panel action button subframe
  frame $m.bus -bd 3 -bg $bgcol ;# test: -bg green
  pack $m.bus -side top -padx 0
  ## ADD/DEL buttons
  button $m.bus.bu1 -text "ADD" -font $ffontb -pady 2 -padx 0 \
    -command "sphavgcxwline add $m.ens" -highlightbackground $bgcol
  set addnewsessbu $m.bus.bu1
  button $m.bus.bu2 -text "DEL" -font $ffontb -pady 2 -padx 1 \
    -command "sphavgcxwline delete $m.ens" -highlightbackground $bgcol
  pack $m.bus.bu1 $m.bus.bu2 -side left -padx 0
  ## hemi
  tixSelect $m.bus.hem -allowzero false -radio true -label "hemi:" \
    -orientation horizontal -options "label.width 4 label.font $ffont"
  $m.bus.hem subwidget label config -bg $bgcol   ;# tix options bug
  $m.bus.hem subwidget label config -font $ffont ;# tix options bug
  $m.bus.hem add rh \
    -text R -font $sfont -width 1 -bg $bgcol -padx 2 -pady 2 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $m.bus.hem add lh \
    -text L -font $sfont -width 1 -bg $bgcol -padx 2 -pady 2 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $m.bus.hem add both \
    -text BOTH -font $sfont -width 4 -bg $bgcol -padx 2 -pady 2 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
  $m.bus.hem config -variable hemi
  pack $m.bus.hem -side left -padx 2
  ## display subject
  tixComboBox $m.bus.cbx -label "sub:" -dropdown true -editable true \
    -command cbx:select_dispsubject -variable dispname -listwidth 208 \
    -options "label.width 3 label.font $ffont" ;# listbox.width 14 -> 25
  $m.bus.cbx subwidget entry config -width 9      ;# tix options bug
  $m.bus.cbx subwidget listbox config -height 23  ;# tix options bug
  $m.bus.cbx subwidget label config -font $ffont  ;# tix options bug
  set subjnamelist [$subjectscombo subwidget listbox get 0 end]
  foreach subjname [lsort $subjnamelist] { $m.bus.cbx insert end $subjname }
  pack $m.bus.cbx -side left -padx 2
  set dispnamecombo $m.bus.cbx
  ## smoothing
  frame $m.bus.sm -bg $bgcol
  label $m.bus.sm.la -text "smooth2ico:" -font $ffont -bg $bgcol
  entry $m.bus.sm.en -textvariable sphavglists(00,smoothsteps2ico) -width 2 \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
      -selectforeground black -font $hfont
  pack $m.bus.sm -side left -padx 2
  pack $m.bus.sm.la $m.bus.sm.en -side left
  ## mapmethod
  frame $m.bus.sp0 -width 4 -bg $bgcol
  pack $m.bus.sp0 -side left
  tixSelect $m.bus.map -allowzero false -radio true -orientation horizontal
  $m.bus.map subwidget label config -bg $bgcol  ;# vert 1pix line at left
  $m.bus.map add nnfr -text nnfr -bg $bgcol -padx 0 -pady 0  ;# -font $sfont
  $m.bus.map add nnf  -text nnf  -bg $bgcol -padx 0 -pady 0  ;# -font $sfont
  $m.bus.map config -variable sphavglists(00,mapmethod)
  pack $m.bus.map -side left -padx 2
  ## phasetype
  frame $m.bus.sp1 -width 4 -bg $bgcol
  pack $m.bus.sp1 -side left
  tixSelect $m.bus.pht -allowzero false -radio true -orientation horizontal
  $m.bus.pht subwidget label config -bg $bgcol ;# def: vert 1pix line at left
  $m.bus.pht add eccen -text ecc -bg $bgcol -padx 0 -pady 0 ;# -font $sfont
  $m.bus.pht add polar -text pol -bg $bgcol -padx 0 -pady 0 ;# -font $sfont
  $m.bus.pht add 2cond -text 2cn -bg $bgcol -padx 0 -pady 0 ;# -font $sfont
  $m.bus.pht add real -text w -bg $bgcol -padx 0 -pady 0 ;# -font $sfont
  $m.bus.pht config -variable sphavglists(00,phasetype)
  pack $m.bus.pht -side left -padx 2
  ## t-test comparison value
  frame $m.bus.cf -bg $bgcol
  label $m.bus.cf.la -text "tcp:" -font $ffont -bg $bgcol
  entry $m.bus.cf.en -textvariable sphavglists(00,ttestcompval) -width 3 \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
      -selectforeground black  -font $hfont
  pack $m.bus.cf -side left -padx 2 
  pack $m.bus.cf.la $m.bus.cf.en -side left
  ## hard F thresh
  frame $m.bus.f -bg $bgcol
  label $m.bus.f.la -text "F:" -font $ffont -bg $bgcol
  entry $m.bus.f.en -textvariable sphavglists(00,preclustfthr) -width 3 \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
      -selectforeground black  -font $hfont
  pack $m.bus.f -side left -padx 2
  pack $m.bus.f.la $m.bus.f.en -side left
  ## cluster area
  frame $m.bus.cl -bg $bgcol
  label $m.bus.cl.la -text "mm^2:" -font $ffont -bg $bgcol
  entry $m.bus.cl.en -textvariable sphavglists(00,clustarea) -width 3 \
      -bg $entbgcol -selectbackground $selbgcol -highlightbackground $bgcol \
      -selectforeground black -font $hfont
  pack $m.bus.cl -side left -padx 2
  pack $m.bus.cl.la $m.bus.cl.en -side left
  ## surface to use for surfclust area calculations
  tixComboBox $m.bus.cbx2 -label "surf:" -dropdown true -listwidth 173 \
    -editable true -variable sphavglists(00,clustsurf) \
    -options "label.width 3 label.font $ffont" ;# listbox.width 12 -> 20
  $m.bus.cbx2 subwidget entry config -width 8      ;# tix options bug
  $m.bus.cbx2 subwidget listbox config -height 23  ;# tix options bug
  $m.bus.cbx2 subwidget label config -font $ffont  ;# tix options bug
  set subjsurflist [$surfacescombo subwidget listbox get 0 end]
  foreach subjsurf [lsort $subjsurflist] { $m.bus.cbx2 insert end $subjsurf}
  pack $m.bus.cbx2 -side left -padx 2

  ### entry titles (TODO: fix Find/Copy Raw tabbing like this)
  frame $m.tis -bg $bgcol
  pack $m.tis -side top
  frame $m.tis.f1 -bg $bgcol -width 52  ;# manual tabs
  label $m.tis.l1 -text "Session" -bg $bgcol -font $tfont
  frame $m.tis.f2 -bg $bgcol -width 60  ;# w/o (opt) in StatBrikStem = 66
  label $m.tis.l2 -text "Subject" -bg $bgcol -font $tfont
  frame $m.tis.f3 -bg $bgcol -width 85 
  label $m.tis.l3 -text "Scandir" -bg $bgcol -font $tfont
  frame $m.tis.f4 -bg $bgcol -width 132
  label $m.tis.l4 -text "VtxListPref" -bg $bgcol -font $tfont
  frame $m.tis.f5 -bg $bgcol -width 87 
  label $m.tis.l5 -text "MorphSurf" -bg $bgcol -font $tfont
  frame $m.tis.f6 -bg $bgcol -width 25   ;# w/o (opt) in StatBrikStem = 35
  label $m.tis.l6 -text "StatBrikStem (opt)" -bg $bgcol -font $tfont
  frame $m.tis.f7 -bg $bgcol -width 10   ;# w/o (opt) in StatBrikStem = 39
  pack $m.tis.f1 $m.tis.l1 $m.tis.f2 $m.tis.l2 $m.tis.f3 $m.tis.l3 \
       $m.tis.f4 $m.tis.l4 $m.tis.f5 $m.tis.l5 $m.tis.f6 $m.tis.l6 \
       $m.tis.f7 -side left -padx 0 -anchor w
  ## empty frame for configurable scan-to-avg widget lines
  frame $m.ens -bg $bgcol ;# -bd 10
  pack $m.ens -side top
  ## space
  frame $m.bot -height 12 -bg $bgcol
  pack $m.bot -side left

  ### bottom response buttons frame
  button $r.cancel -text "Cancel" -font $hfont -width 10 -pady 5 \
    -highlightbackground $bgcol -command "killsphavgcx $f"
  button $r.save -text "Save" -font $hfont -width 10 -pady 5 \
    -highlightbackground $bgcol -command { savesphavgcxparms }
  button $r.close -text "Save/Close" -font $hfont -width 10 -pady 5 \
    -highlightbackground $bgcol \
    -command "savesphavgcxparms; after 250 \"killsphavgcx $f\""
  pack $r.cancel $r.save $r.close -side right -padx 45

  ### unset existing stray tmp widget line vars (exist if panel prev opened)
  foreach spgarray { spgnums spgsessions spgsubjects spgscandirs \
                     spgvtxlistprefs spgmorphsurfs spgstatbrikprefs } {
    if [info exists $spgarray] { unset $spgarray }
  }

  ### reinstate panel content from parms if sphavgdir exists, else ignore
  if [info exists sphavglists(00,sphavgdir)] {
    set sphavgdir $sphavglists(00,sphavgdir)
    set newsphavgdir $sphavgdir
  }
  if { [file exists $env(FUNCTIONALS_DIR)/$session/$sphavgdir] || \
       $sphavgdir == "image/__no_dir__"} { ;# partial setup w/__no_dir__ opens
    if [info exists sphavglists(00,hemi)] {
      set hemi $sphavglists(00,hemi)
    }
    foreach ent [lsort [array names sphavglists]] {
      if ![string match ??,session $ent] { continue }
      set num [string range $ent 0 1]
      $addnewsessbu invoke
      # postpone too many missing sess errors till click on finished panel
      $subjectscombo config -disablecallback true
      $sessionscombo config -disablecallback true
      $scandirscombo config -disablecallback true
      set spgsessions($num)      $sphavglists($num,session)
      set spgsubjects($num)      $sphavglists($num,subject)
      set spgscandirs($num)      $sphavglists($num,scandir)  ;# N.B.: iscandir
      $subjectscombo config -disablecallback false
      $sessionscombo config -disablecallback false
      $scandirscombo config -disablecallback false
      set spgvtxlistprefs($num)  $sphavglists($num,vtxlistpref)
      set spgmorphsurfs($num)    $sphavglists($num,morphsurf)
      if ![info exists sphavglists($num,statbrikpref)] { ;#update old csurf.dat
        set sphavglists($num,statbrikpref) ""
      }
      set spgstatbrikprefs($num) $sphavglists($num,statbrikpref)
    }
  } else {  ;# undo parms->live above
    set sphavgdir image/__no_dir__
    set newsphavgdir $sphavgdir
  }
  $m.bus.cbx config -disablecallback true
  set dispname $name   ;# after traces (re)sync subject
  $m.bus.cbx config -disablecallback false

  $subjectscombo config -state disabled
  $sessionscombo config -state disabled
  $scandirscombo config -state disabled
  tkwait visibility $f

  wm protocol . WM_DELETE_WINDOW killboxOK   ;# disarm csurf win killbox
  if { [exec uname] != "Linux" } { raise $f }
  wm resizable $f 0 1        ;# only y
  set geom [wm geometry $f]  ;# 792x581+53+79
  set minx [string range $geom 0 [expr [string first x $geom] - 1]]
  set miny [string range $geom [expr [string first x $geom] + 1] \
                               [expr [string first + $geom] - 1]]
  wm minsize $f $minx $miny  ;# because tixScrolledWindow won't shrink
  focus $f

  # logs/help avail from this toplevel
  bind $f <$xcmd-l> { \
    if {$logflag} {set logflag 0; hidelogs} else {set logflag 1; showlogs} }
  bind $f <ButtonRelease-3> { helpwin setupsphavg 50 $helpwinlines }
}

### kill Cross Sess Sphere Avg window if purple buttons finished
proc killsphavgcx { w } {
  global sphereavgbu samp2subjbu volavgbu selbgcol
  global subjectscombo sessionscombo scandirscombo

  set sphereavgrunning 0
  set samp2subjrunning 0
  set volavgrunning 0

  ### strings here assume 2 spaces appended to buttonlabel arg to runacmd
  # 2 label chars trimmed: runacmd truncs 4 for "Quit" minus 2 spaces added2arg
  if { [info exists sphereavgbu] && [info commands $sphereavgbu] != "" } {
    if { [$sphereavgbu cget -text] == "QuitSPHEREA"} { set sphereavgrunning 1 }
  }
  if { [info exists samp2subjbu] && [info commands $samp2subjbu] != "" } {
    if { [$samp2subjbu cget -text] == "QuitSAMP2SU"} { set samp2subjrunning 1 }
  }
  if { [info exists volavgbu] && [info commands $volavgbu] != "" } {
    if { [$volavgbu cget -text] == "QuitVOLA"} { set volavgrunning 1 }
  }

  if {$sphereavgrunning} {
    confirmalert "Quit sphere average first"
  } elseif {$samp2subjrunning} {
    confirmalert "Quit sample to subject first"
  } elseif {$volavgrunning} {
    confirmalert "Quit volume average first"
  } else {
    destroy $w
    foreach cbx "$subjectscombo $sessionscombo $scandirscombo" {
      $cbx config -state normal
      $cbx subwidget entry config -selectbackground $selbgcol   ;# tix8.4+
      $cbx subwidget listbox config -selectbackground $selbgcol ;# tix8.4+
    }
    wm protocol . WM_DELETE_WINDOW testclose  ;# re-arm csurf window killbox
    if [info exists sphereavgbu]  { unset sphereavgbu }
    if [info exists samp2subjbu]  { unset samp2subjbu }
    if [info exists volavgbu]     { unset volavgbu }
  }
}

### make Run Batch Process popup
proc runbatchstat { { menuscandirtype functdir } } {
  global batchdone interruptbatch force
  global pfont mfont hfont ffontbb bgcol entbgcol selbgcol selcol

  if [winfo exists .batchdialog] {
    raise .batchdialog
    confirmalert "Finish current batch first"
    return
  }
  if [winfo exists .setuppopup] {
    raise .setuppopup
    confirmalert "Close current panel first"
    return
  }
  set f [toplevel .batchdialog -borderwidth 10]
  bind $f <ButtonRelease-3> { helpwin batch 50 $helpwinlines }
  #positionpopup $f
  wm geometry $f +[expr [winfo rootx .]-10]+[expr [winfo rooty .]+50]
  wm protocol $f WM_DELETE_WINDOW killboxOK
  set btitle "BATCH PROCESS"
  label $f.la -text $btitle -font $ffontbb -bd 2 -relief groove -padx 7 -pady 7
  if {$menuscandirtype == "sphavgdir"} {
    set msgtext "Select Actions to Perform on Configured SphereAvg Directories"
  } elseif {$menuscandirtype == "functdir"} {
    set msgtext "Select Actions to Perform on All Configured Scan Directories"
  } else {
    set msgtext "(unknown menuscandirtype)"
  }
  message $f.msg \
    -text $msgtext -justify center -font $pfont -width 260 -padx 30 -pady 20
  set msgtext "Interrupts -> after current button finishes"
  message $f.msg2 -text $msgtext -font $mfont -width 260 -padx 30 -pady 10

  # surfstat(surfavg,calcfield) only mult-action now, plus paint from 3 panels
  tixCheckList $f.cklist -scrollbar auto -height 126 -bg $bgcol \
     -options "hlist.selectBackground $selbgcol" -highlightbackground $bgcol
  set hlist [$f.cklist subwidget hlist]
  $hlist config -bd 2 -relief sunken -highlightbackground $bgcol
  # next 3: newpkgtix
  $hlist config -pady 0 -padx 25  ;# padx/pady defaults changed
  $f.cklist config -height 170    ;# height units changed
  $hlist config -font $hfont      ;# let old tix use orig compact arial-like
  # panel entries
  if {$menuscandirtype == "sphavgdir"} {
    $hlist add sphavg -itemtype imagetext \
                               -text "Run CrossSess SphereAvg, Samp2Subj"
    $hlist add rendersphavg -itemtype imagetext \
                               -text "Run SphereRender Panel (curr surf)"
    foreach ck { sphavg rendersphavg } {
      $f.cklist setstatus $ck off
    }
  } elseif {$menuscandirtype == "functdir"} {
    # actions all same names as aspects except multi-aspect surfstat
    $hlist add rawavg -itemtype imagetext -text "Run All Combine 3D Raw Images"
    $hlist add calcfour -itemtype imagetext \
                                       -text "Run All Calculate 3D Fourier"
    $hlist add calcrand -itemtype imagetext \
                                       -text "Run All Calculate 3D Rand Block"
    $hlist add sigavg  -itemtype imagetext -text "Run All Combine 3D Stats"
    $hlist add extstat -itemtype imagetext -text "Run All Import/Extract Stats"
    $hlist add paint   -itemtype imagetext -text "Run All Paint Surfaces"
    $hlist add surfstat -itemtype imagetext \
                                       -text "Run All Calculate Surface Stats"
    $hlist add render  -itemtype imagetext \
                               -text "Run All Rendering Panels (current surf)"
    foreach ck \
        { rawavg calcfour calcrand sigavg extstat paint surfstat render } {
      $f.cklist setstatus $ck off
    }
  } else {
    ;# bad $menuscandirtype
  }

  set saved $force
  set force 1
  set b [frame $f.buttons -borderwidth 10]
  button $b.go -text "Start" -font $pfont -highlightbackground $bgcol \
   -command "set interruptbatch 0; runbatchstatcmd $f.cklist $menuscandirtype;\
             set force $saved"
  button $b.int -text "Interrupt" -font $pfont -highlightbackground $bgcol \
    -command "set interruptbatch 1; set force $saved"
  button $b.can -text "Cancel" -font $pfont -highlightbackground $bgcol \
    -command "set interruptbatch 1; destroy $f; set force $saved; \
     wm protocol . WM_DELETE_WINDOW testclose"

  pack $f.la -side top -anchor w
  pack $f.msg -side top
  pack $f.cklist -side top -fill both -expand yes
  checks $f "" "Don't Ask to Overwrite" force col
  pack $f.msg2 -side top
  pack $f.buttons -side top
  pack $b.go $b.int $b.can -side right -padx 5 -anchor e

  foreach win "$f $f.msg $f.msg2 $b" { $win config -background $bgcol }
  foreach win "$f.la $b.go $b.int $b.can" { $win config -background $entbgcol }
  "$f.aDon't Ask to Overwrite.ck" config \
     -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
  tkwait visibility $f

  wm protocol . WM_DELETE_WINDOW killboxOK
  if { [exec uname] != "Linux" } { raise $f }
  focus $f
  tkwait variable batchdone
  if [winfo exists $f] {destroy $f}
  wm protocol . WM_DELETE_WINDOW testclose
  set force $saved
}

### queue lists for Batch Stats actions (all but one actions unpacked)
proc runbatchstatcmd { cklist menuscandirtype } {
  global batchdone interruptbatch hemi savergbflag

  set hlist [$cklist subwidget hlist]
  if {$menuscandirtype == "sphavgdir"} {
    foreach ck { sphavg rendersphavg } {
      $hlist entryconfig $ck -state disabled
    }
  } elseif {$menuscandirtype == "functdir"} {
    foreach ck \
        { rawavg calcfour calcrand sigavg extstat paint surfstat render } {
      $hlist entryconfig $ck -state disabled
    }
  } else {
    return  ;# bad $menuscandirtype
  }
  set hemisaved $hemi
  set dolist [$cklist getselection on]
  if { [lsearch -exact $dolist render] != -1 || \
       [lsearch -exact $dolist rendersphavg] != 1 || \
       [lsearch -exact $dolist sphavg] != 1 } {
    selecthemi "Render: Process both hemispheres?"
    set hemisaved $hemi   ;# most cmds reset hemi manually
  }
  foreach action $dolist {
    if ![winfo exists $cklist] { return }
    $cklist setstatus $action default  ;# feedback
    $hlist anchor clear
    $hlist selection clear
    $hlist selection set $action
    update idletasks
    if {$interruptbatch} { continue }
    if {$action == "rawavg"} {
      foreach aspect { rawavg } {
        if {$interruptbatch} { continue }
        runpanel $aspect
      }
    }
    if {$action == "calcrand"} {
      foreach aspect { calcrand } {
        if {$interruptbatch} { continue }
        runpanel $aspect
      }
    }
    if {$action == "calcfour"} {
      foreach aspect { calcfour } {
        if {$interruptbatch} { continue }
        runpanel $aspect
      }
    }
    if {$action == "sigavg"} {
      foreach aspect { sigavg } {
        if {$interruptbatch} { continue }
        runpanel $aspect
      }
    }
    if {$action == "extstat"} {
      foreach aspect { extstat } {
        if {$interruptbatch} { continue }
        runpanel $aspect
      }
    }
    if {$action == "paint"} {
      foreach aspect { calcfour sigavg extstat } {
        if {$interruptbatch} { continue }
        set justpaintflag 1
        runpanel $aspect $justpaintflag  ;# since paint on multiple panels
      }
    }
    if {$action == "surfstat"} {
      foreach aspect { surfavg calcfield } {
        if {$interruptbatch} { continue }
        runpanel $aspect
      }
    }
    if {$action == "render"} {
      foreach aspect { render } {
        if {$interruptbatch} { continue }
        set hemi $hemisaved
        set savergbflagsaved $savergbflag
        set savergbflag 1   ;# save, not just render
        runpanel $aspect
        set savergbflag $savergbflagsaved
      }
    }
    if {$action == "sphavg"} {
      foreach aspect { sphavg } {
        if {$interruptbatch} { continue }
        set hemi $hemisaved
        runsphavgpanel $aspect  ;# special case
      }
    }
    if {$action == "rendersphavg"} {
      foreach aspect { rendersphavg } {
        if {$interruptbatch} { continue }
        set hemi $hemisaved
        set savergbflagsaved $savergbflag
        set savergbflag 1   ;# save, not just render
        runpanel $aspect
        set savergbflag $savergbflagsaved
      }
    }
  }
  if {!$interruptbatch} {
    confirmalert "Batch processing sequence finished"
  } else {
    confirmalert "Batch processing sequence interrupted"
  }
  set batchdone 1
}

### open one kind of setupscans/SessionTools panel press buttons for BatchStats
proc runpanel { aspect {justpaintflag 0} } {   ;# TODO: medrender
  global interruptbatch exitrenderflag env session hemi datfile
  global rawaveragebu calcfourbu calcrandbu sigaveragebu
  global surfaveragebu calcfieldbu bordersbu convertfunctbu paintbu
  global surfrenderbu
  global subjectscombo sessionscombo scandirscombo selbgcol
  global sessionscanlists functscanlists renderscanlists

  readarrayparms $datfile alignfunct  ;# gets all aspects

  set pagelist ""
  foreach index [array names sessionscanlists] {
    set ipage [string range $index 0 [expr [string last , $index] - 1]]
    if {$ipage != "def"} {
      if {$sessionscanlists($index) == "functscan" || \
          $sessionscanlists($index) == "fsscan" || \
          $sessionscanlists($index) == "extstatscan" || \
          $sessionscanlists($index) == "sphavgscan" } {
        if [file exists $env(FUNCTIONALS_DIR)/$session/$ipage] { ;# cfg'd+exist
          lappend pagelist $ipage
        }
      }
    }
  }
  set panel .setuppopup
  set nbwin $panel.to.no
  set hemisaved $hemi
  foreach page [lsort $pagelist] {
    if { [info exists interruptbatch] && $interruptbatch } {
      if [winfo exists $panel] { destroy $panel }
      foreach cbx "$subjectscombo $sessionscombo $scandirscombo" {
        $cbx config -state normal
        $cbx subwidget entry config -selectbackground $selbgcol   ;# tix8.4+
        $cbx subwidget listbox config -selectbackground $selbgcol ;# tix8.4+
      }
      return
    }
    set mpage [manglepath $page]
    # funct panel 3dvolreg un-batch-able without flag since 2 buttons possible
    if {$aspect == "rawavg" && \
        [info exists functscanlists($page,rawavgflag)] && \
        $functscanlists($page,rawavgflag)} {
      if ![winfo exists $panel] { setupscans $aspect }
      $nbwin raise $mpage
      $rawaveragebu invoke
    }
    if {$aspect == "calcfour" && \
        [info exists functscanlists($page,fourflag)] && \
        $functscanlists($page,fourflag)} {
      set timeseriesdataflag 1
      if { [info exists functscanlists($page,sigavgflag)] && \
           $functscanlists($page,sigavgflag)} { set timeseriesdataflag 0 }
      if { [info exists functscanlists($page,surfavgflag)] && \
           $functscanlists($page,surfavgflag)} { set timeseriesdataflag 0 }
      if {$timeseriesdataflag} {
        if ![winfo exists $panel] { setupscans $aspect }
        $nbwin raise $mpage
        if {$justpaintflag} { $paintbu invoke } else { $calcfourbu invoke }
      }
    }
    if {$aspect == "calcrand" && \
        [info exists functscanlists($page,randflag)] && \
        $functscanlists($page,randflag)} {
      if ![winfo exists $panel] { setupscans $aspect }
      $nbwin raise $mpage
      $calcrandbu invoke
    }
    if {$aspect == "sigavg" && \
        [info exists functscanlists($page,sigavgflag)] && \
        $functscanlists($page,sigavgflag)} {
      if ![winfo exists $panel] { setupscans $aspect }
      $nbwin raise $mpage
      # added update to end of addsigavgscan to force panel completion
      if {$justpaintflag} { $paintbu invoke } else { $sigaveragebu invoke }
    }
    if {$aspect == "surfavg" && \
        [info exists functscanlists($page,surfavgflag)] && \
        $functscanlists($page,surfavgflag)} {
      if ![winfo exists $panel] { setupscans $aspect }
      $nbwin raise $mpage
      $surfaveragebu invoke
    }
    if {$aspect == "calcfield" && \
        [info exists sessionscanlists($page,type)] && \
        $sessionscanlists($page,type) == "fsscan"} {
      if ![winfo exists $panel] { setupscans $aspect }
      $nbwin raise $mpage
      $calcfieldbu invoke
      $bordersbu invoke
    }
    if {$aspect == "extstat" && \
        [info exists sessionscanlists($page,type)] && \
        $sessionscanlists($page,type) == "extstatscan"} {
      if ![winfo exists $panel] { setupscans $aspect }
      $nbwin raise $mpage
      if {$justpaintflag} { $paintbu invoke } else { $convertfunctbu invoke }
    }
    if {$aspect == "render" && \
        [info exists functscanlists($page,renderflag)] && \
        $functscanlists($page,renderflag)} {
      set hemi $hemisaved   ;# orig runbatchstat request
      set exitsaved $exitrenderflag
      set exitrenderflag 1
      if ![winfo exists $panel] { setupscans $aspect }
      $nbwin raise $mpage
      if {$hemi == "both"} {  ;# auto exit can't repeatifboth
        set hemi rh; $surfrenderbu invoke
        set hemi lh; $surfrenderbu invoke
      } else {
        $surfrenderbu invoke
      }
      set exitrenderflag $exitsaved
      # TODO: medrender
    }
    if {$aspect == "rendersphavg" && \
        [info exists functscanlists($page,renderflag)] && \
        $functscanlists($page,renderflag)} {
      set hemi $hemisaved   ;# orig runbatchstat request
      set exitsaved $exitrenderflag
      set exitrenderflag 1
      if ![winfo exists $panel] { setupscans $aspect }
      $nbwin raise $mpage
      if {$hemi == "both"} {  ;# auto exit can't repeatifboth
        set hemi rh; $surfrenderbu invoke
        set hemi lh; $surfrenderbu invoke
      } else {
        $surfrenderbu invoke
      }
      set exitrenderflag $exitsaved
      # TODO: medrender
    }

  }
  if [winfo exists $panel] { destroy $panel }
  foreach cbx "$subjectscombo $sessionscombo $scandirscombo" {
    $cbx config -state normal
    $cbx subwidget entry config -selectbackground $selbgcol   ;# tix8.4+
    $cbx subwidget listbox config -selectbackground $selbgcol ;# tix8.4+
  }
}

### open sphavg panel and press its 2 surface buttons for BatchStats
proc runsphavgpanel { aspect } {
  global interruptbatch datfile sphavglists sessionscanlists
  global sphereavgbu samp2subjbu
  global subjectscombo sessionscombo scandirscombo selbgcol

  readarrayparms $datfile alignfunct  ;# gets all aspects (incl sphavg)
  set panel .sphavgdialog
  if {$aspect == "sphavg" && \
      [info exists sphavglists(00,sphavgdir)] && \
      [info exists sessionscanlists($sphavglists(00,sphavgdir),type)] && \
      $sessionscanlists($sphavglists(00,sphavgdir),type) == "sphavgscan" } {
    if ![winfo exists $panel] { setupsphavgcx }
    $sphereavgbu invoke  ;# button 1
    if { [info exists interruptbatch] && $interruptbatch } {
      if [winfo exists $panel] { destroy $panel }
      foreach cbx "$subjectscombo $sessionscombo $scandirscombo" {
        $cbx config -state normal
        $cbx subwidget entry config -selectbackground $selbgcol   ;# tix8.4+
        $cbx subwidget listbox config -selectbackground $selbgcol ;# tix8.4+
      }
      return
    }
    $samp2subjbu invoke  ;# button 2
  }
  if [winfo exists $panel] { destroy $panel }
  foreach cbx "$subjectscombo $sessionscombo $scandirscombo" {
    $cbx config -state normal
    $cbx subwidget entry config -selectbackground $selbgcol   ;# tix8.4+
    $cbx subwidget listbox config -selectbackground $selbgcol ;# tix8.4+
  }
}

### Main csurf window: check selection in subject combobox
proc cbx:select_subject { s } {
  global env name makingnewsubject matchsubject
  if {$name == "__nobody__" || $name == ""} { return }
  if {!$makingnewsubject} {
    set islink 0
    catch {
      if { [file type $env(SUBJECTS_DIR)/$name] == "link" } { set islink 1 }
    }
    if { $islink && ![file exists $env(SUBJECTS_DIR)/$name] } {
      confirmalert "Subject: $name is a stale link"
      set name ""
      return
    } 
    if ![file exists $env(SUBJECTS_DIR)/$name] {
      set list [glob -nocomplain $env(SUBJECTS_DIR)/*${name}*]
      if {$list == ""} {
        confirmalert \
          "Subject: no match to $name\nfound in $env(SUBJECTS_DIR)"
        set name ""
        return
      } else {
        set taillist ""
        foreach dir $list { set taillist "$taillist [file tail $dir]" }
        set taillist [lsort $taillist]
        if { [llength $taillist] == 1 } { after 750 {set userok 1} }
        set name \
          [selectfromlist "Partial matches:" "Select One Subject" $taillist]
      } 
    }
    if ![file isdirectory $env(SUBJECTS_DIR)/$name] {
      set name ""
      return
    }
    if {$matchsubject} { fixsessions 0 0 0 }
    cdsubjectscripts
  }
}

### Main csurf window: check selection in session combobox
proc cbx:select_session { s } {
  global env session makingnewsession matchsubject fnewtopflag

  if {$session == "__nosession__" || $session == ""} { return }
  if {!$makingnewsession} {
    set islink 0
    catch {  ;# if not even a bad link
      if {[file type $env(FUNCTIONALS_DIR)/$session] == "link"} {set islink 1}
    }
    if { $islink && ![file exists $env(FUNCTIONALS_DIR)/$session] } {
      confirmalert "Session: $session is a stale link"
      set session ""
      return
    } 
    if ![file exists $env(FUNCTIONALS_DIR)/$session] {
      if {$matchsubject} { set session ""; return }
      set list [glob -nocomplain $env(FUNCTIONALS_DIR)/*${session}*]
      if {$list == ""} {
        confirmalert \
          "Session: no match to $session\nfound in $env(FUNCTIONALS_DIR)"
        set session ""
        return
      } else {
        set taillist ""
        foreach dir $list { set taillist "$taillist [file tail $dir]" }
        if {$fnewtopflag} {set order -decreasing} else {set order -increasing}
        set taillist [lsort $order $taillist]
        if { [llength $taillist] == 1 } { after 750 {set userok 1} }
        set session \
          [selectfromlist "Partial matches:" "Select One Session" $taillist]
      }
      if ![file isdirectory $env(FUNCTIONALS_DIR)/$session] {
        set session ""
        return
      }
    }
    cdfunctscripts
  }
  cbx:select_surface { }
  focus .  ;#init: .main.right.border.frame.both.top.cbx.shell.slistbox.listbox
}

### Main csurf window: update viewtype radio after select in surface combobox
proc cbx:select_surface { s } {
  global surfext viewtype oldinflatedext orig1ext orig2ext
  global origext foldedext whiteext graymidext pialext
  global inflatedext inflatedext2 sphereext regext

  if {$surfext == $origext}        { set viewtype "folded" }
  if {$surfext == $orig1ext}       { set viewtype "folded" }
  if {$surfext == $orig2ext}       { set viewtype "folded" }
  if {$surfext == $foldedext}      { set viewtype "folded" }
  if {$surfext == $whiteext}       { set viewtype "folded" }
  if {$surfext == $graymidext}     { set viewtype "folded" }
  if {$surfext == $pialext}        { set viewtype "folded" }
  if {$surfext == $inflatedext}    { set viewtype "inflated" }
  if {$surfext == $inflatedext2}   { set viewtype "inflated" }
  if {$surfext == $oldinflatedext} { set viewtype "inflated" }
  if {$surfext == $sphereext}      { set viewtype "inflated" }
  if {$surfext == "$sphereext.$regext"} { set viewtype "inflated" }
  # recognize inflate steps (inflate/sphere movies)
  if [string match ${inflatedext}???? $surfext] { set viewtype "inflated" }
  if [string match ${sphereext}???? $surfext] { set viewtype "inflated" }
  # recognize orig hacks
  if [string match ${origext}* $surfext]  { set viewtype "folded" }
}

### Setup panels: duplicate of main surface combobox on Setup panels
proc cbx:select_surface2 { s } {
}

proc cbx:listcmd_patch { } {
  global patchescombo

  # before select: for tksurfer wrote new patch
  $patchescombo config -disablecallback true
  fixpatches 0 0 0
  $patchescombo config -disablecallback false
}

### Main csurf window: update viewtype radio after selection in patch combobox
proc cbx:select_patch { s } {
  global env name hemi surfdir patchext viewtype fsaverage
  global begin3dext endflatext patchinfix oldendflatext editingsurface
  global sing2fsavgflag oppfsavghemiflag sing2singflag anothersub1time

  # TODO: verbose w/type bad, no RET, click subject/session
  if {$patchext == "" || $hemi == "both" || $editingsurface} { return }
  if [string match *.$begin3dext $patchext]     { set viewtype "viewcuts" }
  if [string match *.$endflatext $patchext]     { set viewtype "flattened" }
  if [string match *.$oldendflatext $patchext]  { set viewtype "flattened" }
  if { [string match *$patchinfix* $patchext] && \
      ![string match *.$begin3dext $patchext] } { set viewtype "flattened" }
  # only check if final display surface exists
  if {$sing2singflag} {  ;# first else next (req'd intermed) prematurely fails
    set fullsurfdir $env(SUBJECTS_DIR)/$anothersub1time/$surfdir
    if ![file exists $fullsurfdir/$hemi.$patchext] {
      confirmalert "Patch:\n\n    $hemi.$patchext\
                \n\nnot found in:\n\n    $fullsurfdir"
      after 250 { set patchext "" }
    }
  } elseif {$sing2fsavgflag} {
    set fullsurfdir $env(SUBJECTS_DIR)/$fsaverage/$surfdir
    if ![file exists $fullsurfdir/$hemi.$patchext] {
      confirmalert "Patch:\n\n    $hemi.$patchext\
                \n\nnot found in:\n\n    $fullsurfdir"
      after 250 { set patchext "" }
    }
  } elseif {$oppfsavghemiflag} {
    ;# TODO
  } else {  ;# standard
    set fullsurfdir $env(SUBJECTS_DIR)/$name/$surfdir
    if ![file exists $fullsurfdir/$hemi.$patchext] {
      confirmalert "Patch:\n\n    $hemi.$patchext\
                \n\nnot found in:\n\n    $fullsurfdir"
      after 250 { set patchext "" }
    }
  }
}

### Setup panels: duplicate of main patch combobox
proc cbx:select_patch2 { s } {
}

### Main csurf window viewtype radio: reset surf/patch combos after select
proc radio2surfpatch { } {
  global viewtype surfext patchext foldedext begin3dext endflatext patchinfix
  global surfacescombo patchescombo
  $surfacescombo config -disablecallback true
  $patchescombo config -disablecallback true
  set patchlist [$patchescombo subwidget listbox get 0 end]
  if {$viewtype == "folded"}   { set surfext $foldedext }
  if {$viewtype == "inflated"} { set surfext [getinflatedext] }
  if {$viewtype == "viewcuts"} { 
    set surfext [getinflatedext]
    if ![string match *.$begin3dext $patchext] {
      set patchext ""
      set first3d [lsearch -glob $patchlist *.$begin3dext]
      if {$first3d != -1} {
        set patchext [lindex $patchlist $first3d]
      }
    }
  }
  if {$viewtype == "flattened"} { 
    set surfext [getinflatedext]
    if ![string match *.$endflatext $patchext] { 
      set patchext ""
      set firstflat [lsearch -glob $patchlist *.$endflatext]
      if {$firstflat != -1} {
        set patchext [lindex $patchlist $firstflat]
      }
      if {$patchext == ""} {  ;# backward compat--find any patch
        set firstanypatch [lsearch -glob $patchlist *$patchinfix*]
        if {$firstanypatch != -1} {
          set patchext [lindex $patchlist $firstanypatch]
        }
      }
    } 
  }
  $surfacescombo config -disablecallback false
  $patchescombo config -disablecallback false
}

### Main csurf window: check selection in scandir combobox
proc cbx:select_scandir { s } {
  global env session iscandir
  # TODO: verbose w/type bad, no RET, click session/subject
  if {$iscandir == "" || [string match *\\** $session]} { return }  ;# need 2
  if ![file exists $env(FUNCTIONALS_DIR)/$session/$iscandir] {
    confirmalert \
     "Scandir:\n\n    $iscandir\n\nnot found in $env(FUNCTIONALS_DIR)/$session"
    after 250 { set iscandir "" }
  }
}

### Main csurf window: strip suff if corresponding radio (for radio update)
proc cbx:select_mritype { s } {
  global mritype vollooklist

  set newmritype [file rootname $mritype]
  if { "$newmritype" == "$mritype" } { return }
  if { [lsearch -exact $vollooklist $newmritype] != -1 } {
    set mritype $newmritype  ;# VOLUME button: dir, then reattach suff
  }
}

### Struct Scan panel:
proc cbx:select_structimage { s } {
}

### Align Scan panel:
proc cbx:select_alignimage { s } {
  global alignscanparms
  if { [string match *.HEAD $s] } {
    set alignscanparms(modelimage) [file rootname $s].BRIK
  }
}

### Funct Scan panel:
proc cbx:select_vregtarg { s } {
}

### Funct Scan panel -- Image File: combo
proc cbx:select_functimage { page s } {
  global functscanlists
  if { [string match *.HEAD $s] } {
    set functscanlists($page,modelimage) [file rootname $s].BRIK
  }
}

### Combine 3D Raw Images panel: append to rawaverage listbox on dir select
proc cbx:select_rawtoavgdir { page s } {
  global env session sessionscanlists functscanlists
  global rawtoavghlist rawtoavgckwidget rawtoavgimagepatt
  if ![info exists sessionscanlists($s,type)] { return }
  if {$sessionscanlists($s,type) != "functscan" &&
      $sessionscanlists($s,type) != "extstatscan"} { return }
  if ![info exists functscanlists($s,imagepatt)] { return }
  if { [lsearch -exact $functscanlists($page,rawtoavgdirs) $s] == -1 } {
    lappend functscanlists($page,rawtoavgdirs) $s
    $rawtoavghlist($page) add $s -itemtype imagetext -text $s
    lappend functscanlists($page,rawtoavgrevs) off
    set status off
    $rawtoavgckwidget($page) setstatus $s $status
    # set missing dmax/dsetp/blockcenter to first in list
    set dir1 [lindex $functscanlists($page,rawtoavgdirs) 0]
    if ![info exists functscanlists($page,paintdmin)] {
      set functscanlists($page,paintdmin) $functscanlists($dir1,paintdmin)
    }
    if ![info exists functscanlists($page,paintdmax)] {
      set functscanlists($page,paintdmax) $functscanlists($dir1,paintdmax)
    }
    if ![info exists functscanlists($page,paintdstep)] {
      set functscanlists($page,paintdstep) $functscanlists($dir1,paintdstep)
    }
    if ![info exists functscanlists($page,paintnormop)] {
      set functscanlists($page,paintnormop) $functscanlists($dir1,paintnormop)
    }
    if ![info exists functscanlists($page,paintnormtype)] {
      set functscanlists($page,paintnormtype) \
         $functscanlists($dir1,paintnormtype)
    }
    if ![info exists functscanlists($page,blockcenteroffset)] {
      set functscanlists($page,blockcenteroffset) \
         $functscanlists($dir1,blockcenteroffset)
    }
  }
  set rawtoavgimagepatt $functscanlists($s,imagepatt)
}

### Combine 3D Phase Stats panel: append sigaverage listbox on dir select
proc cbx:select_sigtoavgdir { page s } {
  global env session sessionscanlists functscanlists
  global sigtoavghlist sigtoavgckwidget sigtoavgbfloatstem
  if ![info exists sessionscanlists($s,type)] { return }
  if {$sessionscanlists($s,type) != "functscan" &&
      $sessionscanlists($s,type) != "extstatscan"} { return }
  if ![info exists functscanlists($s,bfloatpatt)] { return }
  set bfloatstem [stripbpatt $functscanlists($s,bfloatpatt)]
  if {$bfloatstem == "-unset-"} { return }
  if { [lsearch -exact $functscanlists($page,sigtoavgdirs) $s] == -1 } {
    lappend functscanlists($page,sigtoavgdirs) $s
    $sigtoavghlist($page) add $s -itemtype imagetext -text $s
    lappend functscanlists($page,sigtoavgrevs) off
    set status off
    if {$functscanlists($page,sigoperation) == "phasecancel"} {set status none}
    $sigtoavgckwidget($page) setstatus $s $status
    # set missing dmax/dstep/blockcenter to first in list
    set dir1 [lindex $functscanlists($page,sigtoavgdirs) 0]
    if ![info exists functscanlists($page,paintdmin)] {
      set functscanlists($page,paintdmin) $functscanlists($dir1,paintdmin)
    }
    if ![info exists functscanlists($page,paintdmax)] {
      set functscanlists($page,paintdmax) $functscanlists($dir1,paintdmax)
    }
    if ![info exists functscanlists($page,paintdstep)] {
      set functscanlists($page,paintdstep) $functscanlists($dir1,paintdstep)
    }
    if ![info exists functscanlists($page,paintnormop)] {
      set functscanlists($page,paintnormop) $functscanlists($dir1,paintnormop)
    }
    if ![info exists functscanlists($page,paintnormtype)] {
      if [info exists functscanlists($dir1,paintnormtype)] { ;# bakcompat
        set functscanlists($page,paintnormtype) \
           $functscanlists($dir1,paintnormtype) ;# warn missing combine time
      }
    }
    if ![info exists functscanlists($page,blockcenteroffset)] {
      set functscanlists($page,blockcenteroffset) \
         $functscanlists($dir1,blockcenteroffset)
    }
  }
  set sigtoavgbfloatstem $bfloatstem
}

### Combine Surface Stats panel: append to surfaverage listbox on wfile select
proc cbx:select_surftoavgwfilepref { nbwin page s } {
  global functscanlists
  global sesstoavgdir surftoavgdir surftoavgbfloatstem surftoavgbigstem
  global surftoavgckwidget surftoavghlist surftoavgwfileprefcombo

  if {$surftoavgbfloatstem == ""} { return }
  if {$page != [demanglepath [$nbwin raised]]} { return }

  $surftoavgwfileprefcombo($page) config -disablecallback true
  set surfoperation $functscanlists($page,surfoperation)
  if {$surfoperation == "phaseavg-ecc" || $surfoperation == "phaseavg-pol" || \
      $surfoperation == "phaseavg-two"} {
    set surftoavgbfloatstem [getuniqcomplexstemlist $surftoavgbfloatstem]
  }
  set surftoavgbigstem $sesstoavgdir/$surftoavgdir/$surftoavgbfloatstem
  if { [lsearch -exact $functscanlists($page,surftoavgbigstems) \
        $surftoavgbigstem] == -1 } {
    lappend functscanlists($page,surftoavgbigstems) $surftoavgbigstem
    $surftoavghlist($page) add $surftoavgbigstem -itemtype imagetext \
      -text $surftoavgbigstem
    lappend functscanlists($page,surftoavgrevs) off
    $surftoavgckwidget($page) setstatus $surftoavgbigstem off
  }
  $surftoavgwfileprefcombo($page) config -disablecallback false
}

### Combine Surface Stats panel: update wfile combobox on select surfdir
proc cbx:select_surftoavgdir { nbwin page s } {
  global session functscanlists
  global sesstoavgdir surftoavgdir
  global sessionscombo subjectscombo scandirscombo
  global surftoavgcombo surftoavgwfileprefcombo

  if ![info exists surftoavgwfileprefcombo($page)] { return }
  if ![winfo exists $surftoavgwfileprefcombo($page)] { return }
  if {$page != [demanglepath [$nbwin raised]]} { return }

  $sessionscombo config -disablecallback true
  $subjectscombo config -disablecallback true
  $scandirscombo config -disablecallback true
  $surftoavgcombo($page) config -disablecallback true
  $surftoavgwfileprefcombo($page) config -disablecallback true
  set savsess $session
  set session $sesstoavgdir
  set preflist [getuniqwfilelist $surftoavgdir]  ;# all--no chkconfig
  $surftoavgwfileprefcombo($page) subwidget listbox delete 0 end
  foreach stem $preflist {
    $surftoavgwfileprefcombo($page) insert end [file tail $stem]
  }
  set firsttail [file tail [lindex $preflist 0]]
  $surftoavgwfileprefcombo($page) config -value $firsttail
  set session $savsess
  $surftoavgwfileprefcombo($page) config -disablecallback false
  $surftoavgcombo($page) config -disablecallback false
  $scandirscombo config -disablecallback false
  $subjectscombo config -disablecallback false
  $sessionscombo config -disablecallback false
}

### Combine Surface Stats panel: update surfdir combobox on select session
proc cbx:select_sesstoavgdir { nbwin page s } {
  global session sesstoavgdir
  global sessionscombo subjectscombo scandirscombo
  global sesstoavgcombo surftoavgcombo

  if ![info exists sesstoavgcombo($page)] { return }    ;# make page time
  if ![info exists surftoavgcombo($page)] { return }
  if ![winfo exists $sesstoavgcombo($page)] { return }  ;# make page time
  if ![winfo exists $surftoavgcombo($page)] { return }
  if {$page != [demanglepath [$nbwin raised]]} {return} ;# 1combovar=>trigs all

  $sessionscombo config -disablecallback true          ;# no set session callbk
  $subjectscombo config -disablecallback true          ;# no fixsubj trace
  $scandirscombo config -disablecallback true          ;# no fixscan trace
  $sesstoavgcombo($page) config -disablecallback true  ;# not here twice
  $surftoavgcombo($page) config -disablecallback true  ;# wait to append hlist

  # like select_session but search combolist not files
  set sesslist [$sessionscombo subwidget listbox get 0 end]
  if { [lsearch -exact $sesslist $sesstoavgdir] == -1 } {
    set list ""
    set patt *$sesstoavgdir*
    foreach sess $sesslist {
      if [string match $patt $sess] { lappend list $sess }
    }
    if {$list == ""} {
      confirmalert "Session: no match to: $sesstoavgdir"
      set sesstoavgdir ""
      $surftoavgcombo($page) config -disablecallback false
      $sesstoavgcombo($page) config -disablecallback false
      $scandirscombo config -disablecallback false
      $subjectscombo config -disablecallback false
      $sessionscombo config -disablecallback false
      return
    } else {
      set list [lsort -decreasing $list]
      set sesstoavgdir \
        [selectfromlist "Partial matches:" "Select One Session" $list]
    }
  }
  set savsess $session
  set session $sesstoavgdir  ;# disable stops select_session
  set scandirslist [getfunctiscandirslist]
  $surftoavgcombo($page) subwidget listbox delete 0 end
  foreach dir $scandirslist { $surftoavgcombo($page) insert end $dir }
  $surftoavgcombo($page) config -value [lindex $scandirslist 0]
  set session $savsess
  $surftoavgcombo($page) config -disablecallback false
  $sesstoavgcombo($page) config -disablecallback false
  $scandirscombo config -disablecallback false
  $subjectscombo config -disablecallback false
  $sessionscombo config -disablecallback false
}

### (all omits gathered here)
### Combine 3D Raw Images panel: delete rawaverage dir from listbox
proc omitrawtoavgdir { page } {
  global functscanlists rawtoavghlist rawtoavgdir
  if {[lsearch -exact $functscanlists($page,rawtoavgdirs) $rawtoavgdir] > -1} {
    set index [lsearch -exact $functscanlists($page,rawtoavgdirs) $rawtoavgdir]
    set functscanlists($page,rawtoavgdirs) \
      [lreplace $functscanlists($page,rawtoavgdirs) $index $index]  ;# delete
    set functscanlists($page,rawtoavgrevs) \
      [lreplace $functscanlists($page,rawtoavgrevs) $index $index]
    $rawtoavghlist($page) delete entry $rawtoavgdir
  }
}

### Combine 3D Phas/Cond Stats panel: delete sigaverage dir from listbox,lists
proc omitsigtoavgdir { page } {
  global functscanlists sigtoavghlist sigtoavgdir
  if {[lsearch -exact $functscanlists($page,sigtoavgdirs) $sigtoavgdir] > -1} {
    set index [lsearch -exact $functscanlists($page,sigtoavgdirs) $sigtoavgdir]
    set functscanlists($page,sigtoavgdirs) \
      [lreplace $functscanlists($page,sigtoavgdirs) $index $index]  ;# delete
    set functscanlists($page,sigtoavgrevs) \
      [lreplace $functscanlists($page,sigtoavgrevs) $index $index]
    $sigtoavghlist($page) delete entry $sigtoavgdir
  }
}

### Combine Surface Stats panel: delete surfaverage dir from listbox,lists
proc omitsurftoavgdir { page } {
  global functscanlists surftoavghlist surftoavgbigstem
  if { [lsearch -exact $functscanlists($page,surftoavgbigstems) \
        $surftoavgbigstem] > -1 } {
    set index [lsearch -exact \
               $functscanlists($page,surftoavgbigstems) $surftoavgbigstem]
    set functscanlists($page,surftoavgbigstems) \
      [lreplace $functscanlists($page,surftoavgbigstems) $index $index] ;# del
    set functscanlists($page,surftoavgrevs) \
      [lreplace $functscanlists($page,surftoavgrevs) $index $index]
    $surftoavghlist($page) delete entry $surftoavgbigstem
  }
}

### Calculate Rand Block Stats panel: delete conds to diff/add from listbox
proc omitcondnames2difforadd { page } {
  global functscanlists condnames2difforadd condnames2difforaddhlist
  if {[lsearch -exact $functscanlists($page,condnames2difflist) \
        $condnames2difforadd] > -1} {
    set functscanlists($page,condnames2difflist) \
      [ldelete $functscanlists($page,condnames2difflist) $condnames2difforadd]
    $condnames2difforaddhlist($page) delete entry $condnames2difforadd
  }
  if {[lsearch -exact $functscanlists($page,condnames2addlist) \
        $condnames2difforadd] > -1} {
    set functscanlists($page,condnames2addlist) \
      [ldelete $functscanlists($page,condnames2addlist) $condnames2difforadd]
    $condnames2difforaddhlist($page) delete entry $condnames2difforadd
  }
}

### Calculate Random Block Statistic panel: select paradigm dropdown command
proc cbx:select_paradigm { page s } {
  global paradigmscombo parasuff
  readparadigmfiles $page
  # TODO: allow user set pattern/suffix?
  $paradigmscombo($page) config -disablecallback true
  $paradigmscombo($page) config -value *.$parasuff   ;# allow user-set pattern
  $paradigmscombo($page) config -disablecallback false
}

### Calculate Visual Fieldsign panel: update wfile combobox on select eccendir
proc cbx:select_eccen { page s } {
  global eccenwfileprefscombo sessionscanlists renderscanlists functscanlists

  set eccenslist {}
  foreach index [array names functscanlists] {
    set ipage [string range $index 0 [expr [string last , $index] - 1]]
    if {$ipage != "def" && [string match *,phasetype $index] } {
      if {$functscanlists($index) == "eccen"} {
        if { [info exists sessionscanlists($ipage,type)] && \
             $sessionscanlists($ipage,type) == "functscan"} {
          lappend eccenslist $ipage
        }
      }
    }
  }
  if ![llength $eccenslist] {
    set renderscanlists($page,eccenstem) $renderscanlists(def,eccenstem)
    return
  }

  set preflist [getuniqwfilelist $s]
  set cpreflist [getuniqcomplexstemlist $preflist]
  set cpreftailslist {}
  ### sort infixes (non-complex non-infix-stripped) to end for 1st time
  #foreach pref $cpreflist { lappend cpreftailslist [file tail $pref] }
  set hasinfix {}
  set noinfix {}
  foreach pref $cpreflist {
    if [string match *_? $pref] {
      lappend hasinfix [file tail $pref]
    } else {
      lappend noinfix [file tail $pref]
    }
  }
  set cpreftailslist [concat $noinfix $hasinfix]

  if [info exists renderscanlists($page,eccenstem)] {
    set currpreftail $renderscanlists($page,eccenstem)
    if { [lsearch -exact $cpreftailslist $currpreftail] == -1 } {
      set currpreftail [lindex $cpreftailslist 0]
      set renderscanlists($page,eccenstem) $currpreftail
    }
  } else {
    set currpreftail [lindex $cpreftailslist 0]
  }
  $eccenwfileprefscombo($page) subwidget listbox delete 0 end
  foreach preftail $cpreftailslist {
    $eccenwfileprefscombo($page) insert end $preftail
  }
  $eccenwfileprefscombo($page) config -value $currpreftail
}

### Calculate Visual Fieldsign panel: update wfile combobox on select polardir
proc cbx:select_polar { page s } {
  global polarwfileprefscombo sessionscanlists renderscanlists functscanlists

  set polarslist {}
  foreach index [array names functscanlists] {
    set ipage [string range $index 0 [expr [string last , $index] - 1]]
    if {$ipage != "def" && [string match *,phasetype $index] } {
      if {$functscanlists($index) == "polar"} {
        if { [info exists sessionscanlists($ipage,type)] && \
             $sessionscanlists($ipage,type) == "functscan"} {
          lappend polarslist $ipage
        }
      }
    }
  }
  if ![llength $polarslist] {
    set renderscanlists($page,polarstem) $renderscanlists(def,polarstem)
    return
  }

  set preflist [getuniqwfilelist $s]
  set cpreflist [getuniqcomplexstemlist $preflist]
  set cpreftailslist {}
  ### sort infixes (non-complex non-infix-stripped) to end for 1st time
  #foreach pref $cpreflist { lappend cpreftailslist [file tail $pref] }
  set hasinfix {}
  set noinfix {}
  foreach pref $cpreflist {
    if [string match *_? $pref] {
      lappend hasinfix [file tail $pref]
    } else {
      lappend noinfix [file tail $pref]
    }
  }
  set cpreftailslist [concat $noinfix $hasinfix]

  if [info exists renderscanlists($page,polarstem)] {
    set currpreftail $renderscanlists($page,polarstem)
    if { [lsearch -exact $cpreftailslist $currpreftail] == -1 } {
      set currpreftail [lindex $cpreftailslist 0]
      set renderscanlists($page,polarstem) $currpreftail
    }
  } else {
    set currpreftail [lindex $cpreftailslist 0]
  }
  $polarwfileprefscombo($page) subwidget listbox delete 0 end
  foreach preftail $cpreftailslist {
    $polarwfileprefscombo($page) insert end $preftail
  }
  $polarwfileprefscombo($page) config -value $currpreftail
}

### Calculate Visual Fieldsign panel:
proc cbx:select_eccenwfilepref { s } {
}

### Calculate Visual Fieldsign panel:
proc cbx:select_polarwfilepref { s } {
}

### RandBlock panel: set cond1 wfile on cond1 name select (TODO:lookup existing)
proc cbx:select_condname1 { page s } {
  global functscanlists condname1
  set cn1 $condname1($page)
  if { ![info exists functscanlists($page,condnames)] || \
       ![llength $functscanlists($page,condnames)] || \
       $cn1 == ""} { return }
  if { [lsearch -exact $functscanlists($page,condnames) $cn1] == -1 } { 
    confirmalert "Select Condition Name: bad condition: $cn1"
    return
  }
}

### RandBlock panel: set cond2 wfile on cond2 name select (TODO:lookup existing)
proc cbx:select_condname2 { page s } {
  global functscanlists condname2
  set cn2 $condname2($page)
  if { ![info exists functscanlists($page,condnames)] || \
       ![llength $functscanlists($page,condnames)] || \
       $cn2 == "" } { return }
  if { [lsearch -exact $functscanlists($page,condnames) $cn2] == -1 } {
    confirmalert "Select Condition Name: bad condition: $cn2"
    return
  }
}

### Ext Stats: set bfloatpatt from extern statfile suffix (intern stats set sep)
proc cbx:select_statimage { nbwin s } {
  global env session iscandir functscanlists 
  set page [demanglepath [$nbwin raised]]
  set iscandir $page
  set ext [file extension $s]
  # bfloatpatt set separately for internal stats
  if {$ext == ".BRIK" || $ext == ".HEAD"} {
    set stem [file rootname $s]
    if {$ext == ".HEAD"} { set functscanlists($page,extstatfile) $stem.BRIK }
    set fullhead $env(FUNCTIONALS_DIR)/$session/$iscandir/$stem.HEAD
    if [brikheaderhaslabels $fullhead] {
      set functscanlists($page,bfloatpatt) -multiple-  ;# ${stem}_%03d.bfloat
      set functscanlists($page,statformat) brikmulti
    } else {
      if {$functscanlists($page,realstatformat) == "bfloat"} {
        set functscanlists($page,bfloatpatt) ${stem}_%03d.bfloat
      }
      if {$functscanlists($page,realstatformat) == "afnibrik"} {
        set functscanlists($page,bfloatpatt) ${stem}.BRIK  ;# stem has +orig
      }
      set functscanlists($page,statformat) briksingle
    }
  } elseif {$ext == ".mgz"} {
    set functscanlists($page,bfloatpatt) $s
    set functscanlists($page,statformat) mgzsingle
  } elseif {$ext == ".bfloat"} {
    set stem [stripbnum $s]
    set functscanlists($page,bfloatpatt) ${stem}_%03d.bfloat
    set functscanlists($page,statformat) bfloat
  } else {
    confirmalert "Select External Stats: extension  $ext not recognized"
    set functscanlists($page,bfloatpatt) -selectimageset-
  }
}

### Ext Stats: used by select_statimage
proc brikheaderhaslabels { header } {
  if ![file exists $header] { return 0 }
  set id [open $header r]
  set lines [split [read $id] "\n"]
  close $id

  set i 0
  foreach line $lines {
    if {[lindex $line 2] == "BRICK_LABS"} { set i 2; continue }
    if {$i == 2 && [lindex $line 0] == "count"} { set i 1; continue }
    if {$i == 1} { ;# 1 def label counts as none (e.g., 3dcalc output)
      if { [lindex $line 0] == "'#0~" } { return 0 } else { return 1 }
      set i 0
    }
  }
  return 0
}

### Import External 3D Statistics: select mask file for current value file
proc cbx:select_maskfile { page s } {
}

### Render panel: check selection in tclscript comboboxes
proc cbx:select_tclscript { combo s } {
  global tcldir
  if {$s == "--------" } { $combo pick 0; return } ;# divider only if user .tcl
  if { ![file exists $tcldir/$s] && ![file exists $s] } {
    confirmalert "Tcl Script: $s not found:\n\nTried:\n\n\
          (1) local: [pwd]\n (2) (absolute works, too)\n (3) tcl lib: $tcldir"
  }
}

### Render panel: reset bfloatstem on wfile select (possibly strip cplx infix)
proc cbx:select_wfilepref { nbwin s } {
  global renderscanlists lastbfloatstem lastrgbname
  global realname complexname amprealname ampcomplexname

  set page [demanglepath [$nbwin raised]]   ;# TODO: just pass page
  ## maybe stripinfix/reset bfloatstem just selected by user
  set uniqstem [getuniqcomplexstemlist $renderscanlists($page,bfloatstem)]
  if {$uniqstem != ""} { set renderscanlists($page,bfloatstem) $uniqstem }
  if {$renderscanlists($page,bfloatstem) != "-multiple-"} {
    if {$renderscanlists($page,rgbname) == "-multiple-" || \
        $renderscanlists($page,rgbname) == ""} { ;# fix rgbname even !samestem
      if ![info exists lastrgbname($page)] {
        set renderscanlists($page,rgbname) $renderscanlists($page,bfloatstem)
        set lastrgbname($page) $renderscanlists($page,rgbname)
      } else {
        set renderscanlists($page,rgbname) $lastrgbname($page)
      }
    }
    set lastbfloatstem($page) $renderscanlists($page,bfloatstem)
    set renderscanlists($page,renderlisttype) one  ;# => select_renderlisttype
  }
  if {$renderscanlists($page,samestem) == 1} {
    set renderscanlists($page,rgbname) $renderscanlists($page,bfloatstem)
  }
  if { [string match *${realname} $s] || \
       [string match *${complexname} $s] } {
    set renderscanlists($page,fourierampflag) 0
  }
  if { [string match *${amprealname} $s] || \
       [string match *${ampcomplexname} $s] } {
    set renderscanlists($page,fourierampflag) 1
  }

  ## update statmask (re-find matching mask if there)
  fixswfileprefs $page

  ## leave XSubPhaseMask up to user except: swap sqrtF/rawfourier
  if { [info exists renderscanlists($page,complexstatsource)] && \
       [info exists renderscanlists($page,fourierampflag)] } {
    set cplxstat $renderscanlists($page,complexstatsource)
    if {!$renderscanlists($page,fourierampflag) && $cplxstat == "fsig"} {
      set renderscanlists($page,complexstatsource) famp
    }
    if {!$renderscanlists($page,fourierampflag) && $cplxstat == "famp"} {
      set renderscanlists($page,complexstatsource) fsig
    }
  }
}

### Render panel: on select swfile (no strip infix)
proc cbx:select_swfilepref { nbwin s } {
  # no-op -- no err on override
}

### Render panel: PhaseMask tixSelect cplx statsrc -> chk file, thresh's, FTamp
proc select_complexstatsource { page buttonname selected } {
  global renderscanlists
  global realname complexname amprealname ampcomplexname
  global cplxstatname1 cplxstatname2 cplxstatname3 cplxstatname4 cplxstatname5
  global cplxstatname6 cplxstatname7
  global realfname realfclustname realpname realpclustname

  if {!$selected} { return }

  # N.B.: next two checks assume 1D .mgh Paintfiles are real
  ### check Paintfile to be masked actually cmplx (infixes should be stripped)
  if { [string match *_? $renderscanlists($page,bfloatstem)] || \
       [string match *.mgh $renderscanlists($page,bfloatstem)] } {
    confirmalert " Complex StatMask: button/Paintfile mismatch:\n\n\
            Current Paintfile:\n\n    $renderscanlists($page,bfloatstem)\n\n\
            First select one of complex-valued Paintfile pair:\n\n    infix:  \
            $realname  or  $complexname  or  $amprealname  or  $ampcomplexname"
    return
  }

  ### ask to reset to "phase" Data Type
  if {!$renderscanlists($page,complexvalflag)} {
    if ![okreplace "" \
          "OK to reset Data Type to \"phase\"?\
       \n\nN.B.: re-select Paintfile if current is not complex\
         \n(infix should be one of: _r, _x, _i, _y)"\
          "Reset Data Type"] { return }
    set renderscanlists($page,colscaletype) cplx
  }

  ### trigger fixswfileprefs to try to update StatMask file combo
  set renderscanlists($page,sbfloatstem) "-no_mask-"
  fixswfileprefs $page   ;# statmask entry left -no_mask- if no useable found

  ### always ask reset sane mid/thresh/slope's on change Select
  askresetcmplxthresh2sane $page $buttonname

  ### check fixswfileprefs reset, warn if doesn't match button request or unset
  set infix ""
  if [string match *_? $renderscanlists($page,sbfloatstem)] {
    set infix [string range $renderscanlists($page,sbfloatstem) \
      [expr [string length $renderscanlists($page,sbfloatstem)] - 2] end]
  }
  if {$renderscanlists($page,sbfloatstem) == "-no_mask-"} {
    set infix "\[no suitable wfile found\]"
  }

  ### update modtype select, check if statmask matches
  ## N.B.: chk 1sub (sig/fclu/fcoh) AND xsub (sig/famp/fsig/raang/tsig/tpow)!!
  if {$buttonname == "sig"} {   ;# orig sqrtF -- single sub or xsubj
    set renderscanlists($page,complexampmodtype) off
    if { $renderscanlists($page,fourierampflag) } {
      putlog "csurf: N.B.: reading raw Fourier amp, not sqrtF-substituted amp"
      #confirmalert "N.B.: reading raw Fourier amp Paintfiles (_x,_y)\
      #            \nvs. Fourier with sqrtF-substituted amp (_r,_i)\
      #         \n\nIf not wanted, untick \"FTamp\" below"
    }
    # ignore curr statmask
  }
  if {$buttonname == "fclu"} {  ;# _f,_h, _p, _q -- single sub only
    set renderscanlists($page,complexampmodtype) mask
    #set renderscanlists($page,fourierampflag) 0 ;# don't touch: either OK
    if { $infix != $realfname && $infix != $realfclustname && \
         $infix != $realpname && $infix != $realpclustname } {
      confirmalert " Complex StatMask: button/StatMask mismatch:\n\n\
                     current StatMask infix:  $infix\n\n\
                     \"sig+(clust)Fmask\" requires infixes:\
            \n  $realfname or $realfclustname or $realpname or $realpclustname"
    }
  }
  if {$buttonname == "fcoh"} {  ;# _c -- single sub only
    set renderscanlists($page,complexampmodtype) mask
    #set renderscanlists($page,fourierampflag) 0 ;# don't touch: either OK
    if { $infix != $cplxstatname7 } {
      confirmalert " Complex StatMask: button/StatMask mismatch:\n\n\
                     current StatMask infix:  $infix\n\n\
                     \"sig+coher\" requires infix:\
                    \n  $cplxstatname7"
    }
  }
  if {$buttonname == "famp"} {  ;# _f, _h -- xsubj only
    set renderscanlists($page,complexampmodtype) mask
    set renderscanlists($page,fourierampflag) 1
    if {$infix != $cplxstatname1 && $infix != $cplxstatname6 } {
      confirmalert " Complex StatMask: button/StatMask mismatch:\n\n\
                     current StatMask infix:  $infix\n\n\
             \"cxF-amp\" requires infix:  $cplxstatname1 or $cplxstatname6"
    }
  }
  if {$buttonname == "fsig"} {  ;# _g -- xsubj only
    set renderscanlists($page,complexampmodtype) mask
    set renderscanlists($page,fourierampflag) 0
    if {$infix != $cplxstatname2 } {
      confirmalert " Complex StatMask: button/StatMask mismatch:\n\n\
                     current StatMask infix:  $infix\n\n\
                     \"cxF-sig\" requires infix:  $cplxstatname2"
    }
  }
  if {$buttonname == "raang"} {  ;# _e -- xsubj only
    set renderscanlists($page,complexampmodtype) mask
    set renderscanlists($page,fourierampflag) 0
    if {$infix != $cplxstatname4 } {
      confirmalert " Complex StatMask: button/StatMask mismatch:\n\n\
                     current StatMask infix:  $infix\n\n\
                     \"cxR-ang\" requires infix:  $cplxstatname4"
    }
  }
  if {$buttonname == "tsig"} {  ;# _a -- xsubj only
    set renderscanlists($page,complexampmodtype) mask
    set renderscanlists($page,fourierampflag) 0
    if {$infix != $cplxstatname3 } {
      confirmalert " Complex StatMask: button/StatMask mismatch:\n\n\
                     current StatMask infix:  $infix\n\
                     \"t-sig\" requires infix:  $cplxstatname3"
    }
  }
  if {$buttonname == "tpow"} {  ;# _b -- xsubj only
    set renderscanlists($page,complexampmodtype) mask
    set renderscanlists($page,fourierampflag) 0
    if {$infix != $cplxstatname5 } {
      confirmalert " Complex StatMask: button/StatMask mismatch:\n\n\
                     current StatMask infix:  $infix\n\n\
                     \"t-pow\" requires infix:  $cplxstatname5"
    }
  }
}

### Render panel: called by select_complexstatsource (and FTamp tick)
proc askresetcmplxthresh2sane { page buttonname } {
  global renderscanlists

  ### on change "PhaseMask:" *or* "XSubPhaseMsk:" (pg-spec. complexstatsource)
  if { "$buttonname" == "sig" } {  ;# back to sqrtF *or* FTamp (1sub + xsub)
    if { $renderscanlists($page,fourierampflag) } {  ;# FTamp
      if { $renderscanlists($page,fslope) != 0.01 ||
           $renderscanlists($page,fmid) != 300.0 ||
           $renderscanlists($page,fthresh) != 30.0 } {
        if [okreplace "" \
              "OK to reset sane thresh for raw fourier amp (no stat mask)?\
           \n\n(left thresholds column this panel)\
           \n\n  \$fslope:   $renderscanlists($page,fslope)  -> 0.01\
             \n  \$fmid:       $renderscanlists($page,fmid)  -> 300.0\
             \n  \$fthresh:  $renderscanlists($page,fthresh)  -> 30.0\
           \n\nIf tksurfer up, kill/re-run SURFACE-STATS to see effect"\
              "Reset Paintfile thresholds"] {
          set renderscanlists($page,fslope)  0.01
          set renderscanlists($page,fmid)    300.0
          set renderscanlists($page,fthresh) 30.0
        }
      }
    } else {  ;# sqrtF
      if { $renderscanlists($page,fslope) != 1.5 ||
           $renderscanlists($page,fmid) != 2.5 ||
           $renderscanlists($page,fthresh) != 0.3 } {
        if [okreplace "" \
              "OK to reset sane thresholds for sqrtF (no stat mask)?\
           \n\n(left thresholds column this panel)\
           \n\n  \$fslope:   $renderscanlists($page,fslope)  -> 1.5\
             \n  \$fmid:       $renderscanlists($page,fmid)  -> 2.5\
             \n  \$fthresh:  $renderscanlists($page,fthresh)  -> 0.3\
           \n\nIf tksurfer up, kill/re-run SURFACE-STATS to see effect"\
              "Reset Paintfile thresholds"] {
          set renderscanlists($page,fslope)  1.5
          set renderscanlists($page,fmid)    2.5
          set renderscanlists($page,fthresh) 0.3
        }
      }
    }
  }

  if { "$buttonname" == "fclu" } {  ;# back to F (sig=FTamp *or* sqrtF) (1sub)
    if {$renderscanlists($page,fourierampflag)} {  ;# FTamp
      if { $renderscanlists($page,sfslope) != 0.5 ||
           $renderscanlists($page,sfmid) != 2.25 ||
           $renderscanlists($page,sfthresh) != 0.45 ||
           $renderscanlists($page,fslope) != 0.01 ||
           $renderscanlists($page,fmid) != 300.0 ||
           $renderscanlists($page,fthresh) != 30.0 } {
        if [okreplace "" \
              "OK reset sane thresh's for raw Fourier sig w/F-stat mask?\
           \n\n(right+left thresholds column this panel)\
           \n\n  \$sfslope:    $renderscanlists($page,sfslope)  -> 0.5\
             \n  \$sfmid:       $renderscanlists($page,sfmid)   -> 2.25\
             \n  \$sfthresh:  $renderscanlists($page,sfthresh)  -> 0.45\
           \n\n  \$fslope:    $renderscanlists($page,fslope)  -> 0.01\
             \n  \$fmid:       $renderscanlists($page,fmid)   -> 300.0\
             \n  \$fthresh:  $renderscanlists($page,fthresh)  -> 30.0\
           \n\nIf tksurfer up, kill/re-run SURFACE-STATS to see effect"\
              "Reset StatMask thresholds"] {
          set renderscanlists($page,sfslope)  0.5
          set renderscanlists($page,sfmid)    2.25
          set renderscanlists($page,sfthresh) 0.45
          set renderscanlists($page,fslope)  0.01
          set renderscanlists($page,fmid)    300.0
          set renderscanlists($page,fthresh) 30.0
        }
      }
    } else {  ;# sqrtF
      if { $renderscanlists($page,sfslope) != 0.5 ||
           $renderscanlists($page,sfmid) != 2.25 ||
           $renderscanlists($page,sfthresh) != 0.45 ||
           $renderscanlists($page,fslope) != 1.5 ||
           $renderscanlists($page,fmid) != 2.5 ||
           $renderscanlists($page,fthresh) != 0.3 } {
        if [okreplace "" \
              "OK reset sane thresh's for raw Fourier sig w/F-stat mask?\
           \n\n(right+left thresholds column this panel)\
           \n\n  \$sfslope:    $renderscanlists($page,sfslope)  -> 0.5\
             \n  \$sfmid:       $renderscanlists($page,sfmid)   -> 2.25\
             \n  \$sfthresh:  $renderscanlists($page,sfthresh)  -> 0.45\
           \n\n  \$fslope:    $renderscanlists($page,fslope)  -> 1.5\
             \n  \$fmid:       $renderscanlists($page,fmid)   -> 2.5\
             \n  \$fthresh:  $renderscanlists($page,fthresh)  -> 0.3\
           \n\nIf tksurfer up, kill/re-run SURFACE-STATS to see effect"\
              "Reset StatMask thresholds"] {
          set renderscanlists($page,sfslope)  0.5
          set renderscanlists($page,sfmid)    2.25
          set renderscanlists($page,sfthresh) 0.45
          set renderscanlists($page,fslope)   1.5
          set renderscanlists($page,fmid)     2.5
          set renderscanlists($page,fthresh)  0.3
        }
      }
    }
  }

  if { "$buttonname" == "fcoh" } {  ;# back to coherence (sig=FTamp *or* sqrtF)
    if {$renderscanlists($page,fourierampflag)} {  ;# FTamp
      if { $renderscanlists($page,sfslope) != 40.0 ||
           $renderscanlists($page,sfmid) != 0.15 ||
           $renderscanlists($page,sfthresh) != 0.05 ||
           $renderscanlists($page,fslope) != 0.01 ||
           $renderscanlists($page,fmid) != 300.0 ||
           $renderscanlists($page,fthresh) != 30.0 } {
        if [okreplace "" \
              "OK reset sane thresh's raw Fourier sig w/coherence stat mask?\
           \n\n(right+left thresholds column this panel)\
           \n\n  \$sfslope:    $renderscanlists($page,sfslope)  -> 40.0\
             \n  \$sfmid:       $renderscanlists($page,sfmid)  -> 0.15\
             \n  \$sfthresh:  $renderscanlists($page,sfthresh)  -> 0.05\
           \n\n  \$fslope:    $renderscanlists($page,fslope)  -> 0.01\
             \n  \$fmid:       $renderscanlists($page,fmid)   -> 300.0\
             \n  \$fthresh:  $renderscanlists($page,fthresh)  -> 30.0\
           \n\nIf tksurfer up, kill/re-run SURFACE-STATS to see effect"\
              "Reset StatMask thresholds"] {
          set renderscanlists($page,sfslope)  40.0
          set renderscanlists($page,sfmid)    0.15
          set renderscanlists($page,sfthresh) 0.05
          set renderscanlists($page,fslope)  0.01
          set renderscanlists($page,fmid)    300.0
          set renderscanlists($page,fthresh) 30.0
        }
      }
    } else {  ;# sqrtF
      if { $renderscanlists($page,sfslope) != 40.0 ||
           $renderscanlists($page,sfmid) != 0.15 ||
           $renderscanlists($page,sfthresh) != 0.05 ||
           $renderscanlists($page,fslope) != 1.5 ||
           $renderscanlists($page,fmid) != 2.5 ||
           $renderscanlists($page,fthresh) != 0.3 } {
        if [okreplace "" \
              "OK reset sane thresh's for sqrtF sig w/coherence stat mask?\
           \n\n(right+left thresholds column this panel)\
           \n\n  \$sfslope:    $renderscanlists($page,sfslope)  -> 40.0\
             \n  \$sfmid:       $renderscanlists($page,sfmid)  -> 0.15\
             \n  \$sfthresh:  $renderscanlists($page,sfthresh)  -> 0.05\
           \n\n  \$fslope:     $renderscanlists($page,fslope)  -> 1.5\
             \n  \$fmid:        $renderscanlists($page,fmid)   -> 2.5\
             \n  \$fthresh:   $renderscanlists($page,fthresh)  -> 0.3\
           \n\nIf tksurfer up, kill/re-run SURFACE-STATS to see effect"\
              "Reset StatMask thresholds"] {
          set renderscanlists($page,sfslope)  40.0
          set renderscanlists($page,sfmid)    0.15
          set renderscanlists($page,sfthresh) 0.05
          set renderscanlists($page,fslope)   1.5
          set renderscanlists($page,fmid)     2.5
          set renderscanlists($page,fthresh)  0.3
        }
      }
    }
  }

  ## TODO: cross-subject buttonnames in select_complexstatsource
  if {"$buttonname" == "sig"  } { }  ;# orig sqrtF (no mask) (also 1sub!)
  if {"$buttonname" == "famp" } { }  ;# Don's complex F on raw amp
  if {"$buttonname" == "fsig" } { }  ;# Don's complex F on sig
  if {"$buttonname" == "raang"} { }  ;# Rayleigh R
  if {"$buttonname" == "tsig" } { }  ;# t vs. sqrtF
  if {"$buttonname" == "tpow" } { }  ;# t (squared) vs. F (power)
}

### Render panel: on select/change complex amp mod type
proc select_complexampmodtype { page buttonname selected } {
  global renderscanlists statmaskparmslist

  if {!$selected} { return }
  if {$buttonname == "mask"} {
    set renderscanlists($page,sbfloatstem) "-no_mask-" ;# trigger next to reset
    fixswfileprefs $page
  }
  if {$buttonname == "off"} {
    set renderscanlists($page,sbfloatstem) "-no_mask-"
  }
  # toggle statmask entries
  if {$buttonname == "mask"} {
    foreach ent $statmaskparmslist($page) { $ent config -state normal }
  } else {
    foreach ent $statmaskparmslist($page) { $ent config -state disabled }
  }
}

### Cross Sess Spherical Average Panel: check selected subject, rewrite namefile
proc cbx:select_dispsubject { s } {
  global env name dispname session choosingavgsurfdir

  if {$choosingavgsurfdir} { return }  ;# separate checks in avgsurfcmd
  if {$s == "__nobody__" || $s == ""} { return }
  set islink 0
  catch {
    if { [file type $env(SUBJECTS_DIR)/$s] == "link" } { set islink 1 }
  }
  if { $islink && ![file exists $env(SUBJECTS_DIR)/$s] } {
    confirmalert "Display Subject: $s is a stale link"
    return
  }
  if ![file exists $env(SUBJECTS_DIR)/$s] {
    confirmalert "Display Subject: $s\nnot found in $env(SUBJECTS_DIR)"
    return
  }
  if ![file isdirectory $env(SUBJECTS_DIR)/$s] { return }

  set namefile $env(FUNCTIONALS_DIR)/$session/name
  if [file exists $namefile] {
    set id [open $namefile r]
    set prevsubjname [string trim [read $id]]
    close $id
  } else {
    confirmalert "Display Subject: $namefile not found"
    return
  }
  if {"$dispname" == "$name"} { return }

  if ![okreplace "" \
 "Update contents of namefile:\n\n    $namefile\n\nto:\n\n    $s" "Update"] {
    confirmalert "Namefile: $namefile not altered"
    set dispname $name
    return
  } else {
    if ![canwriteormakefile $namefile] {
      confirmalert "Display Subject: can't modify namefile:\n\n  $namefile"
      set dispname $name
      return
    } else {
      set id [open $namefile w 0644]
      puts $id "$dispname"
      close $id
    }
  }
  set name $dispname
  cdfunctscripts
}

### Cross Sess Spherical Average Panel: fix subj, morphsurf,fill scandirs combo
proc cbx:select_sphavgsess { num scandirscombo2 s } {
  global spgsessions spgsubjects spgscandirs spgvtxlistprefs spgmorphsurfs
  global spgstatbrikprefs
  global env session hemi surfdir sphereext regext subjectscombo

  set spgsubjects($num)      ""
  set spgscandirs($num)      ""   ;# N.B.: iscandirs
  set spgvtxlistprefs($num)  ""
  set spgmorphsurfs($num)    ""
  set spgstatbrikprefs($num) ""

  set namefile $env(FUNCTIONALS_DIR)/$spgsessions($num)/name
  if [file exists $namefile] {
    set id [open $namefile r]
    set subjname [string trim [read $id]]
    close $id
    if [file exists $env(SUBJECTS_DIR)/$subjname] {
      set spgsubjects($num) $subjname
    } else {
      # ignore namefile subject not found
    }
  } else {
    # ignore missing namefile
  }

  if {"$spgsubjects($num)" != ""} {
    set fullsurfdir $env(SUBJECTS_DIR)/$spgsubjects($num)/$surfdir
    set spgmorphsurfs($num) not_found
    if {$hemi == "both"} {
      if { [file exists $fullsurfdir/rh.$sphereext.$regext] || \
           [file exists $fullsurfdir/lh.$sphereext.$regext] } {
        set spgmorphsurfs($num) $sphereext.$regext
      }
    }
    if {$hemi == "rh"} {
      if { [file exists $fullsurfdir/rh.$sphereext.$regext] } {
        set spgmorphsurfs($num) $sphereext.$regext
      }
    }
    if {$hemi == "lh"} {
      if { [file exists $fullsurfdir/lh.$sphereext.$regext] } {
        set spgmorphsurfs($num) $sphereext.$regext
      }
    }
  }

  $scandirscombo2 subwidget listbox delete 0 end
  set savesession $session
  $subjectscombo config -disablecallback true ;# stop sesstouch->cdsubjscripts
  set session $spgsessions($num)
  set scandirslist [getfunctiscandirslist]
  set session $savesession
  $subjectscombo config -disablecallback false
  foreach trimmeddir $scandirslist { $scandirscombo2 insert end $trimmeddir }
}

### Cross Sess Spherical Average Panel: fill wfile/statbrik combos on scandirsel
proc cbx:select_sphavgscandir { num wfilescombo statbrikscombo s } {
  global env session subjectscombo
  global sphavglists spgsessions spgvtxlistprefs spgstatbrikprefs

  set savesession $session
  $subjectscombo config -disablecallback true ;# stop sesstouch->cdsubjscripts
  set session $spgsessions($num)
  # find uniq infix-stripped wfile prefixes
  set preflist [getuniqwfilelist $s]
  if {$sphavglists(00,phasetype) == "real"} {  ;# leave infixes (if any)
    set cpreflist [lsort $preflist]
  } else {  ;# strip infixes, uniq-ize (sphavgcxcmd manages infixes)
    set cpreflist [lsort [getuniqcomplexstemlist $preflist]]
  }
### xxx -- also load SamSrf label files ${hemi}_*.label in curr scandir?
# --get uniqcomlexstemlist can strip complex infixes
# --SamSrf label:   $hemi_<stem><infix>.label ('_' vs. MGH='.' and me='-')
# --Standard wfile: <stem><infix>-$hemi.w
#  => need new phasetype (polar,eccen,2cond,real): add spol/secc
# --could write sam getuniq functs to directly use above
# --problem: need adapt sphavgcxcmd (convert for mri_surf2surf to read??)
# --easier to write script to conv labels->wfiles, put in scandir!
#========================================
#  # HOWTO match SamSrf labels in this scandir
#  set patt $env(FUNCTIONALS_DIR)/$session/$s/?h_pRF*.label
#  set lablist [glob -nocomplain $patt]
### xxx -- end
  # find all briks (no prefix strip)
  set briklist [getbriklist $s]
  set session $savesession
  $subjectscombo config -disablecallback false

  # clear wfiles combo/combovar, load uniq infix-less wfile prefixes into combo
  set spgvtxlistprefs($num) ""
  $wfilescombo subwidget listbox delete 0 end
  set cpreftailslist {}
  foreach pref $cpreflist { lappend cpreftailslist [file tail $pref] }
  foreach wfilepref $cpreftailslist { $wfilescombo insert end $wfilepref }
  # clear statsbrik combo/combovar, load all scandir briks into combo
  set spgstatbrikprefs($num) ""
  $statbrikscombo subwidget listbox delete 0 end
  set btailslist {}
  foreach brik $briklist { ;# filter out raw data files (was: just first)
    if { [string match *+orig_?+orig.BRIK $brik] || \
         [string match *Coef*+orig.BRIK $brik] } {
      lappend btailslist [file tail $brik]
    }
  }
  foreach btail $btailslist { $statbrikscombo insert end $btail }
}

### Cross Sess Spherical Average Panel: infix already stripped (vs. next)
proc cbx:select_sphavgwfile { num s } {
}

### Cross Sess Spherical Average Panel: strip infix (like cbx:select_wfilepref)
proc cbx:select_volavgstatbrik { num s } {
  global realname complexname amprealname ampcomplexname
  global sphavglists spgstatbrikprefs
  if [string match *+orig.BRIK $s] {
    set stemend [expr [string length $s] - 11]   ;# strip +orig.BRIK
    set stem [string range $s 0 $stemend]
    if {$sphavglists(00,phasetype) != "real"} {
      if       [string match *${realname} $stem] {         ;# trim _r
        set reallen [string length $realname]
        set stemend [expr [string length $stem] - $reallen - 1]
      } elseif [string match *${complexname} $stem] {      ;# trim _i
        set complexlen [string length $complexname]
        set stemend [expr [string length $stem] - $complexlen - 1]
      } elseif [string match *${amprealname} $stem] {      ;# trim _x
        set ampreallen [string length $amprealname]
        set stemend [expr [string length $stem] - $ampreallen - 1]
      } elseif [string match *${ampcomplexname} $stem] {   ;# trim _y
        set ampcomplexlen [string length $ampcomplexname]
        set stemend [expr [string length $stem] - $ampcomplexlen - 1]
      } else {
        set stemend [expr [string length $stem] - 1]  ;# unrec untrimmed
      }
      set stem [string range $stem 0 $stemend]
    }
    set spgstatbrikprefs($num) $stem
  }
}

### check power of 2 for fourier reps
proc checkpow2 { val } {
  if [catch {set ival [expr int($val)]} ] {
    confirmalert \
      "Fourier: Images Per Slice: $val => not a num\n\nRedo Setup Funct Scans"
    return
  }
  if {$val != $ival} {
    confirmalert \
     "Fourier: Images Per Slice: $val => not an int\n\nRedo Setup Funct Scans"
    return
  }
  while { [expr $ival / 2] } {
    if { [expr $ival % 2] } {
      confirmalert \
 "Fourier: Images Per Slice: $val => not power of 2\n\nRedo Setup Funct Scans"
      return
    } else { set ival [expr $ival / 2] }
  }
}

### (use tcl error checking)
proc isnum { val } {
  if [catch {set num [expr int($val)]} ] { return 0 } else { return 1 }
}

### go to session script dir to run SessionTools programs
proc cdfunctscripts { } {
  global env session program tmpdir startupdone
  if {$session == "__nosession__" || $session == "" || !$startupdone} {return}
  set fullsess $env(FUNCTIONALS_DIR)/$session
  if ![file isdirectory $fullsess] {
    confirmalert "Session: $fullsess: not a directory\n\n ...cd'ing to $tmpdir"
    set scriptsdir $tmpdir 
  } else {
    set scriptsdir $fullsess/image/scripts
    if ![file exists $scriptsdir] {
      set scriptsdir \
        [glob -nocomplain $fullsess/?????/scripts]
      if ![file exists $scriptsdir] {
        set scriptsdir $fullsess/scripts
        if { ![file exists $scriptsdir] } {
          confirmalert "Session: $session: \"scripts\" subdir not found\n\n\
            Checked for:\n\n\
            $fullsess/image/scripts\n\
            $fullsess/scripts\n\
            $fullsess/?????/scripts\n\n\
            ...using $tmpdir (make scripts dir to save session-specific parms)"
          set scriptsdir $tmpdir
        }
      }
    }
  }
  cdlog $scriptsdir
  wm title . "$program -- $scriptsdir"
  return $scriptsdir
}

### go to subject script dir to run SubjectTools programs
proc cdsubjectscripts { } {
  global env name program tmpdir startupdone
  if {$name == "__nobody__" || $name == "" || !$startupdone} { return }
  set fullname $env(SUBJECTS_DIR)/$name
  if ![file isdirectory $fullname] {
    confirmalert "Subject: $fullname: not a directory\n\n ...cd'ing to $tmpdir"
    set scriptsdir $tmpdir
  } else {
    set scriptsdir $fullname/scripts
    if { ![file exists $scriptsdir] } {
      confirmalert "Subject: $name: \"scripts\" subdir not found:\n\n\
          \t$fullname/scripts\n\n\
          ...using $tmpdir (make scripts dir to save subject-specific parms)"
      set scriptsdir $tmpdir
    }
  }
  cdlog $scriptsdir
  wm title . "$program -- $scriptsdir"
  return $scriptsdir
}

### go into scandir (twitzel tkmedit, afni, 3dDeconvolve) (vs. scriptdir)
proc cdscandir { } {
  global env session iscandir program tmpdir
  set fullscandir $env(FUNCTIONALS_DIR)/$session/$iscandir
  if ![file exists $fullscandir] { set fullscandir $tmpdir }
  cdlog $fullscandir
  wm title . "$program -- $fullscandir"
  return $fullscandir
}

### backward compat for oldstyle inflated extension
proc getinflatedext { } {
  global env name hemi surfdir
  global inflatedext oldinflatedext
  set inflatedsurf    $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$inflatedext
  set oldinflatedsurf $env(SUBJECTS_DIR)/$name/$surfdir/$hemi.$oldinflatedext
  if [file exists $inflatedsurf]    { return $inflatedext }
  if [file exists $oldinflatedsurf] { return $oldinflatedext }
  return $inflatedext
}

### Expert Preferences menu command--make notebook window
proc setupexpertparms { } {
  global env name datfile csurfstripskullflag
  global convparms stripskullparms normalizeparms wmfilterparms wmfillparms
  global surfparms inflateparms finalparms flattenparms sphereparms postclparms
  global lightparms
  global bgcol selbgcol selcol ffont ffontb
  global oldfillentlist newfillentlist helpwinlines

  set w .setuppopup
  if [winfo exists .setuppopup] {  ;# save/kill/reopen expertparms for a few
    if { $wmfillparms(usehiresfillflag) || \
         $wmfilterparms(usehireswmfilterflag) || \
         $stripskullparms(usehiresstripskullflag) } {
      writearrayparms $datfile struct   ;# N.B.: force save
      destroy $w
    } else {  ;# orig
      raise .setuppopup
      confirmalert "Close current panel first"
      return
    }
  }
  if [winfo exists .progress] {  ;# allow open w/bgsequence open for a few
    if { !$wmfillparms(usehiresfillflag) && \
         !$wmfilterparms(usehireswmfilterflag) && \
         !$stripskullparms(usehiresstripskullflag) } {
      raise .progress
      confirmalert "Finish current operation first"
      return
    }
  }
  toplevel $w -background $bgcol
  ::tk::classic::restore  ;# newpkgtix
  wm title $w "Subject Expert Preferences Settings (adjust carefully)"
  positionpopup $w

  set title $w.ti
  frame $title -background $bgcol
  pack $title -side top -fill x -padx 10
  label $title.la -text "Subject Directory:  $name" -borderwidth 2 \
     -background $bgcol -relief groove -padx 7 -pady 7
  tixButtonBox $title.bu -bd 1 -background $bgcol -relief flat
  $title.bu add subjdefaults -text "Restore CurrSubj Defaults" -width 21 \
    -command "resetparms subject" -highlightbackground $bgcol
  $title.bu add sessdefaults -text "Restore CurrSess Defaults" -width 21 \
    -command "resetparms funct" -highlightbackground $bgcol
  pack $title.la -side left -anchor w
  $title.bu config -pady 20  ;# newpkgtix
  pack $title.bu -side left -padx 0

  set top $w.to
  frame $top -bd 1 -relief raised -background $bgcol
  pack $top -side top -fill both -expand yes

  configtixbookcbxent $w
  set nbwin $w.to.nb
  tixNoteBook $nbwin -ipadx 0 -ipady 6 -bg $bgcol
  $w.to config -bg $bgcol  ;# tabpady on next: newpkgtix
  $nbwin subwidget nbframe config -bg $bgcol -backpagecolor $bgcol -tabpady 5

  $nbwin add conv       -label "Conv"
  $nbwin add normalize  -label "Norm"
  $nbwin add stripskull -label "RmSkull"
  $nbwin add wmfilter   -label "FilterWM"
  $nbwin add wmfill     -label "FillWM"
  $nbwin add surf       -label "Surf"
  $nbwin add inflate    -label "Inflate"
  $nbwin add inflatep   -label "InflateP"
  $nbwin add final      -label "Final"
  $nbwin add flatten    -label "Flatten"
  $nbwin add sphere     -label "SphereReg"
  $nbwin add position   -label "Views"
  $nbwin add lights     -label "Lights"
  pack $nbwin -expand yes -fill both -padx 5 -pady 5 -side top

  ### read previously saved parms
  cdsubjectscripts
  if [file exists $datfile] { readarrayparms $datfile struct }
  set foundoldpostcl [readoldpositiontcl]

  ### convert
  set f [$nbwin subwidget conv]
  $f config -bg $bgcol
  tixLabelFrame $f.la -label "Align Structs Before Average Method" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -bg $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  pack $f.la -side top
  set f [$f.la subwidget frame]
  $f config -bg $bgcol
  radiobutton $f.a -text "Simple average (no align)" \
     -variable convparms(aligntype) -value noalign \
     -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
  radiobutton $f.b -text "Internal linear register (under test)" \
     -variable convparms(aligntype) -value intalign \
     -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
  radiobutton $f.c -text "MNI linear register (must be installed separately)" \
     -variable convparms(aligntype) -value mnialign \
     -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
  #pack $f.a -side top -anchor w -padx 10 -pady 2 ;# TODO: uncover when Mac
  #pack $f.b -side top -anchor w -padx 10 -pady 2 ;# TODO: uncover if -align OK
  #pack $f.c -side top -anchor w -padx 10 -pady 2 ;# TODO: uncover if intalled
  radiobutton $f.d -text "Manual align with tkregister" \
     -variable convparms(aligntype) -value manualalign \
     -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
  pack $f.d -side top -anchor w -padx 10 -pady 2
  radiobutton $f.e -text "Auto align with AFNI 3dvolreg" \
     -variable convparms(aligntype) -value afnialign \
     -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
  pack $f.e -side top -anchor w -padx 10 -pady 2
  radiobutton $f.f -text "Auto align with AFNI 3dvolreg (-heptic)" \
     -variable convparms(aligntype) -value afnihalign \
     -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
  pack $f.f -side top -anchor w -padx 10 -pady 2

  ### normalize
  set f [$nbwin subwidget normalize]
  $f config -bg $bgcol
  tixLabelEntry $f.a -label "intensity gradient limit (0.6): " -labelside left\
    -options "entry.textVariable normalizeparms(intensgradlim)"
  tixLabelEntry $f.b -label "normalize steps (2): " -labelside left \
    -options "entry.textVariable normalizeparms(normsteps)"
  checkbutton $f.c -text "use manual control points (\$subj/tmp/control.dat)" \
    -variable normalizeparms(manualcontrol) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  pack $f.a $f.b $f.c -side top -padx 10 -pady 2

  ### stripskull
  set f [$nbwin subwidget stripskull]
  $f config -bg $bgcol
  if {$csurfstripskullflag} {
    label $f.a0 -text "mri_strip_skull and tkstrip/hi-res" -bg $bgcol \
      -font $ffont
    tixLabelEntry $f.a -label "fzero (40:low->erode less): " -labelside left \
      -options "entry.textVariable stripskullparms(fzero)"
    tixLabelEntry $f.b -label "fmax (130:high->erode less): " -labelside left \
      -options "entry.textVariable stripskullparms(fmax)"
    tixLabelEntry $f.c -label "dfrac (starting diameter): " -labelside left \
      -options "entry.textVariable stripskullparms(dfrac)"
    tixLabelEntry $f.d -label "istilt (inside stilt in mm): " -labelside left \
      -options "entry.textVariable stripskullparms(istilt)"
    label $f.e -bg $bgcol
    label $f.f -text "tkstrip/hi-res only" -bg $bgcol -font $ffont
    tixLabelEntry $f.g -label "action (0-5:no,br,in,out,sk,pd): " \
      -labelside left -options "entry.textVariable stripskullparms(action)"
    tixLabelEntry $f.h -label "fsteepness (MRI->forcetanh): " -labelside left \
      -options "entry.textVariable stripskullparms(fsteepness)"
    tixLabelEntry $f.i -label "fstrength (sm4,pntforcetanh): " -labelside left \
      -options "entry.textVariable stripskullparms(fstrength)"
    tixLabelEntry $f.j -label "update (d+=update*d): " -labelside left \
      -options "entry.textVariable stripskullparms(update)"
    tixLabelEntry $f.k -label "decay (if momentum): " -labelside left \
      -options "entry.textVariable stripskullparms(decay)"
    label $f.l -bg $bgcol
    checkbutton $f.ck1 -text "use tkstrip tcl script instead" \
      -variable stripskullparms(usescript) -bg $bgcol -selectcolor $selcol \
      -highlightbackground $bgcol
    tixLabelEntry $f.m -label "tcl (rel: subj/scripts, else lib): " \
      -labelside left -options "entry.textVariable stripskullparms(tclscript)"
    button $f.bu -text "VIEW TCL SCRIPT" -font $ffontb -pady 2 -padx 5 \
      -highlightbackground $bgcol -command \
      "helpwin $stripskullparms(tclscript) 50 50 $env(CSURF_DIR)/lib/tcl"
    pack $f.a0 $f.a $f.b $f.c $f.d $f.e $f.f $f.g $f.h $f.i $f.j $f.k $f.l \
       $f.ck1 $f.m $f.bu -side top -padx 10 -pady 2
    # another call to Help -> Strip Skull (hi-res) 
    bind $f <ButtonRelease-3> { helpwin stripskullhires 50 $helpwinlines }
  }

  ### wmfilter
  set f [$nbwin subwidget wmfilter]
  $f config -bg $bgcol
  tixLabelEntry $f.a -label "white high limit (125): " -labelside left \
    -options "entry.textVariable wmfilterparms(wm_hi)"
  tixLabelEntry $f.b -label "white low limit (90): " -labelside left \
    -options "entry.textVariable wmfilterparms(wm_low)"
  tixLabelEntry $f.c -label "gray high limit (100): " -labelside left \
    -options "entry.textVariable wmfilterparms(gray_hi)"
  checkbutton $f.d \
    -text "use wmfilter (vs. mri_segment)" \
    -variable wmfilterparms(usehireswmfilterflag) -bg $bgcol \
    -selectcolor $selcol -highlightbackground $bgcol
  label $f.la0 -text "\nmri_segment options" -bg $bgcol
  checkbutton $f.e -text "keep wm edits (for manual renormalize)" \
    -variable wmfilterparms(keepedits) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  label $f.la1 -text "\nwmfilter options" -bg $bgcol
  checkbutton $f.f \
    -text "Gauss plane filter + trunc (vs. trunc/filter/trunc)" \
    -variable wmfilterparms(gausstruncflag) -bg $bgcol \
    -selectcolor $selcol -highlightbackground $bgcol
  tixLabelEntry $f.g -label "Gauss kern width, pix (1.5): " -labelside left \
    -options "entry.textVariable wmfilterparms(kfwhm)"
  pack $f.a $f.b $f.c $f.d $f.la0 $f.e $f.la1 $f.f $f.g \
    -side top -padx 10 -pady 2
  # another call to Help -> Filter WM (hi-res) 
  bind $f <ButtonRelease-3> { helpwin wmfilterhires 50 $helpwinlines }

  ### fill
  set f [$nbwin subwidget wmfill]
  $f config -bg $bgcol
  # first label frame
  tixLabelFrame $f.la1 -label \
     "mri_fill" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f.la1.border.pad config -bg $bgcol   ;# internal ugh
  $f.la1.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f1 [$f.la1 subwidget frame]
  $f1 config -bg $bgcol -bd 3
  tixLabelEntry $f1.a -label "max same neighbors: " -labelside left -options \
    "entry.textVariable wmfillparms(max_same_neigh)"
  checkbutton $f1.b \
    -text "Set detached callosum point (coords from medit tools)" \
    -variable wmfillparms(callpnt) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  frame $f1.c -bg $bgcol
  tixLabelEntry $f1.c.x -label "xTal: " -labelside left -options \
    "entry.textVariable wmfillparms(callx)"
  tixLabelEntry $f1.c.y -label "yTal: " -labelside left -options \
    "entry.textVariable wmfillparms(cally)"
  tixLabelEntry $f1.c.z -label "zTal: " -labelside left -options \
    "entry.textVariable wmfillparms(callz)"
  checkbutton $f1.d -text "Set detached pons point (coords from medit tools)" \
    -variable wmfillparms(ponspnt) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  frame $f1.e -bg $bgcol
  tixLabelEntry $f1.e.x -label "xTal: " -labelside left -options \
    "entry.textVariable wmfillparms(ponsx)"
  tixLabelEntry $f1.e.y -label "yTal: " -labelside left -options \
    "entry.textVariable wmfillparms(ponsy)"
  tixLabelEntry $f1.e.z -label "zTal: " -labelside left -options \
    "entry.textVariable wmfillparms(ponsz)"
  checkbutton $f1.f -text "Constrain midbrain cut by A/P of callosal cut" \
    -variable wmfillparms(ccmask) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  foreach ent "$f1.c.x $f1.c.y $f1.c.z $f1.e.x $f1.e.y $f1.e.z" {
    $ent subwidget label config -width 7
    $ent subwidget entry config -width 5
  }
  pack $f.la1 -side top
  pack $f1.a $f1.b $f1.c $f1.d $f1.e -side top -padx 10 -pady 2
  pack $f1.c.x $f1.c.y $f1.c.z -side left
  pack $f1.e.x $f1.e.y $f1.e.z -side left
  pack $f1.f -side top
  # second label frame
  tixLabelFrame $f.la2 -label \
     "fill (original completely manual, native coords only, hi-res OK)" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f.la2.border.pad config -bg $bgcol   ;# internal ugh
  $f.la2.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f2 [$f.la2 subwidget frame]
  $f2 config -bg $bgcol -bd 3
  frame $f2.a -bg $bgcol
  checkbutton $f2.a.a \
    -text "use \"fill\" (vs. \"mri_fill\")" \
    -variable wmfillparms(usehiresfillflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  tixLabelEntry $f2.a.b -label "CutPlanesCol (0,hi-res=80): " -labelside \
    left -options "entry.textVariable wmfillparms(clipfeedback)"
  tixLabelEntry $f2.a.c -label "thr (2.0):" -labelside \
    left -options "entry.textVariable wmfillparms(wmfillthresh)"
  $f2.a.b subwidget label config -width 25
  $f2.a.b subwidget entry config -width 4
  $f2.a.c subwidget label config -width 9
  $f2.a.c subwidget entry config -width 4
  frame $f2.b -bg $bgcol
  tixLabelEntry $f2.b.a -label "RH WM seed(127):     col:" -labelside left \
    -options "entry.textVariable wmfillparms(seed1valRH)"
  $f2.b.a subwidget label config -width 21
  $f2.b.a subwidget entry config -width 4
  tixLabelEntry $f2.b.b -label "PA:" -labelside left -options \
    "entry.textVariable wmfillparms(seed1A)"
  tixLabelEntry $f2.b.s -label "IS:" -labelside left -options \
    "entry.textVariable wmfillparms(seed1S)"
  tixLabelEntry $f2.b.l -label "RL:" -labelside left -options \
    "entry.textVariable wmfillparms(seed1L)"
  frame $f2.c -bg $bgcol
  tixLabelEntry $f2.c.a -label "LH WM seed(255):     col:" -labelside left \
    -options "entry.textVariable wmfillparms(seed2valLH)"
  $f2.c.a subwidget label config -width 21 
  $f2.c.a subwidget entry config -width 4
  tixLabelEntry $f2.c.b -label "PA:" -labelside left -options \
    "entry.textVariable wmfillparms(seed2A)"
  tixLabelEntry $f2.c.s -label "IS:" -labelside left -options \
    "entry.textVariable wmfillparms(seed2S)"
  tixLabelEntry $f2.c.l -label "RL:" -labelside left -options \
    "entry.textVariable wmfillparms(seed2L)"
  frame $f2.d -bg $bgcol
  label $f2.d.la -text "CallosumCut:" -bg $bgcol -width 11
  tixLabelEntry $f2.d.p -label "P:" -labelside left -options \
    "entry.textVariable wmfillparms(callP)"
  tixLabelEntry $f2.d.a -label "A:" -labelside left -options \
    "entry.textVariable wmfillparms(callA)"
  label $f2.d.sp1 -bg $bgcol -width 2
  tixLabelEntry $f2.d.i -label "I:" -labelside left -options \
    "entry.textVariable wmfillparms(callI)"
  tixLabelEntry $f2.d.s -label "S:" -labelside left -options \
    "entry.textVariable wmfillparms(callS)"
  label $f2.d.sp2 -bg $bgcol -width 2
  tixLabelEntry $f2.d.r -label "R:" -labelside left -options \
    "entry.textVariable wmfillparms(callR)"
  tixLabelEntry $f2.d.l -label "L:" -labelside left -options \
    "entry.textVariable wmfillparms(callL)"
  frame $f2.e -bg $bgcol
  label $f2.e.la -text "MidbrainCut:" -bg $bgcol -width 11
  tixLabelEntry $f2.e.p -label "P:" -labelside left -options \
    "entry.textVariable wmfillparms(midbP)"
  tixLabelEntry $f2.e.a -label "A:" -labelside left -options \
    "entry.textVariable wmfillparms(midbA)"
  label $f2.e.sp1 -bg $bgcol -width 2
  tixLabelEntry $f2.e.i -label "I:" -labelside left -options \
    "entry.textVariable wmfillparms(midbI)"
  tixLabelEntry $f2.e.s -label "S:" -labelside left -options \
    "entry.textVariable wmfillparms(midbS)"
  label $f2.e.sp2 -bg $bgcol -width 2
  tixLabelEntry $f2.e.r -label "R:" -labelside left -options \
    "entry.textVariable wmfillparms(midbR)"
  tixLabelEntry $f2.e.l -label "L:" -labelside left -options \
    "entry.textVariable wmfillparms(midbL)"
  frame $f2.f -bg $bgcol
  tixLabelEntry $f2.f.a -label "Fill Cyc(10,20):" -labelside left -options \
    "entry.textVariable wmfillparms(max_fill_iter)"
  tixLabelEntry $f2.f.b -label "Fill Done(100,10):" -labelside left -options \
    "entry.textVariable wmfillparms(min_filled_per_cyc)"
  tixLabelEntry $f2.f.c -label "Max Same Neigh(10,8):" \
    -labelside left -options "entry.textVariable wmfillparms(max_same_neigh)"
  foreach ent "$f2.b.b $f2.b.s $f2.b.l $f2.c.b $f2.c.s $f2.c.l" {
    $ent subwidget label config -width 6
    $ent subwidget entry config -width 5
  }
  foreach ent "$f2.d.p $f2.d.a $f2.d.i $f2.d.s $f2.d.r $f2.d.l \
               $f2.e.p $f2.e.a $f2.e.i $f2.e.s $f2.e.r $f2.e.l" {
    $ent subwidget label config -width 2
    $ent subwidget entry config -width 4
  }
  $f2.f.a subwidget label config -width 13
  $f2.f.a subwidget entry config -width 3
  $f2.f.b subwidget label config -width 16
  $f2.f.b subwidget entry config -width 4
  $f2.f.c subwidget label config -width 21
  $f2.f.c subwidget entry config -width 3
  pack $f.la2 -side top
  pack $f2.a $f2.b $f2.c $f2.d $f2.e $f2.f -side top -padx 10 -pady 2
  pack $f2.a.a $f2.a.b $f2.a.c $f2.b.a $f2.b.b $f2.b.s $f2.b.l -side left
  pack $f2.c.a $f2.c.b $f2.c.s $f2.c.l -side left
  pack $f2.d.la $f2.d.p $f2.d.a $f2.d.sp1 $f2.d.i $f2.d.s $f2.d.sp2 $f2.d.r \
    $f2.d.l -side left
  pack $f2.e.la $f2.e.p $f2.e.a $f2.e.sp1 $f2.e.i $f2.e.s $f2.e.sp2 $f2.e.r \
    $f2.e.l -side left
  pack $f2.f.a $f2.f.b $f2.f.c -side left
  set newfillentlist "$f1.a $f1.c.x $f1.c.y $f1.c.z $f1.e.x $f1.e.y $f1.e.z"
  set oldfillentlist \
    "$f2.a.b $f2.a.c $f2.b.a $f2.b.b $f2.b.s $f2.b.l $f2.c.a $f2.c.b \
     $f2.c.s $f2.c.l \
     $f2.d.p $f2.d.a $f2.d.i $f2.d.s $f2.d.r $f2.d.l \
     $f2.e.p $f2.e.a $f2.e.i $f2.e.s $f2.e.r $f2.e.l \
     $f2.f.a $f2.f.b $f2.f.c"  ;# both lists global
  if {$wmfillparms(usehiresfillflag)} {  ;# init
    foreach ent $newfillentlist { $ent config -state disabled }
    foreach ent $oldfillentlist { $ent config -state normal }
  } else {
    foreach ent $newfillentlist { $ent config -state normal }
    foreach ent $oldfillentlist { $ent config -state disabled }
  }
  $f2.a.a config -command { if {$wmfillparms(usehiresfillflag)} { \
      foreach ent $newfillentlist { $ent config -state disabled }; \
      foreach ent $oldfillentlist { $ent config -state normal }; \
    } else { \
      foreach ent $newfillentlist { $ent config -state normal }; \
      foreach ent $oldfillentlist { $ent config -state disabled }; \
    } } ;# on change
  # another call to Help -> Fill WM (hi-res)
  bind $f <ButtonRelease-3> { helpwin fillhires 50 $helpwinlines }

  ### surf, tksurfer
  set f [$nbwin subwidget surf]
  $f config -bg $bgcol
  label $f.la1 -text "\nWM fill/surf Seed Colors" -bg $bgcol
  label $f.la2 -text "(used here, change in FillWM)" \
     -bg $bgcol -font $ffont
  tixLabelEntry $f.a -label "RH (127): " \
    -labelside left -options "entry.textVariable wmfillparms(seed1valRH)"
  tixLabelEntry $f.b -label "LH (255): " \
    -labelside left -options "entry.textVariable wmfillparms(seed2valLH)"
  $f.a subwidget label config -width 9
  $f.a subwidget entry config -width 4 -state disabled
  $f.b subwidget label config -width 9
  $f.b subwidget entry config -width 4 -state disabled
  label $f.la3 -text "\nRead Surface Options" -bg $bgcol
  checkbutton $f.ck1 -text "Quad Surfaces: divide each quad into 2 triangles" \
    -variable surfparms(dividequadsflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  label $f.la4 -text "\nWrite Surface Options" -bg $bgcol
  checkbutton $f.ck2 \
    -text "write div'd->tri quads as quads (leave live divided)" \
    -variable surfparms(undividequadsflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $f.ck3 -text "new quad (float) output, else orig (short)" \
    -variable surfparms(newquadoutputflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  label $f.la5 -text "\nWrite Curv/Area Options" -bg $bgcol
  checkbutton $f.ck4 -text "New Curv (float), Area (not 2x)" \
    -variable surfparms(newcurvareaoutputflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  pack $f.la1 $f.la2 $f.a $f.b $f.la3 $f.ck1 $f.la4 $f.ck2 $f.ck3 \
    $f.la5 $f.ck4 -side top

  ### inflate (with mris_inflate,  includes smooth)
  set f [$nbwin subwidget inflate]
  $f config -bg $bgcol
  label $f.la0 -text "Options for mris_inflate (inflate full surf)\n" \
    -bg $bgcol -font $ffontb
  label $f.la1 -text "standard resolution (1x1x1mm)" \
    -bg $bgcol -font $ffont
  tixLabelEntry $f.a -label "smooth cycles (10): " -labelside left \
    -options "entry.textVariable inflateparms(smoothcycles)"
  tixLabelEntry $f.b -label "inflate cycles (10): " -labelside left \
    -options "entry.textVariable inflateparms(inflatecycles)"
  tixLabelEntry $f.c -label "metric vs smooth (-dist=0.1): " -labelside left \
    -options "entry.textVariable inflateparms(metric2smooth)"
  tixLabelEntry $f.d -label "neighborhood size (-nbrs=2): " -labelside left \
    -options "entry.textVariable inflateparms(nbrs)"
  label $f.la2 -text "\nhi-res: nbrs up -> get more iters by incr rms height" \
    -bg $bgcol -font $ffont
  tixLabelEntry $f.e -label "smooth hi-res cycles (-n=25): " -labelside left \
    -options "entry.textVariable inflateparms(smoothhirescycles)"
  tixLabelEntry $f.f -label "inflate hi-res cycles (-n=50): " -labelside left \
    -options "entry.textVariable inflateparms(inflatehirescycles)"
  tixLabelEntry $f.g -label "inflate hi-res neigh (-nbrs=5): " -labelside left \
    -options "entry.textVariable inflateparms(nbrshires)"
  tixLabelEntry $f.h -label "write every x iter (0=end): " -labelside left \
    -options "entry.textVariable inflateparms(write_per_iters)"
  pack $f.la0 $f.la1 $f.a $f.b $f.c $f.d $f.la2 $f.e $f.f $f.g $f.h \
    -side top -padx 10 -pady 2

  ### inflatep (inflate patch w/tksurfer)
  set f [$nbwin subwidget inflatep]
  $f config -bg $bgcol
 label $f.la -text "Options for tksurfer area_shrink (inflate surf w/holes)\n" \
    -bg $bgcol -font $ffontb
  tixLabelEntry $f.a -label "steps per cycle (15): " -labelside left \
    -options "entry.textVariable inflateparms(tkstepspercycle)"
  tixLabelEntry $f.b -label "total cycles (tiffs) (100): " -labelside left \
    -options "entry.textVariable inflateparms(tkinflatecycles)"
  tixLabelEntry $f.c -label "dump tiff every cycle (0): " -labelside left \
    -options "entry.textVariable inflateparms(tktiffpercycleflag)"
  tixLabelEntry $f.d -label "weight tangential (\$ws=0.5): " -labelside left \
    -options "entry.textVariable inflateparms(ws)"
  tixLabelEntry $f.e -label "weight normal/curv (\$wn=0.5): " -labelside left \
    -options "entry.textVariable inflateparms(wn)"
  tixLabelEntry $f.f -label "weight logarearatio (\$wa=0.5): " -labelside left \
    -options "entry.textVariable inflateparms(wa)"
  tixLabelEntry $f.g -label "weight negar2norm (\$wc=0.0): " -labelside left \
    -options "entry.textVariable inflateparms(wc)"
  checkbutton $f.h -text "bord mv uses nonbord nei (\$bordneiflag, 0=radial) " \
    -variable inflateparms(bordneiflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $f.i -text "rm vtx w/no nonbord 2nd nei (\$rmvtx2nonbordflag) " \
    -variable inflateparms(rmvtx2nonbordflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  tixLabelEntry $f.j -label "weight radial bord (\$wt=0.5): " -labelside left\
    -options "entry.textVariable inflateparms(wt)"
  pack $f.la $f.a $f.b $f.c $f.d $f.e $f.f $f.g $f.h $f.i $f.j \
    -side top -padx 10 -pady 2
  # another call to Help -> Inflate Surface Patch (hi-res, holes)
  bind $f <ButtonRelease-3> { helpwin inflatepatchhires 50 $helpwinlines }

  ### final
  set f [$nbwin subwidget final]
  $f config -bg $bgcol
  label $f.la -text "mris_make_surfaces options" -bg $bgcol -font $ffontb
  pack $f.la -side top
  checkbutton $f.a -text "defunct selfintersect: old binary only (-graymid) " \
    -variable finalparms(selfintersect) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $f.b -text "omit selfintersection, gray/white only (-q) " \
    -variable finalparms(quickfinalflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $f.c -text "only make white matter surface (-whiteonly) " \
    -variable finalparms(whiteonlyflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $f.d -text "omit auto segmentation (-noaseg) " \
    -variable finalparms(noasegflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $f.e -text "omit auto parcellation (-noaparc) " \
    -variable finalparms(noaparcflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $f.f -text "omit auto statistics (-noauto) " \
    -variable finalparms(noautoflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  checkbutton $f.g -text "longitudinal (-long) " \
    -variable finalparms(longflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  tixLabelEntry $f.h -label "max thk (long.: -max 3.5): " -labelside left \
    -options "entry.textVariable finalparms(max)"
  pack $f.a $f.b $f.c $f.d $f.e $f.f $f.g $f.h \
    -side top -anchor w -padx 150 -pady 2
  label $f.i -bg $bgcol
  checkbutton $f.j -text "use tksurfer tcl script instead" \
    -variable finalparms(usescript) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  tixLabelEntry $f.k -label "tcl (rel: subj/scripts, else lib): " \
    -labelside left -options "entry.textVariable finalparms(tclscript)"
  button $f.l -text "VIEW TCL SCRIPT" -font $ffontb -pady 2 -padx 5 \
    -highlightbackground $bgcol -command \
    "helpwin $finalparms(tclscript) 50 50 $env(CSURF_DIR)/lib/tcl"
  pack $f.i $f.j $f.k $f.l -side top -padx 10 -pady 2

  ### flatten
  set f [$nbwin subwidget flatten]
  $f config -bg $bgcol

 tixLabelEntry $f.a -label "out to n-connected--full (7,13): " -labelside left \
    -options "entry.textVariable flattenparms(sampledist_mm_full)"
 tixLabelEntry $f.b -label "max neigh each dist--full (12): " -labelside left \
    -options "entry.textVariable flattenparms(vertices_per_full)"
 tixLabelEntry $f.c -label "out to n-connectd--sm (20,13): " -labelside left \
    -options "entry.textVariable flattenparms(sampledist_mm_patch)"
 tixLabelEntry $f.d -label "max neigh each dist--sm (12): " -labelside left \
    -options "entry.textVariable flattenparms(vertices_per_patch)"
 tixLabelEntry $f.e -label "write every x iter (0=end): " -labelside left \
    -options "entry.textVariable flattenparms(write_per_iters)"
  checkbutton $f.ck1 -text \
    "New (float) patch output format (unchecked=old/short*100)" -variable \
    flattenparms(writefloatpatchflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  pack $f.a $f.b $f.c $f.d $f.e $f.ck1 -side top -padx 10 -pady 2
  # another call to Help -> Flatten Surface
  bind $f <ButtonRelease-3> { helpwin flattensurface 50 $helpwinlines }

  ### sphere
  set f [$nbwin subwidget sphere]
  $f config -bg $bgcol
  tixLabelEntry $f.a -label "sample distance mm (##): " -labelside left \
    -options "entry.textVariable sphereparms(sampledist_mm)"
  tixLabelEntry $f.b -label "vertices each dist (##): " -labelside left \
    -options "entry.textVariable sphereparms(vertices_per)"
  tixLabelEntry $f.c -label "write every x iter (0=end): " -labelside left \
    -options "entry.textVariable sphereparms(write_per_iters)"
  tixLabelEntry $f.d -label "dist (0.1, 5.0) (geom: hi stiff): " \
    -labelside left -options "entry.textVariable sphereparms(dist)"
  tixLabelEntry $f.e -label "parea (0.2) (area: high stiff): " -labelside left \
    -options "entry.textVariable sphereparms(parea)"
  tixLabelEntry $f.f -label "corr (1.0) (sulcwei, low stiff): " \
    -labelside left -options "entry.textVariable sphereparms(corr)"
  tixLabelEntry $f.g -label "tolerance (10.0, 0.5): " -labelside left \
    -options "entry.textVariable sphereparms(tol)"
  tixLabelEntry $f.h -label "num avgs (256, 1024): " -labelside left \
    -options "entry.textVariable sphereparms(nav)"
  tixLabelEntry $f.i -label "touch up using curv (-curv): " -labelside left \
    -options "entry.textVariable sphereparms(sulcfirst)"
  frame $f.j -bg $bgcol
  label $f.j.la -text "morph target:" -bg $bgcol
  radiobutton $f.j.b -text "\$hemi.average.tif" \
     -variable sphereparms(morphtarg) -value average \
     -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
  radiobutton $f.j.c -text "\$hemi.average.curvature.filled.buckner40.tif" \
     -variable sphereparms(morphtarg) \
     -value average.curvature.filled.buckner40 \
     -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
  pack $f.a $f.b $f.c $f.d $f.e $f.f $f.g $f.h $f.i $f.j \
    -side top -padx 10 -pady 2
  pack $f.j.la $f.j.b $f.j.c -side left -padx 2 -pady 2
  # another call to Help -> Sphere/Register Surface
  bind $f <ButtonRelease-3> { helpwin spheresurface 50 $helpwinlines }

  ### position.tcl
  set f [$nbwin subwidget position]
  $f config -bg $bgcol
  # first label frame
  tixLabelFrame $f.la1 -label \
     "Init Viewing Pose: OCCIPITAL Flattening for \$hemi.occ*.patch.flat" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f.la1.border.pad config -bg $bgcol   ;# internal ugh
  $f.la1.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f1 [$f.la1 subwidget frame]
  $f1 config -bg $bgcol -bd 3
  frame $f1.a -bg $bgcol
  label $f1.a.a -text "  RH" -width 8 -bg $bgcol
  tixLabelEntry $f1.a.b -label "rotate: " -labelside left \
    -options "entry.textVariable postclparms(rh_occip_zrot)"
  tixLabelEntry $f1.a.c -label "scale: " -labelside left \
    -options "entry.textVariable postclparms(rh_occip_scale)"
  tixLabelEntry $f1.a.d -label "xmov: " -labelside left \
    -options "entry.textVariable postclparms(rh_occip_xtrans)"
  tixLabelEntry $f1.a.e -label "ymov: " -labelside left \
    -options "entry.textVariable postclparms(rh_occip_ytrans)"
  frame $f1.b -bg $bgcol
  label $f1.b.a -text "  LH" -width 8 -bg $bgcol
  tixLabelEntry $f1.b.b -label "rotate: " -labelside left \
    -options "entry.textVariable postclparms(lh_occip_zrot)"
  tixLabelEntry $f1.b.c -label "scale: " -labelside left \
    -options "entry.textVariable postclparms(lh_occip_scale)"
  tixLabelEntry $f1.b.d -label "xmov: " -labelside left \
    -options "entry.textVariable postclparms(lh_occip_xtrans)"
  tixLabelEntry $f1.b.e -label "ymov: " -labelside left \
    -options "entry.textVariable postclparms(lh_occip_ytrans)"
  foreach ent "$f1.a.b $f1.a.c $f1.a.d $f1.a.e \
               $f1.b.b $f1.b.c $f1.b.d $f1.b.e" {
    $ent subwidget label config -width 6
    $ent subwidget entry config -width 5
  }
  pack $f.la1 -side top
  pack $f1.a $f1.b -side top
  pack $f1.a.a $f1.a.b $f1.a.c $f1.a.d $f1.a.e -side left
  pack $f1.b.a $f1.b.b $f1.b.c $f1.b.d $f1.b.e -side left
  # second label frame
  tixLabelFrame $f.la2 -label \
   "Init Viewing Pose: FULL/CORTEX Flattening for \$hemi.\{full*,cortex*\}.patch.flat" \
    -labelside acrosstop -bg $bgcol -padx 10 \
    -options "label.padX 5 label.background $bgcol"
  $f.la2.border.pad config -bg $bgcol   ;# internal ugh
  $f.la2.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f2 [$f.la2 subwidget frame]
  $f2 config -bg $bgcol -bd 3
  frame $f2.a -bg $bgcol
  label $f2.a.a -text "  RH" -width 8 -bg $bgcol
  tixLabelEntry $f2.a.b -label "rotate: " -labelside left \
    -options "entry.textVariable postclparms(rh_full_zrot)"
  tixLabelEntry $f2.a.c -label "scale: " -labelside left \
    -options "entry.textVariable postclparms(rh_full_scale)"
  tixLabelEntry $f2.a.d -label "xmov: " -labelside left \
    -options "entry.textVariable postclparms(rh_full_xtrans)"
  tixLabelEntry $f2.a.e -label "ymov: " -labelside left \
    -options "entry.textVariable postclparms(rh_full_ytrans)"
  frame $f2.b -bg $bgcol
  label $f2.b.a -text "  LH" -width 8 -bg $bgcol
  tixLabelEntry $f2.b.b -label "rotate: " -labelside left \
    -options "entry.textVariable postclparms(lh_full_zrot)"
  tixLabelEntry $f2.b.c -label "scale: " -labelside left \
    -options "entry.textVariable postclparms(lh_full_scale)"
  tixLabelEntry $f2.b.d -label "xmov: " -labelside left \
    -options "entry.textVariable postclparms(lh_full_xtrans)"
  tixLabelEntry $f2.b.e -label "ymov: " -labelside left \
    -options "entry.textVariable postclparms(lh_full_ytrans)"
  foreach ent "$f2.a.b $f2.a.c $f2.a.d $f2.a.e \
               $f2.b.b $f2.b.c $f2.b.d $f2.b.e" {
    $ent subwidget label config -width 6
    $ent subwidget entry config -width 5
  }
  pack $f.la2 -side top
  pack $f2.a $f2.b -side top
  pack $f2.a.a $f2.a.b $f2.a.c $f2.a.d $f2.a.e -side left
  pack $f2.b.a $f2.b.b $f2.b.c $f2.b.d $f2.b.e -side left
  # extra data overlay parm stuck here
  label $f.la3 -text "\nStartup Viewing Options" -bg $bgcol
  checkbutton $f.ck1 -text \
    "Polar Inset Range: 360 deg (vs. 180) phase color rect" \
    -variable postclparms(fullpolrectflag) -bg $bgcol -selectcolor $selcol \
    -highlightbackground $bgcol
  pack $f.la3 $f.ck1 -side top
  # extra font parm also stuck here
  label $f.la4 -text \
    "\n(put non-default TrueType font into \$CSURF_DIR/lib/fonts)" \
    -bg $bgcol -font $ffont
  tixLabelEntry $f.e0 -label "fontfile: " -labelside left -options \
    "entry.textVariable postclparms(fontfile) label.width 7 entry.width 24"
  button $f.bu -text "Reset to default font (luxisb.ttf)" -font $ffont -pady 1 \
    -highlightbackground $bgcol -command "set postclparms(fontfile) luxisb.ttf"
  pack $f.la4 $f.e0 $f.bu -side top -pady 1

  ### lights
  set f [$nbwin subwidget lights]
  $f config -bg $bgcol
  tixLabelFrame $f.la -label \
     "Overlay Background and Brightness/Position Surface Lights (Vtx Coords)" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f.la.border.pad config -bg $bgcol   ;# internal ugh
  $f.la.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f1 [$f.la subwidget frame]
  $f1 config -bg $bgcol -bd 3
  pack $f.la -side top
  # offset, cvfact
  tixLabelFrame $f1.la0 -label \
"Overlay: Background Gray ------- Curvature Contrast" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f1.la0.border.pad config -bg $bgcol   ;# internal ugh
  $f1.la0.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f2 [$f1.la0 subwidget frame]
  $f2 config -bg $bgcol -bd 3
  tixLabelEntry $f2.b -label "offset (0.3):" -labelside left -options \
    "entry.textVariable lightparms(offset) label.width 20 entry.width 4"
  tixLabelEntry $f2.c -label "cvfact (0.0):" -labelside left -options \
    "entry.textVariable lightparms(cvfact) label.width 16 entry.width 4"
  pack $f1.la0 -side top
  pack $f2.b $f2.c -side left
  # light0
  tixLabelFrame $f1.la1 -label \
"Light 0 ------------------------------ position (default: from viewer)" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f1.la1.border.pad config -bg $bgcol   ;# internal ugh
  $f1.la1.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f2 [$f1.la1 subwidget frame]
  $f2 config -bg $bgcol -bd 3
  tixLabelEntry $f2.b -label "bright (0.4):" -labelside left -options \
    "entry.textVariable lightparms(light0) label.width 12 entry.width 4"
  tixLabelEntry $f2.c -label "x (0.0):" -labelside left -options \
    "entry.textVariable lightparms(light0x) label.width 12 entry.width 4"
  tixLabelEntry $f2.d -label "y (0.0):" -labelside left -options \
    "entry.textVariable lightparms(light0y) label.width 8 entry.width 4"
  tixLabelEntry $f2.e -label "z (1.0):" -labelside left -options \
    "entry.textVariable lightparms(light0z) label.width 8 entry.width 4"
  pack $f1.la1 -side top
  pack $f2.b $f2.c $f2.d $f2.e -side left
  # light1
  tixLabelFrame $f1.la2 -label \
"Light 1 ------------------------------ position (default: from behind brain)" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f1.la2.border.pad config -bg $bgcol   ;# internal ugh
  $f1.la2.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f2 [$f1.la2 subwidget frame]
  $f2 config -bg $bgcol -bd 3
  tixLabelEntry $f2.b -label "bright (0.0):" -labelside left -options \
    "entry.textVariable lightparms(light1) label.width 12 entry.width 4"
  tixLabelEntry $f2.c -label "x (0.0):" -labelside left -options \
    "entry.textVariable lightparms(light1x) label.width 12 entry.width 4"
  tixLabelEntry $f2.d -label "y (0.0):" -labelside left -options \
    "entry.textVariable lightparms(light1y) label.width 8 entry.width 4"
  tixLabelEntry $f2.e -label "z(-1.0):" -labelside left -options \
    "entry.textVariable lightparms(light1z) label.width 8 entry.width 4"
  pack $f1.la2 -side top
  pack $f2.b $f2.c $f2.d $f2.e -side left
  # light2
  tixLabelFrame $f1.la3 -label \
"Light 2 ------------------------------ position (default: from upper right)" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f1.la3.border.pad config -bg $bgcol   ;# internal ugh
  $f1.la3.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f2 [$f1.la3 subwidget frame]
  $f2 config -bg $bgcol -bd 3
  tixLabelEntry $f2.b -label "bright (0.8):" -labelside left -options \
    "entry.textVariable lightparms(light2) label.width 12 entry.width 4"
  tixLabelEntry $f2.c -label "x (0.6):" -labelside left -options \
    "entry.textVariable lightparms(light2x) label.width 12 entry.width 4"
  tixLabelEntry $f2.d -label "y (0.6):" -labelside left -options \
    "entry.textVariable lightparms(light2y) label.width 8 entry.width 4"
  tixLabelEntry $f2.e -label "z (1.6):" -labelside left -options \
    "entry.textVariable lightparms(light2z) label.width 8 entry.width 4"
  pack $f1.la3 -side top
  pack $f2.b $f2.c $f2.d $f2.e -side left
  # light3
  tixLabelFrame $f1.la4 -label \
"Light 3 ------------------------------ position (default: from direct left)" \
     -labelside acrosstop -bg $bgcol -padx 10 \
     -options "label.padX 5 label.background $bgcol"
  $f1.la4.border.pad config -bg $bgcol   ;# internal ugh
  $f1.la4.border config -relief groove -bd 2  ;# newpkgtix internal ugh
  set f2 [$f1.la4 subwidget frame]
  $f2 config -bg $bgcol -bd 3
  tixLabelEntry $f2.b -label "bright (0.2):" -labelside left -options \
    "entry.textVariable lightparms(light3) label.width 12 entry.width 4"
  tixLabelEntry $f2.c -label "x(-1.0):" -labelside left -options \
    "entry.textVariable lightparms(light3x) label.width 12 entry.width 4"
  tixLabelEntry $f2.d -label "y (0.0):" -labelside left -options \
    "entry.textVariable lightparms(light3y) label.width 8 entry.width 4"
  tixLabelEntry $f2.e -label "z (0.0):" -labelside left -options \
    "entry.textVariable lightparms(light3z) label.width 8 entry.width 4"
  pack $f1.la4 -side top
  pack $f2.b $f2.c $f2.d $f2.e -side left

  ### ok/save/cancel
  set box $w.bo
  tixButtonBox $box -bd 1 -relief raised -bg $bgcol
  pack $box -side top -fill both
  $box add ok -text "OK/Save" -highlightbackground $bgcol -command \
    "writearrayparms $datfile struct; mkpositiontcl; destroy $w" -width 10
  $box add save -text "Save" -highlightbackground $bgcol -command \
    "writearrayparms $datfile struct; mkpositiontcl" -width 10
  $box add cancel -text "Cancel" -highlightbackground $bgcol -command \
    "destroy $w" -width 10
  $box config -pady 20  ;# newpkgtix

  if {$foundoldpostcl} {
    tkwait visibility $box
    confirmalert "Posfile: old style position.tcl file in\n\
                  $env(SUBJECTS_DIR)/$name/scripts\n\
                  moved aside to position.tclOLD\n\n\
                  Verify old-to-new conversion in:\n\
                  Expert Preferences -> Views"
  }
}

### check before resetting all subject/session Expert Parms to defaults
proc resetparms { type } {
  global datfile
  set savecwd [pwd]
  set clearlists 0
  if {$type == "subject"} { cdsubjectscripts; set clearlists 0 }
  if {$type == "funct"}   { cdfunctscripts;   set clearlists 1 }
  if [okreplace $datfile "Move aside $datfile in [pwd]?" "Move Aside"] {
    mvlog $datfile $datfile~
    setdefaultarrays $clearlists
  } else {
    confirmalert "$datfile in [pwd] not altered\n\nCancel to avoid overwrite"
  }
  cdlog $savecwd
}

### tmp hidden debug stuff (obscure key binding only: Alt-numbersign)
proc hiddenprefs { } {
  global functdirstyle debugarrayparms
  global csurfconvalignflag
  set w .hiddenpopup
  if [winfo exists $w] { return }
  toplevel $w
  wm title $w "Debug Hacks\!"
  edlabval $w "functdirstyle" $functdirstyle n 15 12 col
  $w.functdirstyle.e config -textvariable functdirstyle
  checks $w "" "csurfconvalignflag" csurfconvalignflag col
  checks $w "" "csurfstripskullflag" csurfstripskullflag col
  checks $w "" "debugarrayparms" debugarrayparms col
}

### live split/unsplit Help menu for small/big screen
proc mkhelpmenus { } {
  global smallscreenflag helpwinlines
  global oldsubjtoolsflag newsubjtoolsflag mghsubjtoolsflag

  ### Help menu(s)
  if {$smallscreenflag} {
    set help0 H1
    set help1 H2
    menuhead $help0 left
  } else {
    set help0 Help
    set help1 Help
    menuhead $help0 right
  }
  menucmd $help0 "All Help Contents (clickable)" { mkhelpTOC }
  menucmd $help0 "Csurf" { helpwin csurf 50 $helpwinlines; wm title . \
    "$program[set ${program}_oldvers] (pid=[pid], csurf=$csurfsubversion, \
    tcl=$tclsubversion, tix=$tixsubversion, tardate=$tarfiledate)" }
    #previous: back to oldvers match csurf0.8: Sep2013
  menucmd $help0 "Retinotopy HOWTO" { helpwin HOWTO 50 $helpwinlines }
  menusepar $help0
  menucmd $help0 "New Subject" { helpwin makenewsubj 50 $helpwinlines }
  menucmd $help0 "Make Origdirs, Find Raw" {helpwin mkorigdirs 50 $helpwinlines}
  menucmd $help0 "Setup Structural Scans" {helpwin setupstruct 50 $helpwinlines}
  menucmd $help0 "Hand Pre-Normalize" {helpwin handnormalize 50 $helpwinlines}
  menucmd $help0 "Edit Segmentation" {helpwin editsegmentation 50 $helpwinlines}
  if {$oldsubjtoolsflag} {
    menusepar $help0
    menucmd $help0 "Process Volume" { helpwin processvolume 50 $helpwinlines }
    menucmd $help0 "Create Surface" { helpwin createsurface 50 $helpwinlines }
    menucmd $help0 "Fix Topology" { helpwin fixtopology 50 $helpwinlines }
    menucmd $help0 "Make Final Surface" { helpwin mkfinalsurf 50 $helpwinlines}
    #menucmd $help0 "Process/Create/Fix/Final" \
      { helpwin processcreatefixfinal 50 $helpwinlines } ;# leave out for space
  }
  if {$newsubjtoolsflag} {
    menusepar $help0
    menucmd $help0 "Strip Skull (hi-res)" \
      { helpwin stripskullhires 50 $helpwinlines }
    menucmd $help0 "Filter WM (hi-res)" {helpwin wmfilterhires 50 $helpwinlines}
    menucmd $help0 "Fill WM (hi-res)" { helpwin fillhires 50 $helpwinlines }
    menucmd $help0 "Create Orig Surface (hi-res)" {
      helpwin surfhires 50 $helpwinlines }
    menucmd $help0 "Smooth(Curv)/Inflate(Sulc) (hi-res)" {
      helpwin smoothcurvinflatesulchires 50 $helpwinlines }
    menucmd $help0 "Make Final Surfaces (hi-res)" {
      helpwin mkfinalsurfshires 50 $helpwinlines }
    menucmd $help0 "Inflate Surface Patch (hi-res, holes)" {
      helpwin inflatepatchhires 50 $helpwinlines }
  }
  if {$mghsubjtoolsflag} {
    menusepar $help0
    menucmd $help0 "Run recon-all" { helpwin reconall 50 $helpwinlines }
    menucmd $help0 "Smooth(Curv)/Inflate(Sulc)" {
      helpwin smoothcurvinflatesulc 50 $helpwinlines }
    menucmd $help0 "Make Final Surfaces" {
      helpwin mkfinalsurfs 50 $helpwinlines }
  }
  #menucmd $help0 "Backward/Forward Compat" { helpwin compat 50 $helpwinlines}
  menucmd $help0 "Make Relaxation Cuts  " {
    helpwin makerelaxationcuts 50 $helpwinlines }
  menucmd $help0 "Flatten Surface" { helpwin flattensurface 50 $helpwinlines }
  menucmd $help0 "Sphere/Register Surface" {
     helpwin spheresurface 50 $helpwinlines }
  
  ### divide Help menu into 2 for small screen (only works if flag set in code)
  if {$smallscreenflag} {
    menuhead $help1 left
  } else {
    menusepar $help1
  } 
  menucmd $help1 "tkmedit" { helpwin tkmedit 50 $helpwinlines }
  menucmd $help1 "tkregister" { helpwin tkregister 50 $helpwinlines }
  menucmd $help1 "tksurfer" { helpwin tksurfer 50 $helpwinlines }
  menusepar $help1
  menucmd $help1 "New Functional" { helpwin makenewfunct 50 $helpwinlines }
  menucmd $help1 "Make Scandirs, Find Raw" {helpwin mkscandirs 50 $helpwinlines}
  menucmd $help1 "Setup Align/Funct Scans" {helpwin setupfunct 50 $helpwinlines}
  menucmd $help1 "Combine 3D Raw Images" {helpwin setuprawavg 50 $helpwinlines }
  menucmd $help1 "Calc 3D Fourier Stats" { \
    helpwin setupfour 50 $helpwinlines std fourierflow.gif right } 
  menucmd $help1 "Calc 3D Rand Block Stats" {helpwin setuprand 50 $helpwinlines}
  menucmd $help1 "Combine 3D Phase Stats" {helpwin setupsigavg 50 $helpwinlines}
  menucmd $help1 "Combine Surface Stats" {helpwin setupsurfavg 50 $helpwinlines}
  menucmd $help1 "Calc Visual Fieldsign, Borders" \
      { helpwin setupfield 50 $helpwinlines }
  menucmd $help1 "Import 3D Stats" { helpwin setupimport 50 $helpwinlines }
  menusepar $help1
  menucmd $help1 "View Functional Data" { helpwin setuprender 50 $helpwinlines }
  menucmd $help1 "View All Scandirs" { helpwin viewscandirs 50 $helpwinlines }
  menucmd $help1 "Run Batch Process" { helpwin batch 50 $helpwinlines }
  menusepar $help1
  menucmd $help1 "New Spherical Avg" { helpwin makenewsphavg 50 $helpwinlines }
  menucmd $help1 "Cross Session Spherical Average" \
      { helpwin setupsphavg 50 $helpwinlines } ;# was ... Fourier Average
  menucmd $help1 "View SphereAvg Data" \
      { helpwin setuprendersphavg 50 $helpwinlines }
}

### read or write .csurfrc (Csurf.app only)
proc dotcsurfrc { action } {
  global env

  if {$action == "read"} {
    foreach na "SUBJECTS_DIR FUNCTIONALS_DIR FSURF_DIR CSURFEDITORVIGTERM" {
      if [info exists env($na)] { putlog "csurf: init $na = $env($na)" }
    }
    if ![file exists ~/.csurfrc] {
      putlog "csurf: no ~/.csurfrc"
      return
    }
    putlog "csurf: ### found ~/.csurfrc -- N.B.: overrides cshrc/bashrc/env"
    if [catch { open ~/.csurfrc r } ret] {
      putlog "csurf: can't open ~/.csurfrc for reading"
      return
    }
    set id $ret
    set lines [split [read -nonewline $id] "\n"]
    close $id
    foreach line $lines {
      if { [lindex $line 0] == "export" } {
        set s [lindex $line 1]
        foreach na "SUBJECTS_DIR FUNCTIONALS_DIR FSURF_DIR CSURFEDITORVIGTERM" {
          if [string match $na* $s] {
            set val [string range $s [expr [string first "=" $s] + 1] end]
            if [info exists env($na)] {  ;# only update if already exists
              set env($na) $val
              putlog "set env($na) $val"
            }
          }
        }
      }
    }
    putlog "csurf: ### to use cshrc/bashrc/env values instead, rm ~/.csurfrc"
  } 
  if {$action == "write"} {
    if [catch { open ~/.csurfrc w 0666 } ret] {  ;# try to blow away existing
      confirmalert "Can't open ~/.csurfrc for writing"
      return
    }
    set id $ret
    foreach na "SUBJECTS_DIR FUNCTIONALS_DIR FSURF_DIR" {
      if [info exists env($na)] { puts $id "export $na=$env($na)" }
    }
    if [info exists env(CSURFEDITORVIGTERM)] {
      puts $id "export CSURFEDITORVIGTERM=1"
    }
    close $id
    confirmalert "wrote new ~/.csurfrc:\n\n[exec cat [glob ~/.csurfrc]]"
  }
}

### live adj logsize
proc resizelogs { } {
  global loglines biglogflag cmdlog medlog surflog
  if {$biglogflag} { set hei 17 } else { set hei $loglines }
  foreach log "$cmdlog $medlog $surflog" { $log config -height $hei }
}

### live adj listbox size
proc adjlistboxforscreensize { } {
  global smallscreenflag subjectscombo sessionscombo

  if {$smallscreenflag} {
    $subjectscombo subwidget listbox config -height 15
    $sessionscombo subwidget listbox config -height 15
  } else {
    $subjectscombo subwidget listbox config -height 30
    $sessionscombo subwidget listbox config -height 30
  }
}

### live split/unsplit Help menu
proc adjhelpforscreensize { } {
  global smallscreenflag ;# Menu

  if {$smallscreenflag} {
    menurmlast Help
    mkhelpmenus
  } else {
    menurmlast H2  ;# req correct order
    menurmlast H1
    mkhelpmenus
  }
}

### table of contents window (global hfname array def'd here for edit ease)
proc mkhelpTOC { } {  ;# index for ~360 help panels
  global env menubg ffont ffontb hfname mac_appnap_hack bgcol cmdkey

  # interface labelname indexed by helpwin filename
  ##################################################################
  # hfname arrayindex=labelfilename   arrayvalue=helpinterfaceTextname
  # N.B.: rename helpfile to avoid rel arrayindex overlap from diff subdirs
  # N.B.: to dup heading name, mkhline just reuses filename (no dup arrayind)
  ### allhelp
  set hlines [lindex [exec wc -l $env(CSURF_DIR)/lib/help/all-help] 0]
  set hklines [expr $hlines/1000]K
  set hfname(all-help)     "All Help In One Panel ($hklines lines, $cmdkey-f)"

  ### csurf
  set hfname(csurf)        "Csurf (click any word, $cmdkey-f in panel)"
  # VOLUME
  set hfname(rc-VOLUME)    VOLUME
  set hfname(rc-volradio)  radio
  set hfname(rc-vol)       vol
  set hfname(rc-surfload)  loadT1
  set hfname(rc-surfload23) loadfillT2

  # SURFACE
  set hfname(rc-SURFACE)   SURFACE
  set hfname(rc-subjects)  subj
  set hfname(rc-surfaces)  surf
  set hfname(rc-hemi)      hemi
  set hfname(rc-patches)   patch
  set hfname(rc-surfradio)  radio
  # subj
  set hfname(reconall)     AutoRecon
  set hfname(makerelaxationcuts)  cuts
  set hfname(flattensurface)  flatten
  # subj2
  set hfname(makenewsubj)  HiRes
  set hfname(mkorigdirs)   import
  set hfname(setupstruct)  setup
  set hfname(handnormalize)  norm
  set hfname(editsegmentation)  editWM
  # subj3
  set hfname(makenewsubj)  HiRes
  set hfname(stripskullhires)  strip
  set hfname(wmfilterhires)  wm
  set hfname(fillhires)    fill
  set hfname(surfhires)    create
  set hfname(smoothcurvinflatesulchires)  inflate
  set hfname(mkfinalsurfhires)  final
  # sess
  set hfname(makenewfunct) Funct
  set hfname(mkscandirs)   import
  set hfname(setupfunct)   setup
  set hfname(setuprawavg)  avg
  set hfname(setupfour)    fourier
  set hfname(setuprender)  view
  # sess2
  #set hfname(makenewfunct) Funct  ;# dup
  set hfname(setuprand)     randblk
  set hfname(setupsigavg)   phavg
  set hfname(setupfield)    fieldsgn
  set hfname(setupimport)   impstat
  # sess3
  set hfname(viewscandirs) Allscans
  set hfname(batch)        batch
  set hfname(viewrgb)      bitmaps
  # sphericalavg
  set hfname(makenewsphavg) SphereAvg
  set hfname(setupsphavg)   setup
  set hfname(setuprendersphavg)  render
  set hfname(fsavg)         fsavg
  
  ### tksurfer
  set hfname(tksurfer)     TkSurfer
  # surf read
  set hfname(surf)         SurfRead
  set hfname(insurf_read)  R
  # surf write
  set hfname(outsurf)      SurfaceWrite
  set hfname(outsurf_write) W
  set hfname(outsurfasc_write) asc
  set hfname(outsurfvtk_write) vtk
  set hfname(outsurfoff_write) off
  set hfname(outsurfstl_write) stl
  set hfname(outsurfglb_write) glb 
  # vol
  set hfname(read_im)       ReadVol
  set hfname(direct_paint)  directpaint
  set hfname(read_im2)      im2
  set hfname(read_im3)      im3
  set hfname(read_im_label) sphim
  # tcl
  set hfname(script)       TclScript
  set hfname(script_run)   run
  set hfname(script_edit)  edit
  set hfname(script_record)  record
  # std scripts
  set hfname(script_offsetmovie)  offmv
  set hfname(script_phasemovie)  phmv
  set hfname(script_movie360)  360
  set hfname(script_inflatemovie) infl
  set hfname(script_flattenmovie) flat
  set hfname(script_explodemovie) expl
  # std scripts (cont)
  set hfname(script_annot2roi) annot2ROIs
  set hfname(script_searchlightdiff) searchlightdiff
  # curv
  set hfname(curv)         Curv/Sulc
  set hfname(curv_read)    R
  set hfname(curv_write)   W
  # area
  set hfname(area)         Area
  set hfname(area_lab)     state
  set hfname(area_read)    R
  set hfname(area_write)   W
  set hfname(area_disp)    D
  # patch
  set hfname(patch)        Patch
  set hfname(patch_read)   R
  set hfname(patch_write)  W
  set hfname(patch_mask)   M
  set hfname(patch_cut)    C
  # label
  set hfname(label)        Label
  set hfname(label_toggle) tick
  set hfname(label_read)   D
  set hfname(label_readcut) C
  set hfname(label_clear)  CLR
  set hfname(label_read2val) R
  set hfname(label_write)  W
  set hfname(label_timecourses) T
  set hfname(label_stat)   S
  set hfname(label_corr)   X
  # label (2)
  set hfname(annot)        annot
  set hfname(labelalpha)   tran
  set hfname(usecurr)      c2lab
  # LUT
  set hfname(val2rgb)      ColLookUpTab
  set hfname(val2rgb_edit) ED
  set hfname(val2rgb_read) R
  set hfname(val2rgb_write) W
  set hfname(intplut)      intp
  set hfname(botedge)      bot
  set hfname(zerosymm)     sym
  # fieldsign/gradients
  set hfname(fieldsign)    Fieldsgn/Gradient
  set hfname(fieldsign_read) R
  set hfname(fieldsign_write) W
  set hfname(comp_fs)      F
  set hfname(comp_grad)    GR
  set hfname(nonbinaryfs)  tick
  set hfname(fsslope)      ent
  # val
  set hfname(val)          ValVtxFile
  set hfname(val_lab)      state
  set hfname(val_read)     R
  set hfname(swapstatval)  S/V
  set hfname(val_clust)    CS
  set hfname(val_clear)    CLR
  set hfname(val_write)    W
  # val3d
  set hfname(statpatt)     Val3Dfile
  set hfname(val3d_read)   R
  set hfname(val3d_raw)    RD
  set hfname(val3d_paint)  PAINT
  set hfname(label_label)  parms
  set hfname(val3d_uniq)   UQ
  set hfname(val3d_vecs)   V
  # nsamp
  set hfname(nsamp_search)  NormSamp
  set hfname(nsamp_uniqvox) vox
  set hfname(nsamp_uniqvtx) vtx
  set hfname(nsamp_all)     all
  set hfname(nsamp_dfrac)   frac
  set hfname(nsamp_samevtx) same
  set hfname(nsamp_wmgmext) wm
  # nsamp2
  set hfname(nsamp_min)     NormSampMin
  set hfname(nsamp_max)     max
  set hfname(nsamp_fracmin) fmin
  set hfname(nsamp_fracmax) fmax
  set hfname(nsamp_step)    step
  set hfname(nsamp_op)      op
  # nsamp3 rare
  set hfname(nsamp_bok)     BokAdjust
  set hfname(nsamp_sul)     sul
  set hfname(nsamp_gyr)     gyr
  # surfclust
  set hfname(nsamp_pre)     SurfClustPre
  set hfname(nsamp_area)    area
  # rgb
  set hfname(rgb)          RgbBitmaps
  set hfname(tiffout)      tick
  set hfname(rgb_read)     R
  set hfname(rgb_write)    W
  set hfname(rgb_write2)   WNoRedraw
  # brain pose
  set hfname(brainpose)    Brainpose
  set hfname(yrot)         yrot
  set hfname(xrot)         xrot
  set hfname(zrot)         zrot
  set hfname(winxy)        win
  set hfname(xtrans)       x
  set hfname(ytrans)       y
  set hfname(scalepercent) zoom
  # contours
  set hfname(isocont)      IsoCont
  set hfname(selectdmax)   clo
  set hfname(dist)         eucli
  set hfname(dijk)         geodesi
  set hfname(saveview)     Save/Goto
  # redraw
  set hfname(redraw)       Redraw
  set hfname(restore)      restore
  set hfname(save_pnt)     SEND
  set hfname(goto_pnt)     GOTO
  set hfname(fliphemi)     Flip
  set hfname(hbutt)        hist
  # bgcol
  set hfname(curv_tick)    BgCurvCol
  set hfname(offset)       offset
  set hfname(cvfact)       contrast
  set hfname(insidesurffact) insurffact
  # lighting
  set hfname(lights)       Lights
  set hfname(blufact)      blufact
  # colscale
  set hfname(curv_bgcol)   ColScales
  set hfname(val_w1)       w1
  set hfname(val_w2)       w2
  set hfname(val_w3)       w3
  set hfname(val_w4)       w4
  set hfname(val_ht)       ht
  set hfname(val_bi)       bi
  set hfname(col1col2)     col1/2
  # colscale2
  #set hfname(curv_bgcol)  ColScales  ;# dup (mkhline just re-uses filename)
  set hfname(val_BRy)      BRy
  set hfname(val_BRw)      BRw
  set hfname(val_lt)       lt
  set hfname(val_lta)      lta
  set hfname(val_ltw)      ltw
  set hfname(val_fs)       fs
  set hfname(val_jt)       jet
  set hfname(val_vd)       vd
  # mesh, bar
  set hfname(mesh)         Mesh+Cols
  set hfname(meshr)        r
  set hfname(meshg)        g
  set hfname(meshb)        b
  set hfname(rect)         bar
  set hfname(cm2)          cm
  # scale limits
  set hfname(minstat)    ScaleLims
  set hfname(maxstat)      max
  set hfname(exptrans)     expEcc
  set hfname(nonintecc)  nonintEcc
  # overlay flags
  set hfname(complexval)   ComplexData
  set hfname(truncphase)   trunc
  set hfname(truncphasesoft) sft 
  set hfname(truncphasemin)  min
  set hfname(truncphasemax)  max
  set hfname(invphase)     invph
  # phasecontours
  set hfname(phcont)       PhaseCont
  set hfname(phcont_num)   num
  set hfname(phcont_width)  width
  set hfname(arrowscale)   arrowsc
  set hfname(arrownorm)    anorm
  # overlay limits
  set hfname(overlay)      Overlay
  set hfname(fthresh)      fthresh
  set hfname(fmid)         fmid
  set hfname(fslope)       fslope
  # mask limits
  set hfname(statmaskamp)  StatMask
  set hfname(sfthresh)     sfthresh
  set hfname(sfmid)        sfmid
  set hfname(sfslope)      sfslope
  # wheel
  set hfname(angle_cycles) ColorWheel  ;# TODO: new helpfile
  set hfname(angle_offset) offset
  set hfname(revphase)     reverse
  set hfname(ipsiyellowfact)  ipsi
  set hfname(fadef)        fade
  # cuts
  set hfname(cuts)         Cuts
  set hfname(cutregion)    area
  set hfname(erode)        erode
  set hfname(fill)         fill
  set hfname(cutplane)     plane
  set hfname(cutline)      line
  set hfname(undo)         undo
  # ROI
  set hfname(roi)          ROI
  set hfname(fill2num)     N
  set hfname(fillcrit)     criterion
  set hfname(fill2area)    A
  set hfname(fill2rad)     R
  set hfname(init)         initcuts
  set hfname(nocut)        allundo
  # smooth(1)
  set hfname(smooth)         Smooth      ;# dup'd 2 times in mkhline below
  set hfname(smooth_steps)   steps
  set hfname(smooth_curv)    curv
  set hfname(smooth_val)     val
  set hfname(smooth_sparse)  sparse
  set hfname(smooth_valonly) valonly
  # smooth(2)
  set hfname(smooth_cpxreal) cpxreal
  set hfname(smooth_stat)    stat
  set hfname(smooth_weight)  weight
  set hfname(smooth_grad)    grad
  # shrink
  set hfname(shrink)           SHRINK
  set hfname(shrink_steps)     steps
  set hfname(shrink_cyc)       cyc 
  # Parms(1)
  set hfname(shrink_parms)     "  parms"  ;# dup'd 9 times in mkhline below
  set hfname(shrink_ws)        ws
  set hfname(shrink_wn)        wn
  # Parms(2)
  set hfname(shrink_forcemode) forcemode
  set hfname(shrink_mstrength) mstrength
  set hfname(shrink_mslope)    mslope
  # Parms(3)
  set hfname(shrink_mmid)      mmid
  set hfname(shrink_adj)       FAT/THIN
  # Parms(4)
  set hfname(shrink_cthk)      cthk
  set hfname(shrink_graymid)   graymid
  set hfname(shrink_whitemid)  whitemid
  # Parms(5)
  set hfname(shrink_ckself)    ckself
  set hfname(shrink_clearself) CLR
  set hfname(shrink_writeself) W
  set hfname(shrink_selfd)     selfd
  # Parms(6)
  set hfname(shrink_ckfill)    ckfill
  set hfname(shrink_ckgr)      ckgr
  set hfname(shrink_ck3rd)     ck3rd
  # Parms(7)
  set hfname(shrink_areaflag)  areaflag
  set hfname(shrink_2dflag)    flag2d
  set hfname(shrink_wbn)       wbn
  set hfname(shrink_wa)        wa
  # Parms(8)
  set hfname(shrink_locklabel) locklabel
  set hfname(shrink_ncthr_ck)  ncflag
  set hfname(shrink_ncthr)     ncthresh
  # Parms(9)
  set hfname(shrink_update)    update
  set hfname(shrink_decay)     decay
  set hfname(shrink_momentum)  momentum
  # Parms(10)
  set hfname(shrink_expand)    expand
  set hfname(shrink_explode)   explode
  # morph
  set hfname(morph)        REG
  #set hfname(shrink_ws)   ws        ;# dup
  set hfname(morph_wcrv)   wcrv
  set hfname(morph_wsta)   wsta
  set hfname(morph_wcpx)   wcpx
  set hfname(morph_wcpx2)  wcpx2

  ### tkmedit
  set hfname(tkmedit)      TkMedit
  # plane
  set hfname(hbutt)        h
  set hfname(coronal)      CORONAL
  set hfname(sagittal)     SAGITTAL
  set hfname(horizontal)   HORIZON
  # contr/midpt
  set hfname(bwslope)      Contrast
  set hfname(bwmid)        brightness
  set hfname(linear)       linear
  set hfname(undoedit)     undoeditflag
  # 3D roi/labelmask/fill/fillrad
  set hfname(roi_ck)       3dROI
  set hfname(roi_ckmask)   labelmask
  set hfname(roi_fill)     fill
  set hfname(roi_rad)      fillrad
  # save
  set hfname(saveimg)      Save
  set hfname(talcoords)    Talairach
  set hfname(pixcoords)    Native
  set hfname(sendpnt)      SEND     ;# non-uniq hfilename OK
  set hfname(gotopnt)      GOTO     ;# non-uniq hfilename OK
  # edit/brush
  set hfname(brush)        EditBrush
  set hfname(inplane)      brush3d
  set hfname(all3)         1vs3views
  set hfname(all3zoom)     zoom
  # surface
  #set hfname(surf)        Surface  ;# non-uniq hfilename OK
  set hfname(surf_ck)      toggle
  set hfname(surf_read)    R
  set hfname(surf2col)     surf2
  set hfname(linewidth)    line
  set hfname(surfpaint)    surfpaint
  # im
  set hfname(imentry)      EditableImage
  set hfname(imread)       R
  set hfname(imwrite)      W
  # roin
  set hfname(roin)         NativeLabel
  set hfname(roin2up)      state
  set hfname(roin_read)    R
  # roiup
  set hfname(roiup)        UpSampLabel
  #set hfname(roin2up)     state  ;# dup
  set hfname(roiup_time)   T
  set hfname(roiup_write)  W
  set hfname(roiup_read)   R
  # valn
  set hfname(valn)         NativeVal
  set hfname(valn2up)      state
  set hfname(valn_read)    R
  # valup
  set hfname(valup)        UpSampVal
  #set hfname(valn2up)     state  ;# dup
  set hfname(valup_read)   R 
  set hfname(valup_write)  W
  set hfname(clear)        CLR
  # mskn
  set hfname(maskn)        NativeStatMask
  set hfname(maskn2up)     state
  set hfname(maskn_read)   R
  # mskup
  set hfname(maskup)       UpSampStatMask
  #set hfname(maskn2up)    state  ;# dup
  set hfname(maskup_read)  R 
  set hfname(maskup_write) W
  # rgb
  set hfname(rgb)          RgbBitmaps
  set hfname(tiffout)      tick
  #set hfname(rgb_write2)   WNoRedraw   ;# non-uniq hfilename OK
  set hfname(rgb_write)    W
  # trunc
  set hfname(wmtrunc)      Trunc
  set hfname(wmfilterstd)  planefilter
  set hfname(wmfiltergau)  planefilterGauss
  # overlay limits
  #set hfname(overlay)     Overlay  ;# non-uniq hfilename OK
  #set hfname(fthresh)     fthresh  ;# non-uniq hfilename OK
  #set hfname(fmid)        fmid     ;# non-uniq hfilename OK
  #set hfname(fslope)      fslope   ;# non-uniq hfilename OK
  # mask limits
  set hfname(mask_ck)      StatMask
  #set hfname(sfthresh)    sfthresh ;# non-uniq hfilename OK
  #set hfname(sfmid)       sfmid    ;# non-uniq hfilename OK
  #set hfname(sfslope)     sfslope  ;# non-uniq hfilename OK
  # im2/compare
  set hfname(compare)      Compare
  set hfname(im2label)     im2label
  set hfname(im2entry)     im2entry
  set hfname(im2read)      R
  set hfname(seglabel)     la
  # smooth
  set hfname(smoothstats)  Smooth
  set hfname(kernelsize)   kernelsize
  set hfname(fwhm)         fwhm
  set hfname(smoothmask)   smoothmask
  # colscales
  set hfname(colscale)     ColScales
  #set hfname(val_w1)      w1  ;# non-uniq hfilename OK
  #set hfname(val_ht)      ht  ;# non-uniq hfilename OK
  #set hfname(val_bi)      bi  ;# non-uniq hfilename OK
  #set hfname(val_BRy)     BRy ;# non-uniq hfilename OK
  #set hfname(val_BRw)     BRw ;# non-uniq hfilename OK
  #set hfname(val_lt)      lt  ;# non-uniq hfilename OK
  # lut
  #set hfname(val2rgb)       ColLookUpTable  ;# non-uniq hfilename OK
  #set hfname(val2rgb_edit)  ED  ;# non-uniq hfilename OK
  #set hfname(val2rgb_read)  R   ;# non-uniq hfilename OK
  #set hfname(val2rgb_write) W   ;# non-uniq hfilename OK
  #set hfname(intplut)       interpol  ;# non-uniq hfilename OK
  # trunc/truncphasemin/truncphasemax
  #set hfname(complexval)   ComplexData  ;# non-uniq hfilename OK
  #set hfname(truncphase)   trunc   ;# non-uniq hfilename O
  #set hfname(truncphasemin)  min   ;# non-uniq hfilename O
  #set hfname(truncphasemax)  max   ;# non-uniq hfilename O
  # anglecycles/angleoffset/fad/iy
  #set hfname(angle_cycles)   ColorWheel  ;# dup
  #set hfname(angle_offset)   offset  ;# non-uniq hfilename OK
  #set hfname(revphase)       reverse ;# non-uniq hfilename O
  #set hfname(ipsiyellowfact) ipsi    ;# non-uniq hfilename O
  #set hfname(fadef)          fade    ;# non-uniq hfilename O
  # tcl
  #set hfname(script)         TclScript ;# non-uniq hfilename OK
  #set hfname(script_run)     run       ;# non-uniq hfilename OK
  #set hfname(script_edit)    edit      ;# non-uniq hfilename OK
  #set hfname(script_record)  record    ;# non-uniq hfilename OK
  # man norm
  set hfname(test1)        ManualNorm
  set hfname(all)          apply
  set hfname(sphnorm)      sphnorm
  set hfname(imim2op)      im,im2op

  ### tkregister
  set hfname(tkregister)   TkRegister
  # compare
  #set hfname(compare)     Compare  ;# non-uniq hfilename
  set hfname(savereg)      save
  set hfname(target)       targ
  set hfname(moveable)     move
  set hfname(blinktime)    blink
  set hfname(round)        round
  # brightness
  set hfname(fmov)         MoveableBright
  set hfname(fsquash)      contr
  set hfname(fthresh2)     midpt
  set hfname(masktarg)     masktarg
  # mirror
  set hfname(sagmirr)      SagMirror
  set hfname(invertmov)    invert
  set hfname(blurmov)      blur
  #set hfname(sendpnt)     SEND     ;# non-uniq hfilename
  #set hfname(gotopnt)     GOTO     ;# non-uniq hfilename

  ### tkstrip
  set hfname(tkstrip)      TkStrip

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

  ### scrolled window
  set f .csurfonehelpTOC
  if [winfo exists $f] { raise $f; return }
  toplevel $f -bd 0
  tkwait visibility $f   ;# fix protocol + get yosemite hack xterm in front
  #wm resizable $f 0 1   ;# kills bind on expand/de-expand
  wm protocol $f WM_DELETE_WINDOW {
    destroy .csurfonehelpwin .csurfonehelpTOC .onefindpanel
    unset -nocomplain hname hlinecnt lasthlab
  }
  set geom +[winfo rootx .]+[expr [winfo rooty .]+170]
  wm geometry $f $geom
  set f [tixScrolledWindow $f.sw -scrollbar auto -width 259 -height 660]
  ##TODO: scrollwheel (also tried "bind TixSWindow","tixBind $f"; combobox OK?)
  #tixBind TixSWindow <MouseWheel> {%W yview scroll [expr {-(%D/120)*2}] units}
  #bind $f <MouseWheel> { %W yview scroll [expr {- (%D / 120) * 2}] units }
  #bind $f <Button-4,5> { %W yview scroll [expr {- (%D / 120) * 2}] units }
  wm title . "csurf help TOC"
  pack $f -side top -expand yes -fill both
  set w [$f subwidget window]
  $w config -bg $menubg

  ### horrible tmp hack gives 20x draw speedup if AppNap (Yosemite+ 5sec->250ms)
  if {$mac_appnap_hack} {
    set pid [exec xterm -geom 42x50${geom} -bg $bgcol -e bash --norc &]
  }

  ### last mkhline list arg are helpfile names (hfname array indices)

  ### allhelp
  set hdir $env(CSURF_DIR)/lib/help
  mkhline $f $w $hdir \
    "all-help"

  ### csurf
  set hdir $env(CSURF_DIR)/lib/help/csurf
  mkhline $f $w $hdir \
    "csurf"
  mkhline $f $w $hdir \
    "rc-VOLUME rc-volradio rc-vol rc-surfload rc-surfload23"
  mkhline $f $w $hdir \
    "rc-SURFACE rc-subjects rc-surfaces rc-hemi rc-patches rc-surfradio"
  mkhline $f $w $hdir \
    "reconall makerelaxationcuts flattensurface"
  mkhline $f $w $hdir \
    "makenewsubj mkorigdirs setupstruct handnormalize editsegmentation"
  mkhline $f $w $hdir \
    "makenewsubj stripskullhires wmfilterhires fillhires surfhires \
     smoothcurvinflatesulchires mkfinalsurfhires"
  mkhline $f $w $hdir \
    "makenewfunct mkscandirs setupfunct setuprawavg setupfour setuprender"
  mkhline $f $w $hdir \
    "makenewfunct setuprand setupsigavg setupfield setupimport"
  mkhline $f $w $hdir \
    "viewscandirs batch viewrgb"
  mkhline $f $w $hdir \
    "makenewsphavg setupsphavg setuprendersphavg fsavg"

  ### tksurfer
  set hdir $env(CSURF_DIR)/lib/help/csurf
  mkhline $f $w $hdir \
    "tksurfer"
  set hdir $env(CSURF_DIR)/lib/help/tksurfer
  mkhline $f $w $hdir \
    "surf insurf_read"
  mkhline $f $w $hdir \
    "outsurf outsurf_write outsurfasc_write outsurfvtk_write 
     outsurfoff_write outsurfstl_write outsurfglb_write"
  mkhline $f $w $hdir \
    "read_im direct_paint read_im2 read_im3 read_im_label"
  mkhline $f $w $hdir \
    "script script_run script_edit script_record"
  mkhline $f $w $hdir \
    "script script_offsetmovie script_phasemovie script_movie360
     script_inflatemovie script_flattenmovie script_explodemovie"
  mkhline $f $w $hdir \
    "script script_annot2roi script_searchlightdiff"
  mkhline $f $w $hdir \
    "curv curv_read curv_write"
  mkhline $f $w $hdir \
    "area area_lab area_read area_write area_disp"
  mkhline $f $w $hdir \
    "patch patch_read patch_write patch_mask patch_cut"
  mkhline $f $w $hdir \
    "label label_toggle label_read label_readcut label_clear \
     label_read2val label_write label_timecourses label_stat \
     label_corr"
  mkhline $f $w $hdir \
    "label annot labelalpha usecurr"
  mkhline $f $w $hdir \
    "val2rgb val2rgb_edit val2rgb_read val2rgb_write intplut botedge zerosymm"
  mkhline $f $w $hdir \
    "fieldsign fieldsign_read fieldsign_write comp_fs comp_grad \
     nonbinaryfs fsslope "
  mkhline $f $w $hdir \
    "val val_lab val_read swapstatval val_clust val_clear val_write"
  mkhline $f $w $hdir \
    "statpatt val_lab val3d_read val3d_raw val3d_paint val3d_uniq val3d_vecs"
  mkhline $f $w $hdir \
    "nsamp_search nsamp_uniqvox nsamp_uniqvtx nsamp_all nsamp_dfrac \
     nsamp_samevtx nsamp_wmgmext"
  mkhline $f $w $hdir \
    "nsamp_min nsamp_max nsamp_fracmin nsamp_fracmax nsamp_step nsamp_op"
  mkhline $f $w $hdir \
    "nsamp_bok nsamp_sul nsamp_gyr"
  mkhline $f $w $hdir \
    "nsamp_pre nsamp_area"
  mkhline $f $w $hdir \
    "rgb tiffout rgb_read rgb_write rgb_write2"
  mkhline $f $w $hdir \
    "brainpose yrot xrot zrot winxy xtrans ytrans scalepercent"
  mkhline $f $w $hdir \
    "isocont selectdmax dist dijk saveview"
  mkhline $f $w $hdir \
    "redraw restore save_pnt goto_pnt fliphemi hbutt"
  mkhline $f $w $hdir \
    "curv_tick offset cvfact insidesurffact"
  mkhline $f $w $hdir \
    "lights blufact"
  mkhline $f $w $hdir \
    "curv_bgcol val_w1 val_w2 val_w3 val_w4 val_ht val_bi col1col2"
  mkhline $f $w $hdir \
    "curv_bgcol val_BRy val_BRw val_lt val_lta val_ltw val_fs val_jt val_vd"
  mkhline $f $w $hdir \
    "mesh meshr meshg meshb rect cm2"
  mkhline $f $w $hdir \
    "minstat maxstat exptrans nonintecc"
  mkhline $f $w $hdir \
    "complexval truncphase truncphasesoft truncphasemin truncphasemax invphase"
  mkhline $f $w $hdir \
    "phcont phcont_num phcont_width arrowscale arrownorm"
  mkhline $f $w $hdir \
    "overlay fthresh fmid fslope"
  mkhline $f $w $hdir \
    "statmaskamp sfthresh sfmid sfslope"
  mkhline $f $w $hdir \
    "angle_cycles angle_offset revphase ipsiyellowfact fadef"
  mkhline $f $w $hdir \
    "cuts cutregion erode fill cutplane cutline undo"
  mkhline $f $w $hdir \
    "roi fill2num fillcrit fill2area fill2rad init nocut"
  mkhline $f $w $hdir \
    "smooth smooth_steps smooth_curv smooth_val smooth_sparse smooth_valonly"
  mkhline $f $w $hdir \
    "smooth smooth_cpxreal smooth_stat smooth_weight smooth_grad"
  mkhline $f $w $hdir \
    "shrink shrink_steps shrink_cyc"
  mkhline $f $w $hdir \
    "shrink_parms shrink_ws shrink_wn"
  mkhline $f $w $hdir \
    "shrink_parms shrink_forcemode shrink_mstrength shrink_mslope"
  mkhline $f $w $hdir \
    "shrink_parms shrink_mmid shrink_adj"
  mkhline $f $w $hdir \
    "shrink_parms shrink_cthk shrink_graymid shrink_whitemid"
  mkhline $f $w $hdir \
    "shrink_parms shrink_ckself shrink_clearself shrink_writeself shrink_selfd"
  mkhline $f $w $hdir \
    "shrink_parms shrink_ckfill shrink_ckgr shrink_ck3rd"
  mkhline $f $w $hdir \
    "shrink_parms shrink_areaflag shrink_2dflag shrink_wa shrink_wbn"
  mkhline $f $w $hdir \
    "shrink_parms shrink_locklabel shrink_ncthr_ck shrink_ncthr"
  mkhline $f $w $hdir \
    "shrink_parms shrink_update shrink_decay shrink_momentum"
  mkhline $f $w $hdir \
    "shrink_parms shrink_expand shrink_explode"
  mkhline $f $w $hdir \
    "morph shrink_ws morph_wcrv morph_wsta morph_wcpx morph_wcpx2"

  ### tkmedit
  set hdir $env(CSURF_DIR)/lib/help/csurf
  mkhline $f $w $hdir \
    "tkmedit"
  set hdir $env(CSURF_DIR)/lib/help/tkmedit
  mkhline $f $w $hdir \
    "hbutt coronal sagittal horizontal"
  mkhline $f $w $hdir \
    "saveimg talcoords pixcoords sendpnt gotopnt"
  mkhline $f $w $hdir \
    "brush inplane all3 all3zoom"
  mkhline $f $w $hdir \
    "bwslope bwmid linear undoedit"
  mkhline $f $w $hdir \
    "roi_ck roi_ckmask roi_fill roi_rad"
  mkhline $f $w $hdir \
    "surf surf_ck surf_read surf2col linewidth surfpaint"
  mkhline $f $w $hdir \
    "roin roin2up roin_read"
  mkhline $f $w $hdir \
    "roiup roin2up roiup_time roiup_write roiup_read"
  mkhline $f $w $hdir \
    "valn valn2up valn_read"
  mkhline $f $w $hdir \
    "valup valn2up valup_read valup_write clear"
  mkhline $f $w $hdir \
    "maskn maskn2up maskn_read"
  mkhline $f $w $hdir \
    "maskup maskn2up maskup_read maskup_write"
  mkhline $f $w $hdir \
    "rgb tiffout rgb_write2 rgb_write"
  mkhline $f $w $hdir \
    "imentry imread imwrite"
  mkhline $f $w $hdir \
    "wmtrunc wmfilterstd wmfiltergau"
  mkhline $f $w $hdir \
    "overlay fthresh fmid fslope"
  mkhline $f $w $hdir \
    "mask_ck sfthresh sfmid sfslope"
  mkhline $f $w $hdir \
    "compare im2label im2entry im2read seglabel"
  mkhline $f $w $hdir \
    "smoothstats kernelsize fwhm smoothmask"
  mkhline $f $w $hdir \
    "colscale val_w1 val_ht val_bi val_BRy val_BRw val_lt"
  mkhline $f $w $hdir \
    "val2rgb val2rgb_edit val2rgb_read val2rgb_write intplut"
  mkhline $f $w $hdir \
    "complexval truncphase truncphasemin truncphasemax"
  mkhline $f $w $hdir \
    "angle_cycles angle_offset revphase ipsiyellowfact fadef"
  mkhline $f $w $hdir \
    "script script_run script_edit script_record"
  mkhline $f $w $hdir \
    "test1 all sphnorm imim2op"

  ### tkregister
  set hdir $env(CSURF_DIR)/lib/help/csurf
  mkhline $f $w $hdir \
    "tkregister"
  set hdir $env(CSURF_DIR)/lib/help/tkregister
  mkhline $f $w $hdir \
    "compare savereg target moveable blinktime round"
  mkhline $f $w $hdir \
    "fmov fsquash fthresh2 masktarg"
  mkhline $f $w $hdir \
    "sagmirr invertmov blurmov sendpnt gotopnt"

  ### tkstrip
  set hdir $env(CSURF_DIR)/lib/help/csurf
  mkhline $f $w $hdir \
    "tkstrip"

  if {$mac_appnap_hack} { after 250 "exec kill $pid" }  ;# horrible tmp hack

  tkwait visibility $f   ;# so next viewonehelp geom query not stale
  pickonehelp $f $w.r1 $env(CSURF_DIR)/lib/help all-help
  #pickonehelp $f $w.r2 $env(CSURF_DIR)/lib/help/csurf csurf
}

### make/pack/bind one line of widgets (hlist: helpfilenames, not widgettexts)
proc mkhline { tocwin w helpdir hlist } {
  global hfname hlinecnt ffont menubg ifont

  if ![info exists hlinecnt] { set hlinecnt 0 }
  set r $w.r[incr hlinecnt]
  frame $r -bg $menubg
  pack $r -side top -anchor w
  set n 0
  foreach h $hlist {
    set font $ffont
    if { $h == "all-help" || $h == "csurf" || $h == "tksurfer" ||
         $h == "tkmedit" || $h == "tkregister" || $h == "tkstrip" } {
      set font $ifont
    }
    set t $hfname($h)
    if {$n == 0} {
      if { [llength $hlist] != 1 } { set t "  $t --" }
      set n 1
    }
    if { [string length $t] == 1 } {  ;# extra space for single letters
      label $r.$h -text $t -font $font -bg $menubg -pady 0 -padx 3
    } else {
      label $r.$h -text $t -font $font -bg $menubg -pady 0 -padx 2
    }
    pack $r.$h -anchor w -side left -pady 0
    bind $r.$h <ButtonRelease-1> "pickonehelp $tocwin $r $helpdir $h"
    incr n
  }
}

### pick helpfile, bold its button, unbold prev
proc pickonehelp { tocwin hrow helpdir helpfile } {
  global lasthlab lasthelpfile ffont ffontb ifont ifontb

  set hlab $hrow.$helpfile
  set font $ffontb
  foreach h "all-help csurf tksurfer tkmedit tkregister tkstrip" {
    if {$h == $helpfile} { set font $ifontb }
  }
  $hlab config -font $font
  if { [info exists lasthlab] && "$hlab" != "$lasthlab" } {
    set font $ffont
    foreach h "all-help csurf tksurfer tkmedit tkregister tkstrip" {
      if {$h == $lasthelpfile} { set font $ifont }
    }
    $lasthlab config -font $font
  }
  set lasthlab $hlab
  set lasthelpfile $helpfile
  viewonehelp $helpdir/$helpfile $tocwin
}

### single text helpwin to display all help
proc viewonehelp { helpfile tocwin } {
  global env ffont bgcol selbgcol find currtxtind xcmd

  set f .csurfonehelpwin
  if [catch {set id [open $helpfile]} ret] { return }
  if [winfo exists $f] {
    raise $f
  } else {
    toplevel $f -borderwidth 10
    wm resizable $f 0 1
    set winx [expr [winfo rootx $tocwin]+263]
    set winy [expr [winfo rooty $tocwin]-22]
    wm geometry $f +${winx}+${winy}
    frame $f.t
    # req'd -inactiveselectbackground else black (helpwin not needed?)
    # was -width 47 (vs. helpwin 50) but lots of wrap (to reduce useless white)
    text $f.t.txt -width 48 -height 45 -font $ffont \
      -borderwidth 3 -relief flat -setgrid true -selectbackground $selbgcol \
      -yscrollcommand "$f.t.scroll set" -highlightbackground black -bg white \
      -inactiveselectbackground $selbgcol -selectforeground black
    scrollbar $f.t.scroll -command "$f.t.txt yview" -highlightbackground $bgcol
    pack $f.t.scroll -side right -fill y
    pack $f.t.txt -side left -expand true -fill y
    pack $f.t -side top -expand true -fill y
    $f.t.txt config -state normal
    foreach win "$f $f.t.scroll" { $win config -bg $bgcol }
    bind $f <Return> "destroy $f"
    bind $f <Control-c> "destroy $f"
  }
  $f.t.txt delete @1,0 end         ;# delete all
  $f.t.txt insert end [read $id]   ;# insert new
  $f.t.txt yview moveto 0.0        ;# scroll to top
  wm title $f [file tail $helpfile]
  set currtxtind 1.0  ;# init search top
  set find ""         ;# init search patt
  bind $f.t.txt <$xcmd-f> "onefindpanel $f.t.txt"
  wm protocol $f WM_DELETE_WINDOW "destroy $f .onefindpanel"
  focus $f.t.txt
  $f.t.txt mark set insert 1.0
}

############################################################################
# place main csurf interface window, initialize configuration arrays
############################################################################
set csurfcnt 1
# catch so csurf source'able from wish8.5 prompt (grep -c err from no csurf)
if { [exec uname] == "Darwin" } {  ;# err to pipe for setuid/DYLD warning
  catch {set csurfcnt [exec ps uxww |& grep wish8.5 | grep -c csurf]} ;#BSD
} elseif { [exec uname] == "Linux" } {  ;# err to pipe for setuid/DYLD warning
  catch {set csurfcnt [exec ps uxww |& grep wish8.5 | grep -c csurf]} ;#Linux
} else {
  catch {set csurfcnt [exec ps af |& grep wish8.5 | grep -c csurf]}   ;#oldsys5
}
### place first, subsequent csurf's tile down/right
#wm geometry . +[expr 8 + 10*($csurfcnt-1)]+[expr 27 + 15*($csurfcnt-1)]
# mv right to clear Mac left dock
wm geometry . +[expr 45 + 10*($csurfcnt-1)]+[expr 27 + 15*($csurfcnt-1)]
wm protocol . WM_DELETE_WINDOW testclose

setdefaultarrays   ;# guarantees newest defaults exist: <xlist>(def,<parm>)

### horrible tmp hack gives 20x drawing speedup (Yosemite+ 5sec->250ms, AppNap?)
if {$mac_appnap_hack} {
  tkwait visibility .    ;# returns when just window, before widgets drawn
  set geom +[winfo rootx .]+[winfo rooty .]
  set pid [exec xterm -geom 100x11${geom} -bg $bgcol -e bash --norc &]
  after 1000 { exec kill $pid }
}

############################################################################
# main csurf window menus
############################################################################
menusetup .mbar

### File
menuhead File left
menucmd File "Update Subjects/Sessions" {
  set currname $name
  set currsess $session
  fixsubjects 0 0 0
  fixsessions 0 0 0
  set name $currname
  set session $currsess
  if {$name != $currname} {confirmalert "changed subject to match curr session"}
}
menusepar File
menucmd File "Open Subject" { choosesubjectdir }
menucmd File "Open Functional" { choosefunctdir }
menucmd File "Open SphereAvg" { choosefunctdir }
menusepar File
menucmd File "Open $notesfile (Subject)" { $subjectscombo invoke; editnotes }
menucmd File \
  "Open $notesfile (Functional)" { $sessionscombo invoke; editnotes }
menucmd File \
  "Open $notesfile (SphereAvg)" { $sessionscombo invoke; editnotes }
menusepar File

if {$oldsubjtoolsflag} {
  menucmd File "New Subject" \
    { mknewsubject; set newname $name; fixsubjects 0 0 0; set name $newname }
} else {
  menucmd File "New Subject (Manual Recon)" \
    { mknewsubject; set newname $name; fixsubjects 0 0 0; set name $newname }
}

menucmd File "New Functional" \
  { mknewfunct session; set newsess $session; fixsessions 0 0 0; \
    set session $newsess }
#menucmd File "New Functional (+ scan1)" \
#  { mknewfunct session 1; set newsess $session 1; fixsessions 0 0 0; \
#    set session $newsess }
menucmd File "New SphereAvg" \
  { mknewfunct sphavg; set newsess $session; fixsessions 0 0 0; \
    set session $newsess }
menusepar File
menucmd File "Copy Subject" { cpdir Subject }
menucmd File "Copy Functional" { cpdir Functional }
menucmd File "Copy SphereAvg" { cpdir Functional }
menusepar File
menucmd File "Terminal -> Subject Scripts" { openterm Subject }
menucmd File "Terminal -> Functional Scripts" { openterm Functional }
menusepar File
menucmd File "Quit" { testclose }

### SubjectTools (insert classic tools or just classic tools)
if {$oldsubjtoolsflag} {  ;# maybe insert reconditioned classic
  menuhead SubjectTools left
  menucmd SubjectTools "Make Origdirs, Find/Copy Raw" { setupscans mkorigdirs }
  menucmd SubjectTools "Setup Structural Scans" { setupscans struct }
  menusepar SubjectTools
  menucmd SubjectTools "Process Volume" { processvolume }
  menucmd SubjectTools "Edit Segmentation" { editsegmentationcmd }
  menucmd SubjectTools "Create Surface" { createsurface }
  menucmd SubjectTools "Create Surface (no fill)" { createsurfacenofill }
  menucmd SubjectTools "Fix Surface Topology" { fixtopology }
  menucmd SubjectTools "Make Final Surface" { mkfinalsurf }
  menusepar SubjectTools
  menucmd SubjectTools "Process/Create/Fix/Final" { processcreatefixfinal }
  menucmd SubjectTools "Process/Create" { processcreate }
  menucmd SubjectTools "Create/Fix/Final" { createfixfinal }
  menucmd SubjectTools "Fix/Final" { fixfinal }
  if {$newsubjtoolsflag} {
    menusepar SubjectTools
    menucmd SubjectTools "Strip Skull (hi-res)" { runtkstriphires }
    menucmd SubjectTools "Filter WM (hi-res)" { runwmfilterhires }
    menucmd SubjectTools "Fill WM (hi-res)" { runfillhires }
    menucmd SubjectTools "Create Orig Surface (hi-res)" { runsurfhires }
    menucmd SubjectTools "Smooth(Curv)/Inflate(Sulc) (hi-res)" { \
      mghsmoothinflatehires }
    # next was: Fill/Create/Smooth/Inflate
    menucmd SubjectTools "Re-Make Surf (Fill->Inflate) (hi-res)" { \
      fillcreatesmoothinflatehires }
    menucmd SubjectTools "Make Final Surfaces (hi-res)" { tksurfermkfinalsurf }
  }
  menusepar SubjectTools
  menucmd SubjectTools "Back Compat Curv/3d" { backcompatcurv3d }
  menucmd SubjectTools "Undo Back Compat Curv" { undobackcompatcurv }
  menucmd SubjectTools "Forward Compat 3d" { forwardcompat3d }
  menucmd SubjectTools "Undo Forward Compat 3d" { undoforwardcompat3d }
  menusepar SubjectTools
  menucmd SubjectTools "Make Full Surface Cuts" \
    {set editingsurface 1; set patchext $fullpatch.$begin3dext; editsurfacecmd}
  menucmd SubjectTools "Make Occip Surface Cuts  " \
   {set editingsurface 1;set patchext $partialpatch.$begin3dext;editsurfacecmd}
  menucmd SubjectTools "Flatten Surface Patch" { flatten }
  menucmd SubjectTools "Sphere/Register Surface" { spherereg } ;# sph+reg
  menusepar SubjectTools
  menucmd SubjectTools "View Saved Subj Bitmaps" { viewbitmaps subject }
  menucmd SubjectTools "Run Subj Mpeg Movie" { runmpeg subject }
} else {
  if {$newsubjtoolsflag} { ;# just setup and reconditioned classic
    menuhead SubjectTools left
    menucmd SubjectTools "Make Origdirs, Find/Copy Raw" {setupscans mkorigdirs}
    menucmd SubjectTools "Setup Structural Scans" { setupscans struct }
    menusepar SubjectTools
    menucmd SubjectTools "Strip Skull (hi-res)" { runtkstriphires }
    menucmd SubjectTools "Filter WM (hi-res)" { runwmfilterhires }
    menucmd SubjectTools "Edit Segmentation" { editsegmentationcmd }
    menucmd SubjectTools "Fill WM (hi-res)" { runfillhires }
    menucmd SubjectTools "Create Orig Surface (hi-res)" { runsurfhires }
    menucmd SubjectTools "Smooth(Curv)/Inflate(Sulc) (hi-res)" {
      mghsmoothinflatehires }
    # next was: Fill/Create/Smooth/Inflate
    menucmd SubjectTools "Re-Make Surf (Fill->Inflate) (hi-res)" {
      fillcreatesmoothinflatehires }
    menucmd SubjectTools "Make Final Surfaces (hi-res)" { tksurfermkfinalsurf }
    menucmd SubjectTools "Inflate Surface Patch (hi-res, holes)" {
      tksurferinflatepatch }
    menusepar SubjectTools
    menucmd SubjectTools "View Saved Subj Bitmaps" { viewbitmaps subject }
    menucmd SubjectTools "Run Subj Mpeg Movie" { runmpeg subject }
  }
}

### SubjectToolsMGH
if {$mghsubjtoolsflag} {
  menuhead MGHTools left
  menucmd MGHTools "Run recon-all" { setupreconall }
  menusepar MGHTools
  menucmd MGHTools "Smooth(Curv)/Inflate(Sulc)" { mghsmoothinflate }
  menucmd MGHTools "Make Final Surfaces" { mghmkfinalsurf }
  menucmd MGHTools "Make Full Surface Cuts" \
    {set editingsurface 1; set patchext $fullpatch.$begin3dext; editsurfacecmd}
  menucmd MGHTools "Make Occip Surface Cuts  " \
   {set editingsurface 1;set patchext $partialpatch.$begin3dext;editsurfacecmd}
  menucmd MGHTools "Flatten Surface Patch" { mghflatten }    ;# =flatten
  menucmd MGHTools "Sphere/Register Surface" { mghspherereg } ;# sph/register
#xxxxxxxx -- opphemi: unfinished
  menucmd MGHTools "Register Surface (to symm)" { mghregsymm } ;# lh/rh
  #if {!$oldsubjtoolsflag} {
  #  menusepar MGHTools
  #  menucmd MGHTools "Back Compat Curv/3d" { backcompatcurv3d }
  #  menucmd MGHTools "Undo Back Compat Curv" { undobackcompatcurv }
  #  menucmd MGHTools "Forward Compat 3d" { forwardcompat3d }
  #  menucmd MGHTools "Undo Forward Compat 3d" { undoforwardcompat3d }
  #}
}

### SessionTools
menuhead SessionTools left
menucmd SessionTools "Make Scandirs, Find/Copy Raw" { setupscans mkscandirs }
menucmd SessionTools "Setup Align/Funct Scans" { setupscans alignfunct }
menusepar SessionTools
menucmd SessionTools "Combine 3D Raw Images" { setupscans rawavg }
menucmd SessionTools "Calculate 3D Fourier Stats" { setupscans calcfour }
menucmd SessionTools "Calculate 3D Rand Block Stats" { setupscans calcrand }
menucmd SessionTools "Combine 3D Phase Stats" { setupscans sigavg }
menucmd SessionTools "Combine Surface Stats" { setupscans surfavg }
menucmd SessionTools "Calc Visual Fieldsign, Borders" { setupscans calcfield }
menucmd SessionTools "Import 3D Stats" { setupscans extstat }
menusepar SessionTools
menucmd SessionTools "View Functional Data" { setupscans render }
menucmd SessionTools "View All Scandirs" { viewallscandirs }
menucmd SessionTools "Run Batch Process" { runbatchstat }
menucmd SessionTools "View Saved Funct Bitmaps" { viewbitmaps }
menucmd SessionTools "Convert Funct Bitmaps to Mpeg " { convert2mpg }
menucmd SessionTools "Run Mpeg Movie" { runmpeg }

### CrossSessTools
if {$xsesstoolsflag} {
  menuhead CrossSessTools left
  menucmd CrossSessTools "Cross Sess SphereAvg" { setupsphavgcx }
#xxx -- TODO: paradigm file support (tmp: use above with "w" 'phasetype')
  #menucmd CrossSessTools "Cross Sess Fourier SphereAvg" { }   ;# better names?
  #menucmd CrossSessTools "Cross Sess RandomBlock SphereAvg" { }
  menusepar CrossSessTools
  menucmd CrossSessTools "View SphereAvg Data" { setupscans rendersphavg }
  menucmd CrossSessTools "Run Batch Process" { runbatchstat sphavgdir }
  menucmd CrossSessTools "View Saved Avg Bitmaps " { viewbitmaps }
  menucmd CrossSessTools "Convert Avg Bitmaps to Mpeg " { convert2mpg }
  menucmd CrossSessTools "Run Mpeg Movie" { runmpeg }
}

### Preferences
menuhead Preferences left
menucheck Preferences "View/Hide Logs" logflag \
  { if {$logflag} {showlogs} else {hidelogs} }
menucmd Preferences "Expert Preferences" { setupexpertparms }
menucheck Preferences "Don't Ask to Overwrite" force
menucmd Preferences "Clear Logs" { clearlogs }
menusepar Preferences
menucheck Preferences "Show Only Curr Subj Sessions  " matchsubject \
  { fixsessions 0 0 0 }
menucmd Preferences "Go To Startup Funct Sess Dir" \
  { set env(FUNCTIONALS_DIR) $initfspacedir }
menucmd Preferences "Set Subjects Directory" \
 {choosedir env(SUBJECTS_DIR) "Choose directory containing subjects:"}
menucmd Preferences "Set Funct Sessions Directory" \
 {choosedir env(FUNCTIONALS_DIR) "Choose directory containing funct. sessions:"}
# Csurf.app only: menu item to write ~/.csurfrc (since can't see env)
if [string match *Csurf.app/Contents/MacOS/csurf $env(CSURF_DIR)] {
  menucmd Preferences "Save Curr Subj/Sess Dirs For Startup" {dotcsurfrc write}
}
menucmd Preferences "Change Subj for Curr Session" { changenamefile }
menusepar Preferences
menucheck Preferences "Simple Rand Block Diffs" simplediffsflag
menucheck Preferences "Save Imgs as .tiff (else SGI .rgb)" tiffoutflag
menucheck Preferences "Surf: Black->Transpar (4bpp tiff!)" black2transparentflag
#menucheck Preferences "Full Directory Trees" fulldtree  ;# broken
menucheck Preferences "Small Screen (corners, no follow)" smallscreenflag \
  { adjlistboxforscreensize; adjhelpforscreensize }
menucheck Preferences "Double Buffer" doublebufferflag
menucheck Preferences "Minimal Z-Buffer (24->12-bit)" minglxdepthflag
menucheck Preferences "Bigger Logs" biglogflag { resizelogs }
menucheck Preferences "Newest Functional At Top" fnewtopflag \
  { fixsessions 0 0 0 }
if { [exec uname] == "Darwin" } {
  set appnapstateforced 1
  menucheck Preferences "Cover/Uncover Speedup Hack" mac_appnap_hack
}
menusepar Preferences
menucmd Preferences "Open csurf cmds-only logfile" { opencmdsonlyfile }
menucmd Preferences "Close csurf cmds-only logfile" { closecmdsonlyfile }
menucheck Preferences "Log tksurfer actions as tcl cmds" tksurferlogflag
menucheck Preferences "Log tkmedit actions as tcl cmds" tkmeditlogflag

### menu hotkeys
menuacceltxt File "Update Subjects/Sessions" <$cmdkey-u>
bind . <$xcmd-u> { \
  set currname $name; set currsess $session; \
  fixsubjects 0 0 0; fixsessions 0 0 0; \
  set name $currname; set session $currsess; menuflash File }

menuacceltxt SessionTools "View Saved Funct Bitmaps" <$cmdkey-b>
bind . <$xcmd-b> { viewbitmaps; menuflash SessionTools }

menuacceltxt SessionTools "View Functional Data" <$cmdkey-f>
bind . <$xcmd-f> { focus .; setupscans render; menuflash SessionTools }
;# undo select_session focus .

menuacceltxt CrossSessTools "View SphereAvg Data" <$cmdkey-F>
bind . <$xcmd-F> { focus .; setupscans rendersphavg; menuflash CrossSessTools }

menuacceltxt Preferences "View/Hide Logs" <$cmdkey-l>
bind . <$xcmd-l> { focus .; \
  if {$logflag} {set logflag 0; hidelogs} else {set logflag 1; showlogs}; \
  menuflash Preferences }

menuacceltxt  Preferences "Don't Ask to Overwrite" <$cmdkey-o>
bind . <$xcmd-o> { set force 1; menuflash Preferences } ;# ON only, no toggle

### Help menu(s) -- put in proc for live small screen adjust
mkhelpmenus

############################################################################
# main csurf window widget packing hierarchy (by indentation)
############################################################################
# main combo boxes
frame .main
pack .main -side top
  # structural column
  tixLabelFrame .main.left -label Structural: -labelside acrosstop \
    -options "label.padX 5"
  .main.left subwidget label config -font $tfont  ;# tix options bug
  pack .main.left -side left
    set tsub [.main.left subwidget frame]
    frame $tsub.left -borderwidth 1
    pack $tsub.left -side left
      frame $tsub.left.top
      pack $tsub.left.top -side top
      frame $tsub.left.bot
      pack $tsub.left.bot -side top
    frame $tsub.right -borderwidth 1
    pack $tsub.right -side left
      frame $tsub.right.top
      pack $tsub.right.top -side top
      frame $tsub.right.bot
      pack $tsub.right.bot -side top
  # functional column
  tixLabelFrame .main.right -label Functional: -labelside acrosstop \
    -options "label.padX 5"
  .main.right subwidget label config -font $tfont  ;# tix options bug
  pack .main.right -side left
    set tsub [.main.right subwidget frame]
    frame $tsub.both -borderwidth 1
    pack $tsub.both -side left
      frame $tsub.both.top
      pack $tsub.both.top -side top
      frame $tsub.both.bot
      pack $tsub.both.bot -side top

# command log
frame .cmd -borderwidth 2 -relief sunken
pack .cmd -side top
  frame .cmd.lg
  pack .cmd.lg -side top

# tkmedit controls, log
frame .med -borderwidth 2 -relief sunken
pack .med -side top
  frame .med.bu
  pack .med.bu -side top
  frame .med.lg
  pack .med.lg -side top

# tksurfer controls, log
frame .sur -borderwidth 2 -relief sunken
pack .sur -side top
  frame .sur.bu
  pack .sur.bu -side top
  frame .sur.lg
  pack .sur.lg -side top

############################################################################
# make widgets in main csurf interface window
############################################################################
configtixbookcbxent .main
### make structural (left two columns) widgets
set tsub [.main.left subwidget frame]

# subject combo (trace $env(SUBJECTS_DIR) => fixsubjects)
set f $tsub.left.top
tixComboBox $f.cbx -label "subject:" -dropdown true \
  -command cbx:select_subject -editable true -variable name -listwidth 208 \
  -options "label.width 7 listbox.height 30"  ;# listbox.width 25
$f.cbx subwidget entry config -width 13 -font $ffont  ;# tix options bug
pack $f.cbx -side top
bind [$f.cbx subwidget entry] <ButtonRelease-3> {
  helpwin rc-subjects 50 $helpwinlines
}
set subjectscombo $f.cbx

# surface combo (trace $name => fixsurfaces)
set f $tsub.left.bot
tixComboBox $f.cbx -label "surface:" -dropdown true \
  -command cbx:select_surface -editable true -variable surfext -listwidth 208 \
  -options "label.width 7 listbox.height 20"  ;# listbox.width 25
$f.cbx subwidget entry config -width 13 -font $ffont  ;# tix options bug
pack $f.cbx -side top
bind [$f.cbx subwidget entry] <ButtonRelease-3> {
  helpwin rc-surfaces 50 $helpwinlines
}
set surfacescombo $f.cbx

# hemi select buttons
set f $tsub.right.top
tixSelect $f.hem -allowzero false -radio true -label " hemi:" \
  -orientation horizontal -options "label.width 5"
$f.hem add rh  -text RIGHT -font $sfont -width 4 -bg $bgcol -padx 9 -pady 3 \
   -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
$f.hem add lh   -text LEFT -font $sfont -width 4 -bg $bgcol -padx 9 -pady 3 \
   -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
$f.hem add both -text BOTH -font $sfont -width 4 -bg $bgcol -padx 9 -pady 3 \
   -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
if { $mainrelease == "Fedora" } {  ;# hack for giant helv 14
  puts [$f.hem subwidget rh config -padx 7]
  puts [$f.hem subwidget lh config -padx 7]
  puts [$f.hem subwidget both config -padx 7]
}
$f.hem config -variable hemi
pack $f.hem -side top -anchor e
bind $f.hem.frame.rh <ButtonRelease-3> { helpwin rc-hemi 50 $helpwinlines }
bind $f.hem.frame.lh <ButtonRelease-3> { helpwin rc-hemi 50 $helpwinlines }
bind $f.hem.frame.both <ButtonRelease-3> { helpwin rc-hemi 50 $helpwinlines }
after 1200 "$f.hem config -command updatesurfaces"

# patch combo (trace $name => fixpatches)
set f $tsub.right.bot
tixComboBox $f.cbx -label "patch:" -dropdown true \
  -command cbx:select_patch -editable true -variable patchext -listwidth 208 \
  -listcmd cbx:listcmd_patch \
  -options "label.width 5 listbox.height 20"  ;# listbox.width 25
$f.cbx subwidget entry config -width 16 -font $ffont  ;# tix options bug
pack $f.cbx -side top
bind [$f.cbx subwidget entry] <ButtonRelease-3> {
  helpwin rc-patches 50 $helpwinlines
}
set patchescombo $f.cbx

### make functional (right column) widgets
set tsub [.main.right subwidget frame]

# session combo (trace $env(FUNCTIONALS_DIR) => fixsession)
set f $tsub.both.top
tixComboBox $f.cbx -label "session:" -dropdown true \
  -command cbx:select_session -editable true -variable session -listwidth 208 \
  -options "label.width 7 listbox.height 30"  ;# listbox.width 25
$f.cbx subwidget entry config -width 15 -font $ffont  ;# tix options bug 
pack $f.cbx -side top
bind [$f.cbx subwidget entry] <ButtonRelease-3> {
  helpwin rc-sessions 50 $helpwinlines
}
set sessionscombo $f.cbx

# scandir combo (trace $session => fixscandirs)
set f $tsub.both.bot
tixComboBox $f.cbx -label "scandir:" -dropdown true \
 -command cbx:select_scandir -editable true -variable iscandir -listwidth 208 \
 -options "label.width 7 listbox.height 18"  ;# listbox.width 25
$f.cbx subwidget entry config -width 15 -font $ffont  ;# tix options bug
pack $f.cbx -side top
bind [$f.cbx subwidget entry] <ButtonRelease-3> {
  helpwin rc-scandirs 50 $helpwinlines
}
set scandirscombo $f.cbx

# text widget for command log
set f .cmd.lg
set cmdlog [text $f.log -width $logwidth -height $loglines -borderwidth 2 \
  -relief sunken -font $ffont -selectbackground $selbgcol -setgrid true \
  -yscrollcommand {.cmd.lg.scroll set} -selectforeground black] ;#last:linux
scrollbar $f.scroll -command {.cmd.lg.log yview}
pack $f.scroll -side right -fill y
pack $f.log -side left -fill both -expand true

# VOLUME/tkmedit button
set f .med.bu
buttons $f "VOLUME" { tkmeditcmd } row 1 8
set medbu $f.aVOLUME.bu
$medbu config -width 7
bind $medbu <ButtonRelease-3> { helpwin rc-VOLUME 50 $helpwinlines }

# VOLUME button tkstrip overload (shift-mid: block accidental intended L-clk)
bind $f.aVOLUME.bu <Shift-ButtonRelease-2> { tkstripcmd }

# mritype radio buttons
set f .med.bu
radios $f "3D" "$origdir"    mritype $origdir    4 row
radios $f ""   "$t1dir"      mritype $t1dir      4 row
### addT2: new:rmPDbrain,ent:6-max (old:MRIent:8->6,VOLUME:7->6,checkpadx:4->0)
### addT2: update vollooklist
#radios $f ""   "$t2dir"          mritype $t2dir      4 row
radios $f ""   "$pddir"      mritype $pddir      4 row
radios $f ""   "$pdbraindir" mritype $pdbraindir 4 row
radios $f ""   "$braindir"   mritype $braindir   4 row
radios $f ""   "$wmdir"      mritype $wmdir      4 row
radios $f ""   "$filleddir"  mritype $filleddir  4 row
foreach ra $vollooklist {
  bind $f.a${ra}.ra <ButtonRelease-3> { helpwin rc-volradio 50 $helpwinlines }
}

## mritype bare entry (working)
#set f .med.bu
#entry $f.e -width 8 -textvariable mritype -bg $entbgcol \
#  -selectbackground $selbgcol
#bind $f.e <Return> { $medbu invoke }
#pack $f.e -side left -padx 2
#bind $f.e <ButtonRelease-3> { helpwin rc-vol 50 $helpwinlines }

## mritype combo
set f .med.bu
tixComboBox $f.cbx -dropdown true \
  -command cbx:select_mritype -editable true -variable mritype -listwidth 208 \
  -options "label.width 0 listbox.height 18" \
  -listcmd cbx:listcmd_mri  ;# listbox.width 25
$f.cbx subwidget entry config -width 6 -font $ffont -selectforeground black
$f.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
pack $f.cbx -side left -padx 0
bind [$f.cbx subwidget entry] <ButtonRelease-3> {
  helpwin rc-vol 50 $helpwinlines
}
bind [$f.cbx subwidget entry] <Return> { after 250 "$medbu invoke" }
set mritypescombo $f.cbx

# load MRI data button (load volume on click SURFACE)
set f .med.bu
checkbutton $f.ck0 -text "load2surf" -font $ffont -variable loadMRIflag \
  -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol ;# "load w/surf"
pack $f.ck0 -side left -padx 0  ;# (was padx 4) load this with SURFACE
bind $f.ck0 <ButtonRelease-3> { helpwin rc-surfload 50 $helpwinlines }

# text widget for tkmedit log
set f .med.lg
set medlog [text $f.log -width $logwidth -height $loglines -borderwidth 2 \
  -relief sunken -font $ffont -selectbackground $selbgcol -setgrid true \
  -yscrollcommand {.med.lg.scroll set} -selectforeground black] ;#last:linux
scrollbar $f.scroll -command {.med.lg.log yview}
pack $f.scroll -side right -fill y
pack $f.log -side left -fill both -expand true

# SURFACE/tksurfer button
set f .sur.bu
buttons $f "SURFACE" { tksurfercmd } row 1 8
set surfbu $f.aSURFACE.bu
$surfbu config -width 7
bind $surfbu <ButtonRelease-3> { helpwin rc-SURFACE 50 $helpwinlines }

# surface viewtype radio buttons
set f .sur.bu
radios $f "Hemisphere Surf" "folded"    viewtype folded    16 row
radios $f ""                "inflated"  viewtype inflated  16 row
radios $f ""                "viewcuts"  viewtype viewcuts  16 row
radios $f ""                "flattened" viewtype flattened 16 row
$f.afolded.ra   config -command radio2surfpatch
$f.ainflated.ra config -command radio2surfpatch
$f.aviewcuts.ra config -command radio2surfpatch
$f.aflattened.ra config -command radio2surfpatch
foreach ra { folded inflated viewcuts flattened } {
  bind $f.a${ra}.ra <ButtonRelease-3> { helpwin rc-surfradio 50 $helpwinlines }
}

# load MRI2 button (load aux volume on click SURFACE)
set f .sur.bu
frame $f.sp -width 4 -bg $bgcol
# orig name: "surfload2 (filled)"
checkbutton $f.ck0 -text "load2surf filled/T2" -variable loadMRIauxflag \
  -font $ffont -bg $bgcol -selectcolor $selcol -highlightbackground $bgcol
pack $f.sp $f.ck0 -side left
bind $f.ck0 <ButtonRelease-3> { helpwin rc-surfload23 50 $helpwinlines }

# lower right "h" help button, concatenated help (all-help) bindings
button $f.bu -text "h" -font $ffontb -pady 0 -padx 0 -command {
  helpwin csurf 50 $helpwinlines
}
pack $f.bu -side left -padx 0
bind $f.bu <ButtonRelease-2> {
  helpwin $env(CSURF_DIR)/lib/help/all-help 50 $helpwinlines
}
#bind . <$xcmd-H> {  ;# don't use: overlaps standard Mac binding
#  helpwin $env(CSURF_DIR)/lib/help/all-help 50 $helpwinlines
#}
bind $f.bu <ButtonRelease-3> { helpwin helpbutton 50 $helpwinlines }

# text widget for tksurfer log
set f .sur.lg
set surflog [text $f.log -width $logwidth -height $loglines -borderwidth 2 \
  -relief sunken -font $ffont -selectbackground $selbgcol -setgrid true \
  -yscrollcommand {.sur.lg.scroll set} -selectforeground black] ;#last:linux
scrollbar $f.scroll -command {.sur.lg.log yview}
pack $f.scroll -side right -fill y
pack $f.log -side left -fill both -expand true

# adj in case smallscreenflag set in code (vs. Help menu inits correctly below)
adjlistboxforscreensize

############################################################################
# all traces
############################################################################
#trace variable env(SUBJECTS_DIR) w fixsubjects  ;# saved example of old syntax
trace add variable env(SUBJECTS_DIR) write fixsubjects
trace add variable name write fixsurfaces
trace add variable name write fixpatches
trace add variable name write fixmritypes
trace add variable env(FUNCTIONALS_DIR) write fixsessions
trace add variable session write fixscandirs
trace add variable session write fixonesubject

#xxx -- HOWTO debug imagepatt weirdness w/trace
#set somepage ""  ;# misbehaving page
#proc debugimagepatt { } {
#  global functscanlists somepage
#  puts \
#  "############# functscanlists($somepage,imagepatt)=$functscanlists($somepage,imagepatt)
#}
#trace variable functscanlists($somepage,imagepatt) w debugimagepatt

############################################################################
# non-default bindings (see also: menu hotkeys)
############################################################################
### keys
bind all <$xcmd-numbersign> { hiddenprefs }

#tix crash w/Esc in main csurf window w/toplevel notebook -disabling combos
#bug:$CSURF_DIR/local/lib/tix4.1/ComboBox.tcl:tixComboBox:EscKey -> 8.4.3 fixed

### double-click subj/surf/sess/scan label raises subwindows in correct order
foreach wlab ".main.left.border.frame.left.top.cbx.label \
              .main.left.border.frame.left.bot.cbx.label \
              .main.right.border.frame.both.top.cbx.label \
              .main.right.border.frame.both.bot.cbx.label" {
  bind $wlab <Double-Button-1> { \
    if [winfo exists .setuppopup] { raise .setuppopup }; \
    if [winfo exists .sphavgdialog] { raise .setuppopup }; \
    if [winfo exists .selectdialog] { raise .selectdialog }; \
    if [winfo exists .progress] { raise .progress }; \
    if [winfo exists .help] { raise .help }; \
    if [winfo exists .okreplace] { raise .okreplace }; \
    if [winfo exists .confirm] { raise .confirm }; \
  }
}

############################################################################
# finish startup
###########################################################################
if {!$logflag} {hidelogs}
foreach win [info commands *.ra] {$win config -selectcolor $selcol} ;# undo
wm resizable . 0 0

### shrink popups (here: breaks older tixwish, before: breaks new pkg8.4.3)
tix resetoptions TixGray 12Point ;# newpkgtix: panel tixcmds need but bad above

### newpkgtix interface tweaks to make look like old
foreach mhead [info commands .mbar.*.me] {
  $mhead config -activeborderwidth 0    ;# make look like old (default=2)
}
.main.left config -bd 0
.main.right config -bd 0

### Csurf.app only: read ~/.csurfrc if exists/readable since can't see env
if [string match *Csurf.app/Contents/MacOS/csurf $env(CSURF_DIR)] {
  dotcsurfrc read    ;# N.B.: overrides cshrc/bashrc/env
}

### touch two main root vars so traces fill all combos, then unselect subj/sess
set env(SUBJECTS_DIR) $env(SUBJECTS_DIR)
set env(FUNCTIONALS_DIR) $env(FUNCTIONALS_DIR)
fixcolors
shrinkcomboarrows
update idletasks
set name __nobody__
set session __nosession__

### if csurf started in a scripts dir, change session or subject to its parent
if [string match *[file tail $env(FUNCTIONALS_DIR)]/*/image/scripts [pwd]] {
  set session [file tail [file dirname [file dirname [pwd]]]]
}
if [string match *[file tail $env(SUBJECTS_DIR)]/*/scripts [pwd]] {
  set name [file tail [file dirname [pwd]]]
}

### warn/help missing, give large subject/sessions dirs a chance to load
after 500 {
  set startupdone 1
  if {$notfoundbin != ""} {
    confirmalert \
      "Core binaries used by csurf not found in ${bindir}:\n\n$notfoundbin"
  }
  if {$notfoundafnibin != ""} {
    confirmalert \
  "AFNI binaries used by csurf not found in ${afnibindir}:\n\n$notfoundafnibin"
  }
  if {$notfoundafnilib != ""} {
    confirmalert \
      " These libs used if csurf calls AFNI not found:\n\n   \
        $notfoundafnilib\n\
        For Linux, try something like this:\n\n\
        \[HOWTO install libXm, e.g. version 4\]\n\
        su -\n\
        wget http://download.fedora.redhat.com/\n   \
        pub/fedora/linux/core/updates/5/x86_64/\n   \
        openmotif-2.3.0-0.1.9.3.i386.rpm\n\
        rpm -ihv openmotif-2.3.0-0.1.9.3.i386.rpm\n\
        \[installs libXm.so.4\]\n\n\
        \[HOWTO link to new lib if older AFNI:\]\n\
        su -\n\
        cd /usr/lib\n\
        ln -s libXm.so.4 libXm.so.3"
  }
  if {$notfoundmincbin != ""} {
    confirmalert \
  "MINC binaries used by csurf not found in ${mincbindir}:\n\n$notfoundmincbin"
  }
  if {$notfoundtcl != ""} {
    confirmalert \
      "tcl lib scripts used by csurf not found in ${tcldir}:\n\n$notfoundtcl"
  }
}

### title bar info (for large subjects/session load)
wm title . "loading subjects, sessions..."
after 600 { 
  wm title . \
    "$program[set ${program}_oldvers] (pid=[pid], csurf=$csurfsubversion, \
    tcl=$tclsubversion, tix=$tixsubversion, tardate=$tarfiledate)"
}

### eventually change to subject fsaverage (if not started from a scripts dir)
after 3000 {
  if {"$name" == "__nobody__" && [file exists $env(SUBJECTS_DIR)/$fsaverage]} {
    set name $fsaverage
  }
}

