#############################################################################
# tksurfer.tcl: UCSD/UCL/SDSU tksurfer user interface (tcl/tk) - Marty Sereno
#############################################################################
### recent changes
# catch GO (was RUN) script fail, errors to a confirmalert
# mini/macro only (no FRAME/SAVENUM), fix editor, redo dolighting, bakcompat
# bind rot/trans/scale/RESTORE/overlay-etc/READ-etc to redrawbutton (no motion)
# add fadef, ipsiyellowfact->ipsiyelfact, taller/wider sliders
# add vi in xterm, cm after MESH (rm colons), add colscalerectflag button
# interface angle{cycles,offset} to actual variable names angle_{cycles,offset}
# fullpolrectflag check in macro
# labelflag check to left of label entry, intercalated CLR label button
# RECONNECTALL -> NOCUTS (restore_ripflags 2) + INIT (same + re-read surf/curv)
# add BRy colscale, rearrange labels to fix (mini+macro)
# add truncphase limits, put ipsiyellowfact,fadef on one line above anglecycles
# expose cvfact,offset in mini next to curv radio (add cvfact to macro)
# changed tcl script defaults to brightphase, rm brightphase.tcl, curf support
# mini: add "bi" red/green complex colscale, fix C (wrappers: squish radios)
# mini: rm READENV, add entry to change surf (same hemi, bad: reload initial)
# if smallscreenflag exists, move tools window to lower left, turn follow off
# if exist, add stat{mult,repl}amp flags ("stat", "mul"), squish rev+inv
# add smooth_val_sparse (N.B.: no-op if full-rank data)
# save_rgb: pop GL window *after* response to testreplace popup
# scalebar limits entries {min,max}statcolscale report/set, squish ovlay+cmplx
# 40 right-click help panels written/updated
# add S/V button for swap_stat_val, bind Return to some READ/WRITE buttons
# multiple phasecontours controls in space left of fslope/fmid/cslope/cmid
# add nonbinary/fsslope controls left of fieldsign entry (default off)
# csurf now using mostly options: don't blow away colscale, default smooth->val
# if complexval data set, smooth val button now smooths both components
# rename: shift_values->swap_val_val2, swap_values->swap_valval2_valbakval2bak
# add tmp listing of available labels at R-click on "label" label
# add rawdata to setfile sessionfiles, 'setfile rawdata ...' in polar-views
# add regdat to setfile sessionfiles, 'setfile regdat ...' in polar-views
# tmp backcompat: trace write $dir, copy it to scname[],$scandir
# "W" button right of rgb WRITE doesn't redraw: saves cursor,timecourse
# "T" button to right of label WRT button: write_label_timecourses
# "T" button -command copies C:write_label_timecourses str manip using $scandir
# change READ label to DISP label (since DISP/WRT not like other READ/WRITE's)
# flat->reread: reset pose, flat->3D:reset pose, leave cuts, 3D->3D:leave pose
# can't save cuts 3D->flat, restore runs position.tcl/redoes pose for 3D->flat
# popup when "T" button finishes w/name of label, rawtimecourse,uniq outfiles
# F3: add col{r,g,b}{1,2} for bi scale color control underneath colscale switch
# "R" label button: clear_values, read label (real/complex) to val(2), fix help
# INIT->NOCUT NOCUTS->INIT, "FILL ROI"-> ROI, fix helps
# add NUM+entry + tcl-only var, $nclosestvertices, for fill_n_nearest_vertices
# rm clear_values from label R (label->val), val:addCLR/READ->R/WRITE->W, help
# add DIST button for calculating Euclidean distances
# add RC button to label: read label to val (like R), but also recut label
# R-click on "tcl:" displays/describes standard scripts
# add c2lab check on patch line to control usecurrcoordsflag (label write only)
# ROI butt: now eroding val (cplx:val/val2 amp) compared to thresh (was stat)
# nmarked exported to tcl, currently only used in roibutton
# cram label transparency control onto curv line, fix background extra entries
# setfile sessionfiles finally uses $scandir (left case: subdir='.')
# fix:csurf->tksurfed->csurfkill->csurf->killed->killstksurfer: >& /dev/null & 
# fixcolscale add real/complexamp color LUT update
# cram color LUT entry+ED(mkdef) + RD in front of squished fs line, lt (BRw->BR)
# fix runaway transform from quick clicks in trough with redrawbutton delay
# change to complex: reset colorlut to complex amp; change back: back to real
# interpolatelutflag, isocontourflag checkbuttons, fix editfile viterm for 10.6
# add write_val2rgblut W button
# changed C variable name $ext->$surfext (need trace here for old tksurfer2000)
# stat/repl -> mask (statreplampflag now hidden), block if stat not loaded
# add hardstatfthreshflag checkbutton, repl/mask/mult back all visible
# add cmplx col LUT for pha, make (re)def vs amp (AMP_TO_COLORLUT script-only)
# fix label string processing to be like tksurfer write_label_timecourses
# fix which/editor once again (new /usr/bin/which empty return on missing)
# winxy entry to resize GL window to known pixel size, ms->mask,ml->mul rm rp
# unlabeled tiff/rgb check on rgb line, resets current suff
# gettseries: warn missing lab/reg/rawdata before write_label_timecourses C-fail
# add SMOOTH "w" (smooth_val_weighted), vsp->sp,curv->cv (complex OK except cv)
# fix insurf/outsurf in F3 panel
# val: "R" button now auto-reads/pushes if complex data (_r,_i or _x,_y)
# val: "W" button now auto-writes if complex data (_r,_i or _x,_y), lab->label
# harmonize/Mac-ize/usage key bindings
# add Alt/Cmd-u,U (next to i,I) for raw fourier amp (TODO: tksurfer.c)
# major rearrange/update/squish SHRINK panel, new names, rm bott line of butts
# add forcemode, chkselfintersect and CLR/W, chkfilled, explode
# warn stale self intersect buffer
# macro: 3 read 3D images (inim{1,2,3},read_images[2,3]) below insurf/outsurf
# pack decimated onto dipole line to save space, 
# add chkthirdflag to shri:ck3 (rm broken NormArea for now), SHRINK butt counts
# squish momentum->mo, put on same line w/decay->dec, update->upd
# add T2 hi/lo entries ("ck3:lo" "ck3:hi") below ckhthirdflag
# add ckgrad (rm shri:'s, area->ar for space), add selfd ($selfstilt)
# make shrink button, purple/killable, fix cmdline macro interface size opt
# add erodingfillflag checkbutton (can also use ROI button w/low fthresh)
# rm untested bakcompat (GOTO tksurfer26k.tcl or older, if needed)
# rm hardstatfthreshflag, statmaskampflag toggles visibil s{fthresh/fmid/fslope}
# help panels for sfthresh/sfmid/sfslope (N.B.: scalebar is unmasked amplitude)
# dup revphaseflag left of angle_offset (cf render panel) (left orig for now)
# clk {surf,tcl,curv,patch,label,lut,fs,val,rgb}: (wrappers.tcl:text in var OK)
# abandon above for all except rgb
# surf combo: load w/standard list (others OK to type in)
# tcl combo: load startup/std/funct/subj, add hack separators 
# label combo: load $hemi*.label, separators for MGH vs. UCSD/UCL labels
# val combo: load *-$hemi.w (should include statmask)
# rm original, now duplicated revphaseflag button
# ROI now also does stat=sfthresh if "mask" clicked (overrides complexamp fill)
# add -selectforeground to *.e? entries not caught by fixcolors for linux
# combotest: 2 extra pix vertically per combo, one combo click disable fn-F2,3
# combotest: cbx replacements recreated localized (TODO: curv/patch/lut)
# combotest: rm tmp show routines bound to right-click entries
# add bindings for adjust fslope, angle_offset, angle_cycles
# hack read binary patch entry command to update stale hack patchname...
# GO/EDIT ignored tcl script dividers pseudo script entries
# add curv combo box (diff logic than select_surf, fix Mac tap doubling)
# surf/curv/val: warn read non-existent (3 diff logics!)
# label ignores dividers, too, notdivider procedure also for for scripts
# adj cslope (contrast) for curv vs. sulc
# add patch combo, transform 3d using flat (no 3d in position.tcl)
# fix bug introduced 10 back: write_binary_curv -> write_binary_patch
# add area field/combo for rh.area, rh.area.mid, rh.area.pial
# nclosestvertices -> num_sqmm_mm, for generalized fill_nearest_
# NUM->N, add A (area), space to group, add to F3 panel (omit INIT and NOCUT)
# add R for nearest up to radius; NOCUT->ALL
# rm show*file procs (now replaced by combo dropdowns), leave no-combo rgb
# add lut combo, mk surf combo dropdown patt-match at end: for smoothwm2, etc
# mv new {surf/tcl,curv/area,patch,label,lut/fs,val} up
# localize all help bindings, rm combotest, dup edlabvals
# warn original area overwrite
# middle-click "W" label button for label_to_vtxcol_label
# middle-click "R" label button for read_draw_vtxcol_label
# testreplace vtxcols has to imitate label_to_vtxcol filename create
# change middle-click "R" to read_vtxcol_label, add a redraw
# middle-click labelflag button toggles vtxcolflag, rm readdrawvtxcols
# fix bug in load scripts into scripts combo, add setfile vclabel
# middle-click label CLR button clears vtxcols
# bind draw light/blufact, let curv read 2x for reread same (e.g. after smooth)
# fix showrgbs popup to show every .rgb, .tiff, tell default format
# ask to create rgb dir in save_rgb_first if missing
# promote save_rgb_checkfirst, delete dolighting tksurfer2000 bakcompat
# fix revphaseflag help binding
# fix accept-surf-with-suff bug that was removing $hemi.sphere
# if read MGH label and complexflag, ask reset display (cpx,colscale,fmid,etc)
# overload smoothsteps: "valholes" or "valueholes" -> fill_val_holes
# overload smoothsteps: "annotholes" or "labelholes" -> fill_annot_holes
# also look for *.lut in scripts dir, divider, check for divider
# overload swap stat/val with swap complex stack if middle-click
# ask autocreate missing functdir rgbdir (was just check subjectsdir rgbdir)
# ask autocreate missing subjdir labeldir
# glob statpatt/statpatt_m, rect<->disk on button
# write_label_timecourses_stats arg now passed to arg-capable testreplace
# toggle val<->val3d like tkmedit, autoread real/cplx 3d stats
# add PNT (check/autoread regdat, paint), CLU buttons (run surf_clust)
# use default normd search til controls
# fix SMOOTH button bug: smoothing real component twice (!)
# 5 new help bindings for val3d entry line
# also load _???.bfloats into val3d
# generate printf format from selected example for read_native_stats stattpatt
# add S button (stat+timecourse), overload middle click S -> just stat
# add right-click controls pop-up for normd samp parms (fix wrappers controls)
# add cluster parms to live run_surfclust to "NormSamp, Cluster Controls"
# add alt-shift-arrow translate brain help/keybindings
# bind Mod-k to toggle bigcursorflag, also show full{0,1,2}, occip{0,2,1}
# patchcombo: match $hemi.$type*.patch.$suff*, curvcombo: match $hemi.$type*
# 3-toggle inset: disk (butt="rect") -> rect (butt="off") -> off (butt="disk")
# patch: set preferred existing (overrides patchname! setfile patch not bound)
# make select_patch act like csurf viewcuts on read 3d
# tixcombo -variable {curv,patch,area}abbrev so setfile {curv,ptch,area} updates
# N.B.: prev means setfile mk abbrev trigs select_{curv.patch,area} callback
# setfile {patch,curv,area} blocks callbacks to select_{curv.patch,area}
# manually block {patch,curv,area} config -value callback (even w/disabled!)
# block harmless callback to redraw before GL window made
# add missing global abbrev's in procs for val/label/insurf/fs/fm
# shift-middle-click double-overloads label W: write DSP'd vtx .vals to label
# read_label_to_val (label "R") now does fix_nonzero_vals (for sparse)
# labelalpha Return: reset alpha all curr displayed annot (DSP now uses entry)
# bold "area:" label swaps with "area2" for read_binary_areas2
# rm unnecessary back slashes in curly brace -command args and cmd logic
# calcdisp_arat bound to middle-click "area:" label
# also load area files into curv dropdown, select_curv more autoset cmid/cslope
# help: new:area_lab, update:area,area_read
# add bokflag, sulfrac, gyrfrac to "NormSamp, Clust Controls" popup
# click "tcl:" toggles enable/disable tksurferlogflag
# tksurferlogflag: log tcl cmds for every interface action to tksurfer.log (!)
# logcmd: setfile,{r,w}{vc,val,stat,surf},paint,smooth,roi,shrink
# => put logcmd *inside* only setfile/testreplace/redrawbutton/restore
# rm xhost+ req send inter-process tcl cmd and findsendto from SEND PNT
# [tksurfer.c: added mechanism of recording left_click wincoords clicks to log]
# rm foundbywhich, canwriteormake (now in wrappers.tcl)
# floss fieldsign tk, fixcolscale: fix fieldsignflag, report (changed) flags
# *don't* expose roundregflag in tksurfer.tcl (exported just for checking)
# bold "tcl:" if clicked to save tcl cmds to tksurfer.log, start too
# add "cortex" to patch look list for fsaverage
# also load .mgh files to "val:" dropdown
# F3 MATLAB jet "jt" colscale, scale ends by overload truncphasemin/max
# follow tksurfer.c export rename: $session -> $isession (includes "image")
# rm unused proc setsession
# DSP->D, add C butt: C is like DSP, but also re-cuts label to get overlap
# update to F2/F3 interface window positions to match new startup GLX winpos
# mini,macro wm geometry use new-exported glxwin{x,y,w,h} to avoid explicit pix
# popup reports filled_{curr,orig}area area for FILL/ROI/N/A/R
# warn fthresh>fmid on fthresh/fmid Return w/BRy
# bind Shift-R-click-RESTORE to re-center surface (recalc_surface_center)
# add rgb combo, liveload dropdown for chk/overwrite/modexist (-listcmd HOWTO)
# add "R" button to display bitmap, WRITE->W, W->WN
# bug: forgot shift in bind shift-middle-click label "W" write_labeled_vertices
# rm last read_label_to_annot_using_col arg: cutlabelflag
# change "C" click to read_label_cut_clearvals 0 (label)
# mid-clk overload "C" to read_label_cut_clearvals 1 (hole) for wfile edit
# "label:" combo includes label files from current scandir
# "val" smoothtype now also smooths stat if statloaded+maskflag
# new "vo" smoothtype: smooth val or val/val2 but *not* stat mask
# rarely used "vo" (valonly) smoothtype only on F3 panel
### ---- csurfsrc-140624.tgz ----
# sort patch,surf dropdowns at end
# warn vertices beyond flag border edge estimated
# add locklabelflag (shrink only unlabeled) to F3 shrink panel
# click FILL w/no vertex warns/reports previous FILL/ROI/N/A/R sum
### ---- csurfsrc-140710.tgz ----
# bind cmd-F killfillflag
# overload "D" button with read_label_to_undo_cut
# re-expose normalize_area function on F3 interface
# add "D" button to "area:" line for display distortion w/curr2orig area ratio
# change middle-click overload of area label to middle-click overload of "D"
# "D" area operations reinstate curr surf area (.area) w/compute_normals_areas
# unset overlayflag, calc area ratios: force redo autocolorscale (for curv)
# init/change scalebar control button "disk"->"bar" real-valued or no overlay
# complex/overlay/fixcolscale update bar/disk button only colscalebar=OFF state
# turn scalebar on automatically when displaying area ratios
# expose logtransflag (for ecc inset) as "exp" chk on F3 interface
# expose noninteccendiskflag (for ecc inset) as "ecp" chk on F3 interface
# add w3 colscale to F3 interface, move jet up to make room
# add lib dir luts to lut dropdown
### ---- csurfsrc-141018.tgz ----
# checklabeldir: warn missing label subdir in session dir
# fix introduced bug in checklabeldir, rename to checkwritelabeldir
# add check{read,write}labeldir return val, use to warn/block read/write label
# add "M" (mask) button for read_binary_patch_to_mask, READ,WRITE=>R,W
# add "C" (cut) button for read_binary_patch_to_cut 
# RESTORE *.3d no longer rotates like flat patch
# read patch (select_patch) no longer does viewcut-like 180 rot
# remove defunct "2d Vectors" line from F3 to make room for 3dfill at bottom
# F3 3dfill interface: normmv/pix/col/"fat"/fill_surf/writeims -- at bottom
# chkwritefillim: warn (1) not yet filled, (2) no mgz yet read for header vals
# block attempt to directly run tksurfer.tcl interface file
### ---- csurfsrc-141102.tgz ----
# warn .origarea redefined upon "R" on "area:" line
# select_patch leaves current pose if prev surface was 3D
# select_patch leaves current pose if patch name same except stepnum
# warn truncphasemin > truncphasemax on <Ret> in entries, truncphaseflag=>ON
### ---- csurfsrc-141207.tgz ----
# logcmd locklabel
# warn/advise empty .stat on CLU just read real-valued
# middle-click on "w1" -> switch to "w2" without needing fn-F3
# N.B.: Shift-ButtonRelease-1 also get unshifted cmd (but overload middle OK!)
# bind read_label_cut_clearvals 2 (add label) to lab line Shift-Middle-"C"
# clear rgb combo on listcmd live re-read rgbdir (was appending!)
# label combo listcmd to live re-read labeldir (manual reabbrev for clean log)
# shift-middle-click on "w1" -> switch to "w3" without needing fn-F3
### ---- csurfsrc-150220.tgz ----
# expose phase LUT (lutw) in fn-F3
# add W-ASCII button on F3 interface for write_ascii_surface
# fix/rename/untangle select_surfext from fullpath F3 entry
# allow full path in F2 "surf:" surface extension entry
# add "R" button on F3 "insurf:" for consistency
# make ltw button redraw
# val3d: warn/fix colscale mismatch, help (PNT to see, samp controls HOWTO)
# add another copy of S/V button to val3d for read/paint/swap 3d stats
# scroll entry to informative end of filename after select val/val3d
# add $anlabel to setfile list (rm unused $annot) to not yoke to $label
# labelentry/D now also load/use .annot files, in addition to .label files
# triple-overload label "W" w/write_val_annotedcol_vertices
# label buttons first chk suffix, then setfile to check{read,write}labeldir
### ---- csurfsrc-150306.tgz ----
# shift-middle-click label tick toggles annotbordflag
# expand "S","T" butts to 9 cases: time/stat/both by label/annotrgb/annotall
# add arg, more errchk to tcl funct gettseries for label/annotrgb/annotall
# add arg, more errchk to tcl funct getstat for label/annotrgb/annotall
# add arg, more errchk to tcl funct getstattseries for label/annotrgb/annotall
# bind all 9 cases to "T" (3 cases) and "S" (6 cases) buttons...
# add "X" button to label line to run corr_over_label
# bind swap_val_val2 to middle-S/V, mv swap_valval2_valbakvalbak2 to shift-mid
# fillneartype, cmptype state now maintained by interface
# bind middle-click nearestbuttons to set fillneartype (left-click sets too)
# bad fill/cmp type error/help for do_corr (before log errors)
# doc $prfdir="prf" in setfile lists (setfile label still guesses dir=label)
# if Mac, look for TextEdit (N.B.: not good for fullscreen)
# "label:" dropdown also loads SamSrf ${hemi}_pRF_sf_{pol,ecc}_r.label 
# label "R" auto reads pair of SamSrf labels given either one
# overload "X" button: middle-click does corr_over_annotcol
# swap to show corr and reset col when done with corr_over_label/annotcol
# confirm 3 kinds of swap with a diagram of stack
# rm corr parms from label popup, add setup prepopup to "X" butt
# corrctrls popups documents CircCorr
# report searchlightvtxcnt, global label so setfile inside do_corr works
### ---- csurfsrc-150322.tgz ----
# calcdisp_curr2orig_logarat: use compute_logarea
# re-bind "area:" line "D": left=>logarat, middle=>arat, shift-mid pial/white
# select_curv rec $hemi.area.logarat, fix a few R/G colscale resets
# "Dijk" button to measure/display approx geodesic path between last 2 selected
# squish entry, "sl:" to nothing, to make space for "F" and "GR" buttons
# "GR" button to run compute_gradient
# overload nonbinaryfs tick with toggle gradvecflag and gradvecbakflag
# tick gradvecflag or gradvecbakflag only resets parms if other not ticked
# "F" button to run fieldsign, optionally display 2 gradients
# arrownormflag/arrowscale unlabeled chk/entry under phasecont (like them)
# toggle arrownormflag resets arrowscale (ON=>0.5mm, OFF=>5)
# editfile: use 'open -e', touch empty file, so TextEdit works on 10.10
# overload unlabeled arrownormflag check w/toggle angoffrevarrflag
### ---- csurfsrc-150410.tgz ----
# corrected prev binding (was an Shift in there, too)
# swap_settings S/V (swap_val_val2, swap_stat_val, swap_valval2_valbakval2bak)
# "curv:" dropdown loads thickness, resets R/G colscale mid=2.3mm
# horrible yosemite hack: draw xterm over panel for 20x speedup
# comp_disp_grad doesn't do compute_angles_vals_to_baks unless phase
# shift-middle-click arrownorm to convert/display gradient as real-val overlay
### ---- csurfsrc-150423.tgz ----
# add F3 panel smooth type "gr" (tcl: smooth <type=grad>), equals valbakonly
# add Caret videen-style "vd" colscale on F3 panel
# select jet/vd zeros fthresh/fmid, resets truncphasemin/max
# middle-click overload: BRy->jet, BR->vd (to avoid going to F3)
# update to new trace syntax
# warn/explain panel for display gradient ampl as shading
# separate fmid/fthresh/truncphase{min,max} presets on click "jt" and "vd"
# L-click "Bg" gives popup with verbose radio labels for all color scales
### ---- csurfsrc-150502.tgz ----
# "winxy:" reports clamped-to-screensize number after short delay
# bind sample controls popup to (default) L-click "label:"
# R-click "label:" now brings up help panel (better consistency)
# shift-mid-"D" on label line converts label to AFNI ROI mask BRIK
# shift-left-"D" on label line converts one clicked .annot region to ROI mask
# ctrl-shift-left-"D" on label line converts all .annot regions to ROIs (warn)
# warn popups for non-default overloaded actions on "label:" line "D" button
# fix bug: lastcolscale was -1 on first complex swap from dup'd fixcolscale var
# fix bug: forgot-to-global-brainregioncnt prevented using do_corr w/MGH annot
### ---- csurfsrc-150513.tgz ---- (6K lines)
# Dijk checks if MGH geodesic binary is there (e.g., not there in 5.1)
# warn $scandir equals __noscandir__ for MGH annot to 3D ROI BRIK
# report sample infix in convert-label-to-ROI-BRIK {mm,fr}={min}to{max}
# if set areaflag, recalc full area on white, else restore def zero midline
# shift-mid-click RESTORE overload: does really_center_brain
# patch combo also loads type smoothwm/inflated (was just full/occip/cortex)
# don't set swap_*_explain vars so overloaded S/V always reports
# warn/block FILL if label loaded but not shown
# put corrctrls at top of do_corr (else prevent change cmptype!)
# report 3rd file (avg timecourse) now written by "T" button
# pop-up pre-report def/nondef label line D,C,CLR,R,RC,W button actions
# pop-up pre-report value: line CLR actions
# ROI button pop-up warns fill to stat/complexamp/real (fthresh/sfthresh)
# pop-up pre-report value: line CLR actions
# label line T check/explains 3D stats not loaded
### ---- csurfsrc-150728.tgz ----
# add w4=18=FRED_TODO to F3 (rm GR), fixcolscale, colscale pop-up
# add R-click help to colscales pop-up radios 
# change "Bg" to "Col" (colscale omitted before)
# fixcolscale sets now-allowed complex (amp) if real/imag both loaded
# if colcontrols already there, just raise it (break works in bind!)
### ---- csurfsrc-150823.tgz ----
# overload mid-click colcontrols real LUT: toggle zerosymmfadeflag
# videen: real:zerosymmfadeflag=0, cplx:zerosymmfadeflag=1 (mid-clk toggle)
# CARET: zerosymmfadeflag=0 (mid-click to toggle)
# auto redraw radio change in colscale popup, rm REDRAW button
# third overload for S/V: swap_pval_val (pval only exposed on this confirm)
# force stat mask OFF on complete xcorr
# mid-click "val:" line CLR also clear pvals
# make "label:" bold to indicate clickable
# if NormSamp controls there, just raise window vs. make another
# "RC" button (read/cut) rm'd, mv funct to shift-middle-click "R"
# popups warn/explain overloaded clicks: vtxcolflag, annotbordflag,
#  (cont.) gradvecbakflag, gradvecflag, zerosymmfadeflag, angoffrevarrflag,
#  (cont.) arrownormflag, nonbinaryfsflag, bordneiflag
# add xcorrcovarflag tickbox to Searchlight popup
# "X" pre-pop-up reports correlation results type, fields where they go
# add R-click popup help to NormSamp popup
# rm val3d: S/V, add val3d: UQ, rename val3d PNT->PAINT
# mv val3d: CLU to val: CS, squish 
# paint_real_or_complex checks 3D stats loaded
# wire find_uniqsamp_vertices to UQ button
# mid-click "val:" line CLR also clear uniqvoxdata (.uniqvoxcnt, .uniqvoxnum)
# add xcorruseuniqflag to xcorr pre-popup
# warn/explain find uniq vox vtxs
# inline corrctrls back into do_corr
# wrappers controls now intercepts killbox, so do_corr can pause/kill
# middle-click "W" on "val:" line: percent resp to .stat and wfile (_%)
# new dftctrls/corrctrls callers allow interactive parm fix w/o kill
# "set userok 0" before "source $script" for new controls-based movie scripts
### ---- csurfsrc-150912.tgz ----
# redraw again in select_surfext fixes stale buff on 2x in function on Mac??
# new help for click "tcl:" to record interface tcl commands
# new help for "%:" scale entry
# cmd-ctrl-left/right arrow rotates brain in plane
### ---- csurfsrc-150922.tgz ----
# warn ROI ignores truncphase
# warn bad non-integer SMOOTH args
# "val:" line "R" choose frame number popup if .mgh file header nframes > 1
# change brainpose by sliders reports core C/tcl cmds to tcl log (was tcl procs)
# label-line binds: change if nondivider to if divider break (works in bind)
# DIST and Dijk also return pop-ups (was just log)
# fmid/fslope/angle_cycles/angleoffset keyboard shortcuts logcmd's
# F2 panel: replace "none" and "curv" radios with "curv" tick
# intplut->"intp", add "bot" ($botedgelutflag), "sym" ($zerosymmfadeflag) ticks
# "bot" and "sym" back on F3 panel, squish radios: "none"->"no", "curv"->"cv"
### ---- csurfsrc-151010.tgz ----
# small upper right "h" button for tksurfer help
# also load *.crv files into "val:" dropdown (ignore $hemi)
# also load *.vtk files (both subject, session dirs) into "val:" (ignore hemi)
# "val:" line "R" choose column num popup if .vtk file header num columns > 1
### ---- csurfsrc-151120.tgz ----
# open xterm and run tail -f tksurfer.log in it on record tcl script
# also load subjects scriptsdir scripts to "tcl:"
# middle-click overload both AREA/LINE w/uncut_connected_vertices (1+ marked)
# warn redo of startup/standard scripts
# shift-middle-click overload both AREA/LINE w/cut_vertices (1+ marked)
# move awkward LINE/AREA cut/restore points overloads to new PTS button
# use listcmd for "tcl:" so newly created scripts visible without restart
# add Save/Goto View buttons inside TRANSLATE panel
# GO (run tcl script) suppresses ret=0,1 in addition to ret=""
# ctrl-left-W val: write mgh valfile (force real-only)
# ctrl-middle-W val: write vtk POINT_DATA valfile (force realonly)
# F3 panel: W-ASCII=>ASC, add VTK (write_vtk_surface), func autoappends .vtk
# rm F3 FL (flatten) button till working again (makes space for PTS)
# shift-ctrl-middle-click "W" on "val:" line: write_vtk_surface_plus_values
# .mgh/.vtk "val:" line "R" resets colscale to real-valued if complex
### ---- csurfsrc-151230.tgz ----
# add listcmd to "val:" combo so open dropdown updates files
# add listcmd to "patch:" combo so open dropdown updates files
# add listcmd to "lut:" combo so open dropdown updates files
# add listcmd to "curv:" combo so open dropdown updates files
# add listcmd to "area:" combo so open dropdown updates files
# ctrl-left-W on "label:" line => write_selected_list_to_label
# ctrl-left-D on "label:" line => read_label_to_select
# don't crash interface if FSURF_DIR not defined, just remove Dijk button
# copy C/tcl functions/vars into comments
# overload eroding FILL check: mid-click => dilating FILL (cancelled by erode)
# new "cr" (complex/real) smoothing F3 (or mid-click F2 "val"): real avg amp
# ctrl-mid-click label "W": assemble csurf labels for ColorLUT structs to .annot
# 100ms delay to block runaway updates w/fast slider trough clicks (Linux-only)
### ---- csurfsrc-160130.tgz ----
# reset flag/alpha for read/write_mgh_annot reset for log
# do_lut2annot displays/rotates assembled labels, then hitcount
#  [tmp 160303 release]
# change "er" to bold "dl" if dilating FILL, better state report
# ROI button unsets dilatingfillflag, updates/restores changed tick label
# [see NOTES for combobox listbox fix details]
# 3 small: -listwidth <pix> *and* listbox.width: surf,curv,area
# 7 large: only -listwidth <pix>: tcl,patch,label,lut,val,val3d,rgb
# if ltw, botedgelutflag=1,zerosymmfadeflag=0 (no effect: reflect policy)
# add (tif) template to setfile sessionfiles
# load abs FSURF_DIR template .tif's into curv dropdown
# if select template .tif -> chooseframe popup (documents frames)
# remove read_tif_* frames arg to parallel read_binary_values mgh,vtk
# 4th,5th S/V bindings to expose swap_curv_curvbak,swap_curv_val
# add REG button to run/interrupt sphere_morph
# swap rarely used parms: area_shrink (wt/wc) for sphere_morph (wcrv/wsta)
# "W" button "val:" overload: shift-M:val_to_sphim 0, shift-R:val_to_sphim 1
# read .tif template popup to warn sphere.reg coords not yet loaded
# swap rare parm: shrink2d(wsh->shear) for sphere_morph(wcpx)
# "W" button "val:" overload: shift-L:val_to_sphim 2 plus val_to_sphim 3
# REG checks {curv,stat,real,imag}imloadeflag's
### ---- csurfsrc-160411.tgz ----
# 1 more overload for unmarked fs button (toggle gradvecbak3dflag)
# 3 more overloads (compute_surfgrad) for "GR" button
# add samevtxthickflag/help to NormSamp, Clust Controls
# add wmgmext/help to NormSamp, Clust Controls
# "label:" line "W" message tells whether write is real vs. complex
# if recognize prf2sess pRF*_{ecc,pol}_r-?h.w, reset colscale like SamSrf label
# add xcorr_outstem entry, r2zscoreflag to xcorr pop-up
# xcorr auto-writes corr/covar wfile as <xcorr_outstem>_s-$hemi.w in $val dir
# xcorr auto-writes r2z wfile as <xcorr_outstem>_z-$hemi.w in $val dir
# paint_real_or_complex: block normsearch=OFF with non-zero range (PAINT)
# get{tseries,stats,stattseries}: block like paint_real_or_complex does
# searchlimitsBAD also checks block min > max
# fix searchlimitsBAD, re-order maxs above mins
# middle-click UQ writes */$scandir/$hemi-UniqSampVtxs.label
### ---- csurfsrc-160527.tgz ----
# middle-click overload on PAINT also smooths (using curr parms) before redraw
# add ~/tmp/TmpTclScript.tcl to "tcl:" menu
# uniqvtx tcourse pre-warn: no native stat, no paint, no uniqsamp
# add normdsampuniqvtxflag
# ROI does phase trunc if truncphase ON (precedence: stat/phase/cplx/real)
# fix Shift-Middle binding "RC"->"R" button (was overlap/ignore)
# add ctrl-left-click "label:" line overload for read_uniqsamp_vertices
# add FDR ctrls CS popup: smoothsteps, desired_FDR, noisedf, uniqsampvtxflag
# do_fdr uses $stat saved by standard tcl scripts to chk name prev loaded file
# if stats loaded, also smooth w/sparse and weighted (was just val)
# new smooth type option on FDR pop-up
# add val,weight smooth type option on FDR pop-up
# catch/fix statmask-disabling sfthresh=sfslope=0.0 (sfthresh,sfslope,mask)
# add F3 panel OFF button to write .off format surface
# add F3 panel STL button to write .stl format surface (3D print)
# middle-click OFF => face colors, shift-middle-click OFF => vertex colors
# add hemi, cp Dijk label from subj scripts to sess scandir (or subj labeldir)
# check selfintersectloaded (avoid ask clear selfintersect twice)
# add surftmp to dropdown list
# middle-click SHRINK does NormArea each cycle
# ctrl-left-click "C" does recut label respecting normdsampuniqvtxflag
# middle-click MESH toggles pointsflag
### ---- csurfsrc-160624.tgz ----
# better "label:" line "C" restore OK help after recutting sparse/uniq label
# add arbitrFDRcovarflag tick to mid-click-"CS" popup
# 6th overload (shift-ctrl-right-click) label "W" button: write_spotlights
# "surf:" entry loads *.$hemi.*.surf.gii, no preappend hemi 
# "val:" entry loads *.$hemi.*.{func,shape}.gii
### ---- csurfsrc-161004.tgz ----
# mv 6th label "W" overload (shift-ctrl-R-click) => (shift-ctrl-MIDDLE-click)
# 7th overload (shift-ctrl-R-click) label "W": write_val_annotedcols_vertices
# force: $hemi-<infix>: match hemi, no .label, dash, at least 1-char infix
# create subject tmp dir if missing (For TmpTclScript.tcl)
# change write_spotlights => write_searchlights
# block using spaces in entered rgb names in save_rgb_{checkfirst,named}
# explicit bind's for ButtonRelease-1's because break doesn't work in -command
# default S/V explain panel only one time (others still always)
# middle-click on upper-right "h" makes run print_hist (histogram) pop-up
# middle-click SMOOTH to get pop-up to run searchlightop_val2stat
### ---- csurfsrc-161217.tgz ----
# histctrls: preset complex ang if complexvalflag
# histctrls: two new options on popup sensitive to (s)fthresh
# xcorr panel: xcorruseuniqflag->searchlightuniqflag, add numafteruniqflag
# "N" button reports standard/dense vs. uniq-by-removal vs. uniq-expand-to-N
# searchlightop panel: add redundant searchlightuniqflag, numafteruniqflag
# SMOOTH steps field also takes "annoterode" -> run erode_annot()
### ---- csurfsrc-170320.tgz ----
# write_val_annoted{col,cols}_vertices: warn if $annotbordflag ON
# count_mgh_annot_neigh2stat: ctrl-middle-click-D, warn no-annot, .stat-loaded
#  [tmp update]
# fix GR (gradient) button error popup bug, manually bind avoids dup L-*-clk
### ---- csurfsrc-170621.tgz ----
# add GLB (glTF output) button on fn-F3 panel
# add ctrl-shift-mid-click $annotborddotflag overload to label tickbox
# add ctrl-shift-right-click prune_annotbord overload to label tickbox
# auto-append .asc/.vtk/.off/.stl/.glb so testreplace can warn overwrite
### ---- csurfsrc-171018.tgz ----
# forcemode errors
# add bindings for 17 new F3 help panels
# rearrange widgets more logically 3 rows: self/selfd/ck3rd/ar/2d/ck3:{lo,hi}
# 3rd overload tick bottom of phasecontour box: toggle display normals
# shift-Return in $arrowscale entry also sets $arrowline to entry value
# middle-click REDRAW toggles stereoflag, divergent stereo
# shift-middle-click REDRAW toggles stereoflag, convergent stereo
### ---- csurfsrc-180125.tgz ----
# first *shift*-right-click help overload (annot summary for label entry)
# middle-click-R on "val:" line does demean,varnorm after read
# REDRAW diverge/converge stereo toggles -> force, def left-click stereo off
# shift-middle-click-R on "val:" line does read cpx, scale mean cpx amp to 1
### ---- csurfsrc-180621.tgz ----
# "R" on "lut:" line warns if val2rgblut file doesn't exist
# "Col:" popup ltw hover saves colscale, undo change->ltw if no val2rgblut file
# ctrl-middle-click REDRAW: toggle light back/inside surfaces
# PLANE button turns on light inside surfaces
# add "clo" tick to toggle selectdmax (def=2mm, deep near vertical surf=0.25)
# show non-standard patch types in "patch:" dropdown after standard
# mid-click "N" bottom left large F3 panel: norm_move_vertices_fracthick
# add "i" button for toggle interface size (skip popup)
# "clo" button R-click help
### ---- csurfsrc-190208.tgz ----
# bind annotmaskflag to label tickbox (5th overload: shift-right-click)
# bind pick annot idnum visibility controls popup to "D" butt (shift-R-click)
# annotmaskctrls/do_annotmask: pick annot idnum(s) to not mask
# annotmaskctrls opens current MGH annot ctab in helpwin
# wire toggle multitimecourseflag to ctrl-mid-REDRAW
# mask annot popup can now write labels (not in "W" but convenient)
# setfile label w/relative now defaults to subject (was funct!)
# truncphase{flag,max,min} allow wrapped phase limits if complex
# ticking colscale=1=heat resets truncphase{min,max} to orig def 2nd half OFF
# add "s" tickbox for $softtruncphaseflag, "truncphase" -> "truncph"
# overload mid-click-W on "rgb:" line to force write transparent
# overload mid-click-WN on "rgb:" line to force write transparent
# add unlabaled entry next to invph tick for $softtruncwidth (invphase->invph)
# rm check for _f in filename (do_fdr) so no err when csurf doesn't load stat
# add $extract_unmasked_flag" tickbox to call write_val_unmasked_vertices
# do_annotmask checks overwrite if omnibus label (but not multi)
# path spaces: listcmd_curv, select_curv (see commented-out): set "" -> lappend
# same fix for listcmd_{area,patch,lut}, select_{area,patch}: set "" -> lappend
# listcmd_{tcl,label,val,rgb} work?? (dblquote lists auto-curly-braced earlier?)
# warn/catch mris_pmake ("Dijk" geodesic) fail w/spaces in SUBJECTS_DIR
### ---- csurfsrc-190722.tgz ----
# strip out *.3d and *.flat in case patch infix matches surflooklist
# write surfer.mat into log on "Save"/"Goto"
# listbox select pops up standard tclscript controls panels w/o GO
# fix Dijk button (normal ret goes to stderr too?)
# middle-click Save/Goto view butts allows adding suffix to default surfer.mat
# select_surfext suppress reread if same as last time (callbacks can overlap!)
# rm 2x reread on F3 interface "insurf:" (touch surfext does tix callback)
# add "P" button (direct_paint) to "im:" entry
# 8th overload of "val:" W button: sample valbak,val2bak: surf2sphim 4,5
# bold "im:" on F3 interface makes surfdata->sphim->mgz popup (sphimctrls)
# write sphim to mgz now optional on sphimctrls
# add "V" button to "val3d:" entry to run all-in-one read_vecs2surf
# dtivecctrls pop-up to allow choose subbrik
# dftcrls -> writedftampctrls for consistency
# R-click help also pops up panel for too-much-overloaded label tick
# do_dtivec purples/disables/renames butt b/c takes a while, unpurples when done
# fix val/val3d both visible after change interface size when val3d
# do_dtivec purple/unpurple moved to more general wrappers.tcl controls
# fix misleading error message on NormSamp parm mismatch
# fix tcl: GO button double exec (block callback from setfile)
# add RD button to val3d to read regdat/rawdata (make space: PAINT=>PA)
# 8th overload "D" button w/calc_annots_nzval_overlap (ctrl-shift-R-clk)
# warn about FILL even w/visible label (was just invisible label)
# warn overwrite $hemi.overlap.txt
# macappnaphackflag can force/unforce hack
# finish "RD" (read rawdata and regdat) popup for val3d: line
# dtivecctrls: add parms for sampling surface, cortical depth
# do_dtivec: force sample at single cortical depth, live update NormSamp panel
# block white text: -selectforeground black for linux dti,regraw
# read .mgh valfile: check embedded *.rh/lh.* (vs. *-rh/lh.w) and warn
# shift-right-clk overload on unlabeled arrowstick to toggle dipolesflag
### ---- csurfsrc-191216.tgz ----
# jam in unlabeled entry for insidesurffact next to offset on F3 panel
# also look-for/dropdown-load oldstyle valfiles in $subject/surf
# load all *.obj to "surf:" dropdown, regardless of hemi
# also load $subject/label/*.poi file to "label:" dropdown
# "D" button uses read_poi_annot if *.poi suffix
# also load $subject/surf/*.obj file to "label:" dropdown
# "D" button uses read_obj_to_annot if *.obj suffix
# add "FlipHemi" button to REDRAW row on F3 interface
# load all *.srf to "surf:" dropdown, regardless of hemi
# add OBJ to F3 panel for write_obj_surface
# if *.obj/*.srf, select_surf tries pre-appended if non-preappended missing
# rm dups from "surf:" dropdown (rh.surftmp match, pref strip, *.obj readded)
# warn read *.srf possibly left-handed (but not *.obj)
# chklefthandedsurf: change subject re-arms chk for left-handed
# fix middle-click SMOOTH logic (for searchlightop_val2stat also does neighfill)
# fix bug in chklefthandedsurf
# block reabbrev callbacks for curv/area in session dir (was just subjects dir)
# also load subjectdir *.mgh files into "val:" dropdown (areas)
# 6th overload S/V with swap_origarea_val
# force load example-resolution mgz file before FILL3d *or* write_fill_images
# bold "View" butt (curr saved matrix popup), report dir that mat's saved into
# better help for the lights
# SAVE/GOTO alt add-suffix-to-viewmatrix popups show avail suffixes
# testclose checks surfediteflag
### ---- csurfsrc-200629.tgz ----
# PLANE complains not enough vtxs in pop-up (vs. just invisible csurf log)
# to select patch for mask/cut: hold Shift to stop "patch:" dropdown auto-load
# select_curv sets surfcolor to 1 to display curvature in case gray
# fix stuck shiftkeypressed for R/W patch (not sure how this happens)
# fix fail load *same* 3d surf after displaying a flat patch
# fix fail restore patch view on reload *same* patch after displaying 3d
# differentiate shift-right-D popup: if !valloaded -> show annot subset
# fix report wrote transparent after cancel
# display "D" annotation pops up areas def color table
# eighth overload of "W" button to extract single MGH annot region to label
# jam dimredcurvfact next to cmid 
# add output .annot to write_mgh_annot popup to avoid accidental overwrite
# add def MY_ANNOT.annot outfile write_mgh_annot popup (avoid overwrite)
# make MGH annot popup now has full paths and loaded dropdowns
# make_mgh_annot: allow skip show overlap, alpha=255
# new arrownorm tick/entry controls pop-up on R-click help
# "cpx" tick catches/fixes blank disp w/inconsistent real/cpx
# write_mgh_annot: check files for each LUT region exist
# normal move "N" on F3 panel does compute_normals_areas
# write_mgh_annot: chk duplicate reg ids (else silent Cfucnt log fail)
# "label:" line plain "D" warns missing file (vs. just log)
# "label:" line "C" overloads warn missing file, allow cancel
# write_mgh_annot: also chk duplicate colors
# write_mgh_annot: gather/report all missing label files (vs. bail on first)
# alt mid-click-GOTO finds opposite hemi point
# fix stale hard/soft truncphase message
# write_mgh_annot: allow make annot when label files missing (Cfunct allows)
### ---- csurfsrc-210614.tgz ----
# buttonbar for "label:" line "C" butt R-click help (recut,hole,add,recutuniq)
# add new var pointsize to ARROWS/NORMALS CONTROLS
# write_mgh_annot: restore overlay if skip count overlap
# buttonbar for "label:" line "W" butt R-click help (label,vtxcol,annot,etc)
# buttonbar for "val:" line "W" butt R-click help (vals,FT2amp,sphims)
# allow bail from all "val:" line writes
# allow bail from all "label:" line writes
# buttonbar for "fs:" line "GR" button R-click help (calc gradient arrows)
# controls for 4-overload unlabeled "fs:" tickbox (gradient arrows)
# buttonbar for "val:" line "S/V" butt R-click help (various swaps)
# allow escape from all S/V button actions
# buttonbar for "label:" line "D" butt R-click help (display,conv3d,mask,etc)
# hack: extra labeltick controls win button, RESTORE ANNOT BORD, to undo PRUNE
# add pointsize, mesh/rgb to labeltick controls win
# allow back out of "val:" line CLR's
# redrawbutton warn vtxcolflag on
# allow back out of "label:" line CLR's
# fix weird bug by always destroy/remake labeltickctrlswin
# middle-click overload statANDhypotflag to mask tick
# increment appnap_hack delay 500->800 msec (works again in 10.15)
# FILL warns eroding/non-eroding fill
# middle-click-R on "rgb:" line shows all tiffs in nmovie
# CLR single label now reads current combo entry, not found err
# hack: fix arrowscale Return in popup somehow bound to arrows->col action butt!
# ROI: if cmplx+stat, force choice between stat vs. stat AND hypot
# ROI: if real+stat, force choice between stat vs. stat AND real
# ROI: ctrl-mid-click overload statANDrealflag to mask tick (radio-ize)
# ctrl-middle-click on CLR does clear_annot_with_col mesh rgb
# reverse Skip/ShowOverlap, so <Ret> skips
# dup arrowscale and arrowline in gradient popup (unlabeld tick in fieldsign)
# buttonbar for "label:" line "CLR" button R-click help
# buttonbar for "label:" line "R" button R-click help
# remaining file not found popups for "D" and "R" buttons on "label:" line
# warn hidden label for ROI button (similar to FILL)
# fix logging for vtxcol labels
# fix nagging vtxcolflag=ON popup -> once only per new read
# dup write_mgh_annot comment-in/out: {exclude,include}_following 
# final overload for "label:" line "W": write_vtxcol_label
# readvtxcols accepts *.col (as well as autoconverted *.label), cleanup
# {read,write}vtxcols,labeltovtxcol cleanup, better vtxcol warnings
# buttonbars pop/re-create corresponding help, shortcuts include button text
# lut2annotcrtsl/do_lut2annot: save combo in global to update hacked cbx's
# set overlayflag for gray BG on read label/annot/etc, write_mgh_annot
# accept $hemi-<name>.label format for csurf annot files
# "label:" entry/dropdown also loads *.gii's, "D" displays
# "label:" entry/dropdown also loads *.cols's, "mid-R" displays
# can't use vtxcol as label so "D" on vtxcol says use "R" instead
# third version of DISPLAY SUBSET/MASK OVERLAY popup for vtxcol subset
# remove buttonbar popup delay since wrappers.tcl now moves it aside
# add labeled_cut_clearval to "label:" line "C" button, buttonbar popup
# allow bail on re-run startup script
# fix auto-run default scripts (after cmd->bind to use break)
# bind cmd/alt-z to UNDO cut button, R-click help on two more popups
# writevtxcols no vtxcols loaded, wrong suff
# final overload of D button: currcol_to_vtxcol
# ctrl-right-R,W bind (also) update vclabel so confirm message not stale
# ctrl-right-R,W bind: fix forgot to read curr entry to label!
# rename helpfile: hemisurf -> insurf_read, bind to F3 "R"
# helpwins for F3 panel col1,col2 for "bi" scale
# check save_rgb suffixes
### ---- csurfsrc-220324.tgz ----
# RESTORE rotates subject name containing "cereb" to posterior view
# 11th overload Shift-R-clk-"W" on "label:" line does write_adjphase_vertices
# checklabelfile proc: warn read complex label as if real and vice versa
# "label:" line CLR button to clear annot+vtxcol
# fix load tix on IRIX64
### ---- csurfsrc-221002.tgz ---- (26oh)
#   [tmprelease]
# "val:" entry accepts *_000.bfloat, check corresponding *.hdr file
# read_real_or_complex_binary_values: std fmt cmplx bfloat's OK 
# R-click on "surf:" upper right label lists vertexcnt,facecnt
#   [tmprelease]
# R-click on "surf:" read_binary_surface printheaderflag to get/show surfhdr
# default left-click "R" now req's *.label (was allowing *.annot)
#   [tmprelease]
# readtemplateframe leaves popup, select_curv only kills/remakes if diff frmcnt
#   [tmprelease]
# fix "D" read single label file popup: borders (new def), incl area, help
# count_mgh_annot_neigh2stat -> areaneigh2stat, fix R-clk "D" button menubar
### ---- csurfsrc-230925.tgz ---- (26oi)
# fix R-clk label "D" popup text: Calc Overlap -> ctrl-shift-mid-clk -> right!
# add tenth label "D" overload: ctrl-mid-clk-D: labelcol_to_vtxcol
# PRUNE ARROWS, gridsize, prunearrowsflag to FIELDSIGN and GRADIENT ARR CTRLS
# add arrownormflag to FIELDSIGN and GRADIENT ARR CTRLS
#   [tmprelease]
# Return in gridsize entry does prune_arrows
# fix Return in arrowline FIELDSIGN popup bound to controls PRUNE_ARROWS button
# add arrowhead{frac,min,angle} to FIELDSIGN and ARROWS popups
# hack in DEFAULT LINE/FILL ARROWS button to FIELDSIGN popup (GR already does)
# put code for bot phc tickbox binding into do_grad2col, binding uses it
# add write_statids2randcolannot button to "label:" line "W" (no-hotkey butt)
# add second alt SMOOTH controls popup for running neighop_val2stat
# pre-delete stranded TmpTclScript.tcl swapfiles
# add another FIELDSIGN and GRADIENT ARROWS default button for sparse arrows
#   [tmprelease]
# tcl: warn re-run startup, block init-run non-standalone SURFACE-STATS script
# better feedback on Dijk output file, check overwrite
# sort Dijk output label to path order, optional insert overlay data into label
# "label:" line "W" R-clk butt for C funct: write_sorted_by_pathdist_label
#   [tmprelease]
# fix stale/broken funct name: read_poi_annot -> read_poi_to_annot
# convert hack event generate's to procs for "label:" line "D" butt/overloads
#  fix swapped popup buttons: labelD_label2roi3d labelD_annot2roi3d
# convert label-line D button bindings to procs (rm event generate hacks)
# convert label-line C button bindings to procs (rm event generate hacks)
# ionvert label-line CLR button bindings to procs (rm event generate hacks)
# convert label-line R button bindings to procs (rm event generate hacks)
# convert label-line W button bindings to procs (rm event generate hacks)
# convert fs-line GR button bindings to procs (rm event generate hacks)
# new buttonbar for label-line "T" button (bind's -> proc's)
# new buttonbar for label-line "S" button (bind's -> proc's)
# new buttonbar for label-line "X" button (bind's -> proc's)
# new buttonbar for val-line "R" button (bind's -> proc's)
# convert val-line "S/V" butt bind's to procs (rm event generate hacks)
# new buttonbar for val-line "CS" button (bind's -> proc's)
# new buttonbar for val-line "CLR" button (bind's -> proc's)
# convert val-line "W" butt bind's to procs (rm event generate hacks)
# new buttonbar for "SMOOTH" button
# new buttonbar for area-line "D" button
### ---- csurfsrc-240426.tgz ---- (26oi)
# put neighbor order info on paintball popup into
# fix SMOOTH button invoke fail w/new empty cmd b/c change to bind
# fix def bind for Return in val: entry (invoke fail w/no-cmd)
# fix def bind for Return in label: entry (invoke fail w/no-cmd)
#  [tmprelease]
# add padlabelvtxsflag to label tickbox popup, add hotkey, warn label read
# add isocontour controls pop-up for R-click "isocont"
# labelD_display opens label control popup (duh!)
# overload "clo" button with selectinsideflag
# event generate buttonbars for R-click help for REDRAW, RESTORE
# overload "c2lab" button with usetalcoordsflag
# fix R-click help on "label:" label popup
# change usecurrcoordsflag/usetalcoordsflag ticks to "|ta|cu|" tixSelect
# copy-C: write_labeled_vertices -> write_val_visible_vertices (bakcompat'd)
# rename: extract_unmasked_flag -> unmasked_to_label_flag
# rename: extract_overlays_flag -> unmasked_to_labels_flag
# copy-C: write_selected_list_to_label -> write_val_selected_list_to_label (syn)
# select Talaiarch sets up choose MNI 305 vs. MNI 152
# R-click-"ta" reports MNI 305 vs. MNI 152
#  [tmprelease]
# add lights brightness/position ctrls: shift-R-clk-REDRAW, REDRAW buttonbar 
# $insidesurffact to brightness/position lights ctrls
# fix buttonbar REDRAW (forgot to change default command to bind for event gen)
#  [tmprelease]
# fix R-click report popups for current ta/cu button state
# add $lighttwosidedflag to lights popup from R-click help buttonbar
# disp annot ("D") prints tot area all regions (except Unknown) for csurf log
#  [tmprelease]
# butt/no-hotkey for read_label_to_nearest_annot_using_col to "label:" line "D"
# overload smooth steps: "{annot,label}holes-more" -> fill_annot_holes_more
# overload smooth steps: add "{annot,label}holes-neigh popup
# prev uses function: C/tcl funct fill_annot_holes_neigh
# rm "annotholes-more" because fill_annot_holes_neigh is more general
### ---- csurfsrc-241112.tgz ---- (26ok)
# add R-click smoothsteps buttonbar for numerical/non-numer. smooth steps opts
# isocont popup action button sets isocontourflag
# better HOWTO save/see result on 'paintballs' popups
# labelW_randcolannot/write_statids2randcolannot ('paintballs') chks overwrite
# add toggle bigcursor button to REDRAW right-clk popup
# add $newreadfulllabflag (tcl only) to override def just show label borders
#  [tmprelease]
# add annoterode button to R-click smooth_steps help
# select_patch: after 100 to (try to) improve missed shift key
# fix comment-bug crasher! "E## force opaque ignoring "tran" entry"
# regularize sampclustctrls{win}, return win for reposition
# add RESTORE button command/buttonmenu: restore_zero_position
#  [tmprelease]
# turn off appnap for all apple silicon (kernvers=BigSur20+)
### ---- csurfsrc-250507.tgz ---- (26ol)
# rewrite RAW FOURIER TO PERCENT RESPONSE pop-up
# add COMPUTE AVG t-SERIES EACH VTX (do_computetseravgs) to that popup
#  [tmprelease]
# add clear_stats button for "val:" line "CLR" buttonbar
#  [tmprelease]
# tksurfer.tcl: "sft" -> "soft" (unoverlap sfthresh!)
#  [tmprelease]
# ticking isocont does isoconttickctrls/popup (prev just R-click isocont label)
# combine SMOOTH/smoothsteps button bars, expand buttons to all smooth types
# check appropriate fields loaded for all SMOOTH/fillholes functions
#  [tmprelease]
# mini popup on R-click "w" smoothing to control $halfweightdist
# add smooth stat to SMOOTH R-click buttonbar (no visible radiobutton, even F3)
# middle-click on DIST button does compute_avg_edgewidth
# middle-click DIST now reports edges (tksurfer.c now appends to genstrret_1k)
# R-click GR, click unmarked fs tick -> put up fieldsign/gradient arrows ctrls
# move up fstickctrls to unoverlap buttonbar if from R-click GR
#  [tmprelease]
# bind to warn filledarrowsflag w/3D surf (no space between left bracket,plus!)
# AReOWS/NORMALS/POINTS popup: add $rmgradoutliersflag
# FIELDSIGN and GRADIENT ARR: $centerarrowsflag, $angoffrevarrflag
# FIELDSIGN and GRADIENT ARR: $sdoutlierfact,$areaoutliermin,$rmgradoutliersflag
# warn (both popups) re-calculate gradient if change rmgradoutliersflag
# warn (fstickctrls) re-calc grad if change $areaoutliermin,$rmgradoutliersflag
# nonbinaryfs helpfile renamed to gradfsarrows
#  [tmprelease]
# if vars exist, add $areanamesflag, no-annot-warn to LABEL CONTROLS popup
# add "Write Region Centers" button to R-click "W" on "label:" line buttonbar
#  [tmprelease 250810]
# liscmd_tcl: don't dup dropdown scripts when csurf starts from subj dir
# labelR_val: better error/help if trying to read .cols file
# add $dthreshfact hack to LABEL CONTROLS
#  [tmprelease 250829]
# add reggradvecbak{3d}flags to FIELDSIGN and GRADIENT ARROWS popup
# add 6 brainregion avg gradient buttons to GR gradient buttonbar
# do_grad2col bugfixes: accept 3D surfgrad, blk reggrad, colscale
#  [tmprelease 250917]
### ---- csurfsrc-250917.tgz ---- (26om)
# add calc gradient reversals make-popup button to GR button R-click
# add findgradrevctrls popup to run find_gradient_reversals
# don't trunc large early-area curv gradients (curv avg flattens distr)
# do_gradrev: run find_gradient, write pval wfile, border dots or val display  
# add flipRHpolararrowsflag to FIELDSIGN and GRADIENT ARR
# do_gradrev: def turn on pvalborddotflag, log popup values (also isocont)
# turn OFF pvalborddotflag for pval-using procs
#  [tmprelease 251126]
# findgradrevctrls help: non-existent findgradrev -> comp_grad
# add 3 Calc Laplacian buttons, comp_disp_laplace proc
# rm'd 3 Calc Laplacian buttons (includelaplacian=0), leave procs, tksurfer.c
# add copy_idnum_val to S/V (swap stat val) button bar
# left-click "label:" auto-pops up label_label help
# mid-click "val;" makes allverticesflag,val2newcurfflag popup
# "val:" combo dropdown also loads *-?h.w files in *label* dir
#  [tmprelease 260108]
# fix title to R-click on "D" on "area:" line: SMOOTH -> AREA RATIO
# read_mgh_annot/annotbordflag does reselect_selected_list: select back on top
# change annotbordflag does reselect_selected_list for select->top
# display-annot + change-annotbordflag do reselect_selected_list for select->top
#  [tmprelease 260412]
# bind toggle nobicurvfadeoverfthresh to middle-click "[ ] curv" tickbox
# cut_line/cut_vertices/uncut_connected_vertices: warn nothing selected
#  [tmprelease 260426]
# bind toggle nobicurvfadeoverfthresh to middle-click on F3 panel "cv" radio

#TODO: full check all do_<popupfunct> for save popup parms to log
#TODO: "R" on "F3-interface "im:" line doesn't work after FILL3d??
#  => callback blocking for no double redraw of already there?
#  => inim doesn't exist? dies FILL3d mess with it?
#  => move on normal seems to cause prob

#TODO BIG: touching cbx vars like $curv triggers select_curv/etc procs
#          those procs test if file exists
#          but file *won't* exist if setting var prior to write!!!
#          perhaps uplevel command could also block callback!?
#          but file still won't exist!
#TODO: convert redrawctrls to tix-combo-box-hacked controls popup
#TODO: convert fs to combo (still edlabval)
#TODO: omit backslashes on unfinished begin curly brace!! zillions!!
#      leave backslashes in multiline list since otherwise return gets in list
#TODO: warn $scandir equals __noscandir__ for MGH annot to 3D ROI BRIK
#TODO: N.B. $val et al stale rel to entry $valabbrev before use
#TODO: fieldsignflag still overrides unused R/G colscale=9
#TODO: could always reset colscale if read std MGH labels (or read w/o reset)
#TODO: update tcl scripts to use $scandir instead of $dir, fix csurf
#TODO: F3: read_{rawdata/reg},stimcycles/normd{frac}samp/rawdatarange/showavg

#### begin pial script NOTES
#INPROG: works OK, 0.75mm smooth T2, end: 10 just self/orig, 10 MRI off
#could apply wmfilter to T2 (first invert?) with adj truncate

#INPROG: moderately good pial (brain,self,fill,3rd=T2)
#INPROG:  mmid=55.0 mstrength=0.08  steps=1000  tang=0.5 norm=0.5
#         plus 20 steps w/filled/T2 off, plus 5 steps with no force

#INPROG: moderately good white (brain,gradientamp)
#INPROG:  MRI+grad: mmid=95.0 mstrength=0.125 steps=00  tang=0.5 norm=1
#         MRI+grad+self: mmid=95.0 mstrength=0.125 steps=40  tang=0.5 norm=1
#         a few steps of no-data relax
#### end pial script NOTES

# ~170 places to click in F2 (~50 more in F3)

############################################################################
# checks, setup
############################################################################
### block direct run
set tksurfertcl_version 26on
if ![info exists named_rgbdir] {  ;# tksurfer.c-defined unlikely there bare run
  puts "tksurfer.tcl: ### tk/tix interface:\
        designed for tksurfer binary to load ($tksurfertcl_version)"
  exit
}

### less sloppy/variable first draw on Mac
#wm withdraw .    ;# tkmedit: here by interface size procs

### require tix
if {[exec uname] == "Linux"}  {load libTix8.4.3.so}    ;# LD_LIBRARY_PATH
if {[exec uname] == "Darwin"} {load libTix8.4.3.dylib} ;# DYLD_LIBRARY_PATH
if {[exec uname] == "IRIX" || [exec uname] == "IRIX64"} {
  load libTix8.4.3.so                                  ;# LD_LIBRARYN32_PATH
}

### restore old look
if { $tcl_version == "8.5" } {
  puts "tksurfer.tcl: restore old look"
  ::tk::classic::restore
}
#set tk_strictMotif 1

### source standard widget wrapper code (fonts/colors/popups)
set program tksurfer   ;# find helpfiles
source $env(CSURF_DIR)/lib/tcl/wrappers.tcl

### hack fix runaway updates from rapid clicks in slider trough (Mac OK now?)
set delayredrawflag 0
if { [exec uname] == "Linux" } { set delayredrawflag 1 }

### horrible tmp hack gives 20x draw speedup (Yosemite+ 5sec->250ms, AppNap?)
set mac_appnap_hack 0
if { [exec uname] == "Darwin" } {
  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
}
if {$macappnaphackflag == -1} { ; }  ;# let this tk decide
if {$macappnaphackflag == 0}  { set mac_appnap_hack 0 }
if {$macappnaphackflag == 1}  { set mac_appnap_hack 1 }
#set mac_appnap_hack 0  ;# uncomment forces disable hack, overriding all
#set mac_appnap_hack 1  ;# uncomment forces enable hack, overriding all

############################################################################
# globals
############################################################################
### so script can determine who called it
set interfacefile tksurfer.tcl

### for send (inter X process auto send commented out)
#set thisapp [tk appname]   ;# maybe multiple copies

### for send (inter X process auto send commented out)
#set thisapp [tk appname]   ;# maybe multiple copies

### tksurfer.c: C/tcl functions defined at startup (init copy 24 Jan 2016)
# functions:
#   swap_buffers to_double_buffer open_window close_window zclip_surface
#   help redraw redraw_cached redraw_second clear_selfintersect
#   add_shell2selfintersect calc_gradamp norm_move_vertices
#   shrink area_shrink sphere_shrink ellipsoid_project ellipsoid_morph
#   ellipsoid_shrink ellipsoid_shrink_bug curv_shrink_to_fill smooth_curvim
#   smooth_curv smooth_val smooth_val_sparse smooth_val_weighted
#   smooth_curvim_sparse smooth_fs add_subject_to_average_curvim
#   read_curv_images read_images read_images2 read_images3
#   read_second_binary_surf read_second_binary_curv
#   normalize_second_binary_curv curv_to_curvim second_surface_curv_to_curvim
#   curvim_to_second_surface swap_curv_curvbak curvim_to_surface
#   read_binary_surface compute_normals_areas compute_normals_areas_report
#   recalc_surface_center read_binary_areas read_binary_areas2
#   compute_area_ratio compute_curr2orig_area_ratio compute_logarea
#   read_binary_curv read_binary_thickness read_binary_sulc swap_buffers
#   read_mgh_header read_binary_values read_binary_patch
#   read_binary_patch_to_mask read_binary_patch_to_cut
#   read_fieldsign read_fsmask read_binary_decimation read_binary_dipoles
#   read_binary_subsample read_label_cut_clearvals read_label_to_select
#   read_label_to_annot_using_col set_annot_alpha read_label_to_val
#   read_label_to_nearest_annot_using_col
#   read_label_to_undo_cut annotcol2brainregionname read_mgh_annot
#   read_mgh_colorlut read_vtxcol_label label_to_vtxcol_label read_regdat
#   read_native_stat paint_surface run_surfclust read_rawdata
#   linrampphase2vtxcol read_val2rgblut write_val2rgblut write_binary_areas
#   write_binary_surface write_ascii_surface write_vtk_surface
#   write_binary_curv write_binary_sulc write_binary_values write_mgh_values
#   write_vtk_values write_vtk_surface_plus_values write_binary_patch
#   write_labeled_vertices write_val_visible_vertices write_val_annoted_vertices
#   write_val_annotedcol_vertices write_label_timecourses_stats
#   write_annotcol_timecourses_stats write_annotcols_timecourses_stats
#   write_val_annotedcol_autoname
#   compute_dftamp2pcnt2stat write_fieldsign write_fieldsign_curvfmt
#   write_fsmask write_fsmask_curvfmt write_binary_dipoles
#   write_binary_decimation write_dipoles write_decimation subsample_dist
#   subsample_orient write_binary_subsample write_subsample write_curv_images
#   write_self_images write_fill_images fill_second_surface compute_curvature
#   compute_CMF compute_cortical_thickness clear_curvature
#   fill_nearest_vertices print_dist_last2_selected print_selected_list
#   write_val_selected_list_to_label
#   clear_ripflags clear_annot clear_vtxcol_labels
#   restore_ripflags fill_val_holes fill_annot_holes find_uniqsamp_vertices
#   select_uniqsamp_vertices find_retin_borders corr_over_annotcol 
#   corr_over_label floodfill_marked_patch uncut_connected_vertices
#   cut_vertices cut_line cut_plane clear_vertex_marks_list flatten
#   normalize_binary_curv normalize_area
#   clear_values clear_valbaks clear_stats clear_pvals clear_uniqvoxdata
#   copy_val_val2 (=shift_values) swap_val_val2 copy_val_dip
#   swap_valval2_valbakval2bak (=swap_values) swap_stat_val swap_pval_val
#   compute_grad_to_ori_in_baks compute_angles_vals_to_baks compute_angles
#   compute_fieldsign compute_gradient compute_phasecancel save_rgb
#   save_rgb_named_orig rotate_brain_x rotate_brain_y rotate_brain_z
#   translate_brain_x translate_brain_y translate_brain_z scale_brain
#   resize_window move_window raise_window do_lighting_model
#   restore_zero_position restore_initial_position make_lateral_view
#   make_lateral_view_second read_view_matrix write_view_matrix
#   read_really_matrix write_really_matrix really_translate_brain
#   really_scale_brain really_rotate_brain_x really_rotate_brain_y
#   really_rotate_brain_z really_center_brain really_center_second_brain
#   really_align_brain find_orig_vertex_coordinates
#   select_orig_vertex_coordinates select_talairach_point
#   read_orig_vertex_coordinates read_ellipsoid_vertex_coordinates
#   fix_nonzero_vals left_click order_qstrips draw_qstrip_surface
#   fill_surface click_vertex leftclick_vertex middleclick_vertex
#   compute_surfgrad write_uniqsamp_vertices pval_from_fourier_fstat
#   read_uniqsamp_vertices find_FDR_from_pvals write_off_surface
#   write_searchlights erode_annot prune_annotbord norm_move_vertices_fracthick
#   select_opphemi_vertex_coordinates

### tksurfer.c: C/tcl vars defined at startup
# boolean:
#   momentumflag expandflag stiffnessflag explodeflag MRIflag MRI2flag MRI3flag
#   sulcflag avgflag areaflag bordneiflag rmvtx2nonbordflag complexvalflag
#   overlayflag labelflag annotbordflag vtxcolflag ncthreshflag edgesflag
#   gradvecflag gradvecbakflag shearvecflag normvecflag movevecflag revfsflag
#   revphaseflag nonbinaryfsflag invphaseflag rectphaseflag truncphaseflag
#   fieldsignflag fsdata2gradsflag angoffrevarrflag arrownormflag flag2d
#   scalebarflag colscalebarflag pointsflag surfaceflag phasecontourflag 
#   phasecontoursflag curvimflag doublebufferflag smallscreenflag
#   openglwindowflag blinkflag renderoffscreen transform_loaded bigcursorflag
#   phasecontourmodflag promptflag followglwinflag colscalerectflag
#   fullpolrectflag noninteccendiskflag logtransflag statreplampflag
#   statmaskampflag statmultampflag showavgcycflag usecurrcoordsflag
#   erodingfillflag dilatingfillflag interpolatelutflag
#   zerosymmfadeflag botedgelutflag
#   isocontourflag undividequadsflag newquadoutputflag writefloatpatchflag
#   allverticesflag val2newcurvflag oldareafileflag newcurvareaoutputflag
#   tiffoutflag black2transparentflag debugflag statloadedflag pvalloadedflag
#   uniqvoxnumloadedflag uniqvoxcntloadedflag valloadedflag val2loadedflag
#   valbakloadedflag val2bakloadedflag annotloadedflag thicknessloadedflag
#   nativerealloadedflag nativeimagloadedflag nativemaskloadedflag
#   arealoaded area2loaded fieldsignloaded fillimloaded onemgzfileloaded
#   vals_cart2polarflag valbaks_cart2polarflag vals_grad2oriflag
#   valbaks_grad2oriflag chkselfintflag chkgradampflag chkfilledflag
#   chkthirdflag xcorrcovarflag searchlightuniqflag numafteruniqflag
#   normdfracflag normdsampsearchflag normdsampuniqvoxflag normdsampallflag
#   uniqvoxnumflag prunearrowsflag
#   bokflag tksurferlogflag roundregflag locklabelflag killfillflag
#   includeintersectingflag rmgradoutliersflag multitimecourseflag
#   gradvecbak3dflag normdsampuniqvtxflag paintTODOflag selfintersectloaded
#   curvloadedflag annotborddotflag
# int:
#   surfcolor mingm colscale ilat meshr meshg meshb
#   colr1 colg1 colb1 colr2 colg2 colb2 scalebar_bright project
#   phasecontour_bright phasecontours blinkdelay blinktime stopatface
#   stimcycles nmarked labelalpha val2rgblutcnt val2rgblutout isoconttype
#   forcemode chkthird_lolim chkthird_hilim glxdepth
#   stat_xdim stat_ydim stat_zdim normdop mghvalframe vtkvalcolumn
#   glxwinx glxwiny glxwinw glxwinh fillcolor3d
#   brainregioncnt searchlightvtxcnt noisedf
# double:
#   decay retinvtxfrac maxretinsearch minretindist 
#   fthresh fmid fslope sfthresh sfmid" sfslope fsslope fcurv cslope cmid
#   mslope mmid whitemid graymid mstrength stressthresh icstrength
#   angle_cycles angle_offset wt wa ws wn wc wsh wbn update decay cthk
#   light0 light1 light2 light3 light0x light0y light0z light1x
#   light2x light2y light2z light3x light3y light3z offset blufact cvfact
#   fadef ipsiyellowfact ncthresh" scalebar_xpos scalebar_ypos
#   colscalebar_height colscalebar_width colscalebar_xpos colscalebar_ypos
#   phasecontour_min phasecontour_max phasecontoursfrac dip_spacing
#   truncphasemin truncphasemax minstatcolscale maxstatcolscale
#   normdfracsamp normdfracmax sulfrac gyrfracgyrfrac normdsamp normdmax
#   normddstep rawdatarange contourspacingRL contourspacingAP contourspacingSI
#   contourlinewidthRL contourlinewidthAP contourlinewidthSI halfweightdist
#   gradampfac selfstilt preclustfthr clustarea filled_origarea filled_currarea
#   fillpix arrowscale pcntsigpk2pk wcrv wsta wcpx pval_FDR_BH
# string:
#   home subject hemi surfext curv thick sulc patch label anlabel lulabel
#   vclabel fs fm dip dec named_rgbdir rgb" csurftclenv insurf outsurf
#   targsurf targcurv targcurvim selfintersectim fillim gradampim
#   inim inim2 inim3 stat val area session isession scandir script
#   origcoords ellcoords sphcoords sphregcoords subjtmpdir transform
#   statpatt_r statpatt_i statpatt_m statpatt regdat rawdata template
#   val2rgblut tksurferinterface brainregionname genstrret_1k
#   pialcoords, whitecoords, wmgmext

### slider sizing
set sclenx    125  ;# 125,120,125
set scleny    104  ;# 100,90,104,107 (ipsiyellow->taller)
set sclenymag 120  ;# 118 (was scleny+15), 115

### save init surf for reload if bad surf
set surfextorig $surfext

### literal subdirs for setfile expansions (scandir is exported C var)
set surfdir surf
#set targdir surf
set fsdir fs
set prfdir prf
set scriptsdir scripts
set bemdir bem
set labeldir label
set rgbdir rgb
#set sessiondir $scandir
set mridir mri

### variable-name lists for diff types of setfile globbing
set sessionfiles { val rawdata statpatt statpatt_m regdat val2rgblut stat \
                   template }
set mrifiles { inim inim2 inim3 targcurvim selfintersectim fillim }
set surffiles { insurf outsurf curv sulc area thickness patch \
                origcoords whitecoords pialcoords \
                ellcoords vrmlsurf }
set targfiles { targsurf targcurv } 
set fsfiles { fs fm } 
set scriptsfiles { script } 
set bemfiles { dip dec } 
set labelfiles { label anlabel vclabel } ;# anlabel: read/write_mgh_annot label
set rgbfiles { rgb }
set rgbdirs { named_rgbdir }   ;# not files but same expansions

### lists of surfdir surfnames to look for, default scripts
set surflooklist {orig smoothwm white pial inflated sphere surftmp} ;#pat*->.reg
set curvlooklist { curv sulc area arat thickness }  ;# used as *${patt}*
set templatelooklist { average*.tif }  ;# used as *${patt}*
set arealooklist { area area.mid area.pial }  ;# used as *${patt}
set patchsufflooklist { 3d flat }
# TODO: next needs add custom, also to ExpertPrefs
set patchtypelooklist { cortex full occip smoothwm inflated }
set defscriptlist { #/offsetmovie.tcl #/phasemovie.tcl #/movie360.tcl \
                    #/inflatemovie.tcl #/flattenmovie.tcl \
                    #/annot2roi.tcl #/searchlightdiff.tcl \
                    #/searchlightarea.tcl #/explodemovie.tcl }

### current transforms
set xrot 0
set yrot 0
set zrot 0
set xtrans 0
set ytrans 0
set scalepercent 100 

### events
set userok 0
set blinkflag 0
set initdelay $blinkdelay
set runshrinkflag 0
set runmorphflag 0

### previous var values
set prevcolscale $colscale  ;# currently only "ltw" on "Col:" popup

### misc interface defaults (mostly pop-ups)
set glwinxydim 600
set num,sqmm,mm 250
set fillneartype 0   ;# 0=n,1=area,2=radius
set cmptype 0        ;# 0=RealReal,1=AmpReal,2=RealAmp,3=AmpAmp,4=PhasePhase
set optype 0         ;# 0=avg,1=count-intIDs,2=variance-subtr-cent
set shrinksteps 2    ;# update steps (num iterations passed to shrink()
set shrinkcycles 10  ;# num cycles redraws for each set of $shrinksteps
set smoothtype val   ;# curv/valonly/val/cpxreal/weight/sparse/grad
if ![info exists smoothsteps] { set smoothsteps 5 }  ;# leave csurf set w/env
set norm_move_mm_or_frac  -0.5
set avg_rawamp 0
set time_points 0
set xcorr_outstem A-xcorr-B
set val,weight val   ;# smoothtype
set desired_FDR 0.05
set uniqsampvtxflag 0
set histtype 1   ;# 0=curv,1=val,2=amp,3=ang,4=stat
set histbins 256
set histsmoothsteps 0
set selectcloseflag 0
set visible_idnums_list 0
set unmasked_to_label_flag 0
set unmasked_to_labels_flag 0
set newreadfulllabflag 0
set viewmatrixsuff ""
set sphvoltype 0
set write_mgz_for_debug_flag 0
set minsphdata -0.5
set maxsphdata 0.5
set scale_subbrik -1    ;# -1=noscale, 5=(zero-based) AFNI first eigenvalue
set xvect_subbrik 9     ;# 9=(zero-based) AFNI x-comp of 1st eigenvector
set normdsamp_pnt 2.5      ;# mm
set normdfracsamp_pnt 0.5  ;# fraction
set statANDhypotflag 0  ;# ROI does AND of stat and complex amp
set statANDrealflag 0   ;# ROI does AND of stat and real amp
set warnvtxcolflag 0    ;# warn vtxcol ON once
set lulabelcombo ""     ;# popup MGH LUT: hacks force read hacked ctrls combos
set anlabelcombo ""     ;# popup MGH annot
set gridsize 3.0        ;# approx desired spacing of gradient arrows */
set neighord 4          ;# for neighop_val2stat <neighorder> <op=3> paintballs
set annotedfrac 0.5     ;# for fill_annot_holes_neigh <neighord> <annotedfrac>
#set maxgradsearch  2.0  ;# searchlight version only
set mindiffphase   0.1  ;# neigh ang diff above this is reversal (0.5=180deg)
#set gradvtxfrac    1.0  ;# searchlight version only
set gradrevprobname gradrevprob_k

### non-modal popups
set regrawctrlswin ""
set labeltickctrlswin ""
set fstickctrlswin ""
set arrownormctrlswin ""
set valfiletypectrlswin ""
set writedftampctrlswin ""
set dtivecctrlswin ""
set sphimctrlswin ""
set corrctrlswin ""
set sampclustctrlswin ""
set lut2annotctrlswin ""
set fillholesneighctrlswin ""
set fdrctrlswin ""
set vmsuffctrlswin ""
set histctrlswin ""
set spotopctrlswin ""
set nonoverlap2statctrlswin ""
set annotmaskctrlswin ""
set isoconttickctrlswin ""
set lightsctrlswin ""
set findgradrevctrlswin ""
set halfweightctrlswin ""

### translate corr_over_label/annotcol numbered types to text
set fillnearname(0) "number vertices"
set fillnearname(1) "area"
set fillnearname(2) "radius"
set critname(0) "count"
set critname(1) "mm^2"
set critname(2) "mm"
set cmpname(0) "real/real"
set cmpname(1) "complex-amp <=> real"
set cmpname(2) "real/complex <=> amp"
set cmpname(3) "complex-amp <=> complex-amp"
set cmpname(4) "complex-phase <=> complex-phase"

### gcc/g++ conditional compile: maybe omit fonts interface widgets
set inclFTGLflag 1
if { ![info exists fontsize] || ![info exists areanamesflag] } {
  set inclFTGLflag 0
}

### log file to record interface-run tcl cmds (C-functs, vars)
#set tksurferlogflag 0  ;# clk "tcl:" toggles, don't override cmdline opt here

############################################################################
# procedures
############################################################################
proc no-op (args} {}
proc editfile { file } { ;# order: (vigterm,vixterm),TextEdit,gedit,nedit,xedit
  global env subject

  if [info exists env(CSURFEDITORVIGTERM)] {
    #set swp [file dirname $file]/.[file tail file].swp  ;# rm any
    #if [file exists $swp] { exec rm -f $swp }
    if [string match "*/tmp/TmpTclScript.tcl" $file] {
      set swp $env(SUBJECTS_DIR)/$subject/tmp/.[file tail $file].swp
      if [file exists $swp] { exec rm $swp }
    }
    if [foundbywhich gnome-terminal] {
      exec gnome-terminal --geometry +50+630 --execute vi "$file" >& /dev/null &
    } else {
      exec xterm -geometry +50+630 -e vi "$file" >& /dev/null & ;#nullelse huptk
    }
  } elseif [info exists env(CSURFEDITORVIXTERM)] {
    #set swp [file dirname $file]/.[file tail file].swp  ;# rm any
    #if [file exists $swp] { exec rm -f $swp }
    if [string match "*/tmp/TmpTclScript.tcl" $file] {
      set swp $env(SUBJECTS_DIR)/$subject/tmp/.[file tail $file].swp
      if [file exists $swp] { exec rm $swp }
    }
    if [foundbywhich xterm] {
      exec xterm -geometry +50+630 -e vi "$file" >& /dev/null & ;#nullelse huptk
    }  else { puts "tksurfer.tcl: ### xterm not found"}
  } else {
    foreach editor { /System/Applications/TextEdit.app/Contents/MacOS/TextEdit \
                     /Applications/TextEdit.app/Contents/MacOS/TextEdit \
                     gedit nedit xedit "" } {
      if [foundbywhich $editor] { break }
    }
    if {$editor == ""} {
      puts "tksurfer.tcl: ### no text editor found (tried TextEdit,gedit,xedit)"
    } elseif [string match *TextEdit $editor] {
      if ![file exists $file] { exec touch $file }
      update idletasks
      exec open -e "$file" >& /dev/null &  ;# N.B.: multiple TextEdits in bg
    } else {
      exec $editor "$file" >& /dev/null &
    }
  }
} ;#to null fixes: csurf->tksurfedit->csurfkill->csurf->killedit->killstksurfer

### tcl 'set' + csurf-specific glob + create/update widget abbrev vars
### N.B.: unlike glob, expansion *doesn't* require that file exists
### N.B.: since touches abbrev, e.g. select_curv callback testing exist may fail
### $home is startup value of $env(SUBJECTS_DIR)
proc setfile { varName value } {    ;# makes "varName"abbrev if doesn't exist
  ### csurf-specific globbing "set" ("~"-subject, "*"=isession, "#"=scriptsdir)
  upvar $varName localvar                 ;# setfile val */4/sig3-lh.w
  upvar ${varName}abbrev localabbrev      ;# setfile outsurf rh.new
  global home subject                     ;# setfile val /tmp/data.w
  global env                              ;# setfile script local.tcl
  global isession                         ;# setfile named_rgbdir ~/tmp/myrgb
  global sessionfiles                     ;# setfile script #/builtin.tcl
  global surfdir fsdir scriptsdir bemdir rgbdir labeldir mridir scandir prfdir
  global surffiles fsfiles scriptsfiles bemfiles rgbfiles labelfiles targfiles
  global mrifiles rgbdirs

  logcmd "setfile $varName $value"

  ### set subdir (for guess w/just relative) using varname, varnamelists
  set onebrainflag 1
  if       { [lsearch -exact $surffiles $varName] >= 0 } {
    set subdir $surfdir
  } elseif { [lsearch -exact $targfiles $varName] >= 0 } {
    set subdir $surfdir
    set onebrainflag 0
  } elseif { [lsearch -exact $fsfiles $varName] >= 0 } {
    set subdir $fsdir
  } elseif { [lsearch -exact $scriptsfiles $varName] >= 0 } {
    set subdir $scriptsdir
  } elseif { [lsearch -exact $bemfiles $varName] >= 0 } {
    set subdir $bemdir
  } elseif { [lsearch -exact $labelfiles $varName] >= 0 } {
    set subdir $labeldir ;#N.B.: samlabels not $subject/labels but $subject/prf
    set onebrainflag 0  ;# for fsaverage-equiv created by AVGSURF
  } elseif { [lsearch -exact $rgbfiles $varName] >= 0 } {
    set subdir $rgbdir
  } elseif { [lsearch -exact $rgbdirs $varName] >= 0 } {
    set subdir $scandir
  } elseif { [lsearch -exact $sessionfiles $varName] >= 0 } {
    set subdir $scandir
  } elseif { [lsearch -exact $mrifiles $varName] >= 0 } {
    set subdir $mridir
  } else {
    puts "bad arg: don't know how to set/glob file type: $varName"
    puts "  setfile {$surffiles} value"
    puts "  setfile {$mrifiles} value"
    puts "  setfile {$targfiles} value (~name OK)"
    puts "  setfile {$fsfiles} value"
    puts "  setfile {$scriptsfiles} value"
    puts "  setfile {$bemfiles} value"
    puts "  setfile {$labelfiles} value"
    puts "  setfile {$rgbfiles} value"
    puts "  setfile {$rgbdirs} value"
    puts "  setfile {$sessionfiles} value"
    prompt
    return
  } 

  ### do csurf-specific glob expansions for fullname (usu. override subdir)
  if { [string range $value 0 0] == "/"} {
    set fullname $value
  } elseif { [string range $value 0 0] == "~"} {
    if { [string range $value 1 1] != "/" } {
      if {$onebrainflag} {
        puts "other subjects only allowed for targfiles: $targfiles" 
        prompt
        return
      }
      set tildegone [string range $value 1 end]
      set tmpsubject [file dirname $tildegone]
      set subdir [file dirname [file tail $tildegone]]
      set filename [file tail [file tail $tildegone]]
    } else {
      set tildegone [string range $value 2 end]
      set tmpsubject $subject
      set subdir [file dirname $tildegone]    ;# overwrite, may be multilevel
      set filename [file tail $tildegone]
    }
    if { $subdir == "." } { 
      set fullname $home/$tmpsubject/$filename
    } else {
      set fullname $home/$tmpsubject/$subdir/$filename
    }
  } elseif { [string range $value 0 0] == "*"} {
    set stargone [string range $value 2 end]
    set fullname $isession/$stargone
  } elseif { [string range $value 0 0] == "#" } {
    set poundgone [string range $value 2 end]
    set fullname $env(CSURF_DIR)/lib/tcl/$poundgone
  } else {  ;# relative (guess session vs. subjects vs. pwd)
    if {$subdir == $surfdir} {
      set fullname $home/$subject/$subdir/$value
    } elseif {$subdir == $bemdir} {
      set fullname $home/$subject/$subdir/$value
    } elseif { $subdir == $fsdir } {
      set fullname $isession/$subdir/$value
    } elseif { $subdir == $labeldir} {
      set fullname $home/$subject/$subdir/$value  ;# was dropthru to session!
    } elseif {$subdir == $scriptsdir} {
      set fullname [exec pwd]/$value
    } elseif { $subdir == $mridir } {
      set fullname $home/$subject/$subdir/$value
    } elseif { $subdir == $prfdir} { ;# never: setfile label guesses dir=label
      set fullname $home/$subject/$subdir/$value
    } elseif { $subdir == "." } {
      set fullname $isession/$value
    } else {
      set fullname $isession/$subdir/$value
    }
  }
  set localvar $fullname
  #puts $fullname

  ### attempt re-abbrev for entry vars (first ~, then *, else #, else abs)
  # N.B.: touching abbrev vars bound to tixCombos will trigger their callbacks
  if {$varName != "script"} {
    set homename $home/$subject
    set homelen [string length $homename]
    set endhome [incr homelen -1]
    set begintail [incr homelen 1]
    if { "$homename" == "[string range $fullname 0 $endhome]" } {
      # block callbacks to read_binary_{curv,areas,patch} from touch 3 abbrev's
      if { $varName == "patch" && [winfo exists .files.patch.cbx] } {
        .files.patch.cbx config -disablecallback true
      }
      if { $varName == "curv" && [winfo exists .files.ca.curv.cbx] } {
        .files.ca.curv.cbx config -disablecallback true
      }
      if { $varName == "area" && [winfo exists .files.ca.area.cbx] } {
        .files.ca.area.cbx config -disablecallback true
      }

      set localabbrev ~[string range $fullname $begintail end]

      if { $varName == "patch" && [winfo exists .files.patch.cbx] } {
        .files.patch.cbx config -disablecallback false
      }
      if { $varName == "curv" && [winfo exists .files.ca.curv.cbx] } {
        .files.ca.curv.cbx config -disablecallback false
      }
      if { $varName == "area" && [winfo exists .files.ca.area.cbx] } {
        .files.ca.area.cbx config -disablecallback false
      }
      return
    }
    set sessionlen [string length $isession]
    set endsession [incr sessionlen -1]
    set begintail [incr sessionlen 1]
    if { "$isession" == "[string range $fullname 0 $endsession]" } {
      # in case curv/area read/write files in a session dir
      if { $varName == "curv" && [winfo exists .files.ca.curv.cbx] } {
        .files.ca.curv.cbx config -disablecallback true
      }
      if { $varName == "area" && [winfo exists .files.ca.area.cbx] } {
        .files.ca.area.cbx config -disablecallback true
      }

      set localabbrev *[string range $fullname $begintail end]

      if { $varName == "curv" && [winfo exists .files.ca.curv.cbx] } {
        .files.ca.curv.cbx config -disablecallback false
      }
      if { $varName == "area" && [winfo exists .files.ca.area.cbx] } {
        .files.ca.area.cbx config -disablecallback false
      }
      return
    }
  } else {
    set scripthome $env(CSURF_DIR)/lib/tcl
    set scripthomelen [string length $scripthome]
    set endscript [incr scripthomelen -1]
    set begintail [incr scripthomelen 1]
    if { "$scripthome" == "[string range $fullname 0 $endscript]" } {
      set localabbrev #[string range $fullname $begintail end]
      return
    }
  }
  set localabbrev $fullname
}

proc listcmd_tcl { combo } {
  global env subject isession scriptsdir defscriptlist scriptabbrev

  set fullfunctlist [lsort [glob -nocomplain $isession/$scriptsdir/*.tcl]]
  set fullsubjectlist \
    [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$scriptsdir/*.tcl]]
  set abbrevlist "{==== DEFAULT LIB SCRIPTS ====}"
  foreach deffile $defscriptlist {
    set abbrevlist "$abbrevlist $deffile"  ;# already abbreviated
  }
  ### next 2: manually re-abbreviate vs. clog log with many setfiles
  if { "$env(SUBJECTS_DIR)/$subject/$scriptsdir" != "$isession/$scriptsdir" } {
    set abbrevlist "$abbrevlist {==== LOCAL FUNCT SCRIPTS ====}"
    foreach fullfile $fullfunctlist {
      #setfile script $fullfile; set abbrevlist "$abbrevlist $scriptabbrev"
      set abbrevlist "$abbrevlist */$scriptsdir/[file tail $fullfile]"
    }
  }
  set abbrevlist "$abbrevlist {==== LOCAL SUBJECT SCRIPTS ====}"
  foreach fullfile $fullsubjectlist {
    #setfile script $fullfile; set abbrevlist "$abbrevlist $scriptabbrev"
    set abbrevlist "$abbrevlist ~/$scriptsdir/[file tail $fullfile]"
  }
  #set abbrevlist "$abbrevlist {==== STARTUP (can't re-run) ====}"
  #set abbrevlist "$abbrevlist $currabbrev"
  set abbrevlist "$abbrevlist {==== TEMP (for testing) ====}"
  set abbrevlist "$abbrevlist ~/tmp/TmpTclScript.tcl"
  $combo subwidget listbox delete 0 end
  foreach abbrev $abbrevlist { $combo insert end $abbrev }
}

proc select_script { combo selected_item } {  ;# gets here twice per select
  global defscriptlist scriptabbrev

  # N.B.: tixComboBox does -command on: (1) ComboBox invoke, (2) -value changes
  ###TODO: lastselected_item (-value already updated so can't chk changed here)
  foreach scr $defscriptlist {
    if {"$scr" == "$scriptabbrev"} {
      $combo config -disablecallback true   ;# rm's extra pair calls to here
      ## next stopped working when command changed to bind (to use break) 
      #.subhead.script.aGO.bu invoke        ;# also ignores second call
      update idletasks   ;# else sometime random cmds
      event generate .subhead.script.aGO.bu <ButtonRelease-1> ;#for bind no-cmd
      $combo config -disablecallback false
      break
    }
  }
}

proc select_coordstype { buname bustate } {  ;# manage binary flags
  global usecurrcoordsflag usetalcoordsflag xform_mni_305to152_flag
  global insurf origcoords c2lab

  # N.B.: if radio action, gets in proc 2x: once for up, again for other down
  if {$buname == "cu" && $bustate == 0 && $c2lab != "ta"} { ;#block->OFF ifradio
    set usecurrcoordsflag 0;       logcmd "set usecurrcoordsflag 0"
    set usetalcoordsflag 0;        logcmd "set usetalcoordsflag 0"
    set xform_mni_305to152_flag 0; logcmd "set xform_mni_305to152_flag 0"
    confirmalert "Write label vertex coords from orig surface:\
              \n\n    [file tail $origcoords]\
              \n\n(default state)"
  }
  if {$buname == "cu" && $bustate == 1} {
    set usecurrcoordsflag 1;       logcmd "set usecurrcoordsflag 1"
    set usetalcoordsflag 0;        logcmd "set usetalcoordsflag 0"
    set xform_mni_305to152_flag 0; logcmd "set xform_mni_305to152_flag 0"
    confirmalert "Write label vertex coords from curr surface:\
              \n\n    [file tail $insurf]\
              \n\n(vs. coords from orig surface: [file tail $origcoords])"
  }
  if {$buname == "ta" && $bustate == 0 && $c2lab != "cu"} { ;#block->OFF ifradio
    set usecurrcoordsflag 0;       logcmd "set usecurrcoordsflag 0"
    set usetalcoordsflag 0;        logcmd "set usetalcoordsflag 0"
    set xform_mni_305to152_flag 0; logcmd "set xform_mni_305to152_flag 0"
    confirmalert "Write label vertex coords from orig surface:\
              \n\n    [file tail $origcoords]\
              \n\n(default state)"
  }
  if {$buname == "ta" && $bustate == 1} {
    set usetalcoordsflag 1;  logcmd "set usetalcoordsflag 1"
    set usecurrcoordsflag 0; logcmd "set usecurrcoordsflag 0"
    if [okreplace "" "Choose Talairach coords type\
                    \n(written to subsequent label files):\
                  \n\n    MNI 305 (default freesurfer)\
                  \n\n         *or*\
                  \n\n    transform to MNI 152" \
                      "Use MNI 305" none "Use MNI 152" ] {
      set xform_mni_305to152_flag 0;   logcmd "set xform_mni_305to152_flag 0"
      confirmalert \
          "Write label vtx coords by converting orig surface coords to:\
       \n\n    MNI 305 Talairach\
       \n\n(vs. coords from orig surface: [file tail $origcoords])"
    } else {  ;# cancel with alt name
      set xform_mni_305to152_flag 1;   logcmd "set xform_mni_305to152_flag 1"
      confirmalert \
          "Write label vtx coords by converting orig surface coords to:\
       \n\n    MNI 152 Talairach\
       \n\n(vs. coords from orig surface: [file tail $origcoords])"
    }
  }
  #if {$c2lab == ""} { ; }  ;# HOWTO catch either to OFF
}

proc report_curr_labelcoords { } {
  global usecurrcoordsflag usetalcoordsflag xform_mni_305to152_flag

  if {$usecurrcoordsflag } {
    confirmalert "Current label coords setting:\
              \n\ncurrent surface coords will be written in subsequent labels\
              \n\n(to change, untick \"cu\" or tick \"ta\")"
  } elseif {$usetalcoordsflag} {
    if {$xform_mni_305to152_flag} {
      confirmalert "Current label coords setting:\
                \n\nMNI 152 coords will be written to subsequent labels\
                \n\n(to change, untick and re-tick \"ta\")"
    } else {
      confirmalert "Current label coords setting:\
                \n\nMNI 305 coords will be written in subsequent labels\
                \n\n(to change, untick and re-tick \"ta\")"
    }
  } else {
    confirmalert "Current label coords setting:\
              \n\n.orig coords will be written to subsequent labels\
              \n\n(to change, tick \"ta\" or \"cu\")"
  }
}

proc writevtxcols { } {
  global label labelabbrev vclabel genstrret_1k

  setfile label [.files.label.cbx subwidget entry get]
  if { [file extension $label] != ".cols" } {  ;# in case direct use tclfunct
    confirmalert "Bad vtxcol label suffix:\n\n    $label\n\nmust be *.cols"
    return
  }
  if ![canwriteormakefile $label] {
    confirmalert "Permissions don't allow create vtxcol label:\n\n    $label"
    return
  }
  if {$genstrret_1k == 0} {
    confirmalert "No vtxcol's loaded"
    return
  }
  set vclabel $label  ;# vclabel only used for C/tcl {read,write}_vtxcol_label
  logcmd "set vclabel $label"
  testreplace $vclabel write_vtxcol_label  ;# logs
}

proc labeltovtxcols { } {
  global label labelabbrev vclabel

  setfile label [.files.label.cbx subwidget entry get]
  # N.B.: $vclabel only used by {read,write}_vtxcol_label C-functs
  # N.B.: label_to_vtxcol_label C-funct uses $label, does .label->.cols convert
  # N.B.: $vclabel set here only for overwrite test below
  set vclabel [file rootname $label].cols
  logcmd "set vclabel [file rootname $label].cols"
  if ![canwriteormakefile $vclabel] {
    confirmalert "Permissions don't allow create vtxcol label:\n\n    $vclabel"
    return
  }
  testreplace $vclabel label_to_vtxcol_label  ;# logs
}

proc readvtxcols { } {  ;# accept *.label or *.cols
  global label labelabbrev vclabel warnvtxcolflag

  setfile label [.files.label.cbx subwidget entry get]
  if ![checkreadlabeldir] { return }  ;# generates error msg
  if [string match *.label $label] {
    set vclabel [file rootname $label].cols
    logcmd "set vclabel [file rootname $label].cols"
  } elseif [string match *.cols $label] {
    set vclabel $label
    logcmd "set vclabel $label"
  } else { return }
  read_vtxcol_label
  logcmd "read_vtxcol_label"
  set warnvtxcolflag 1   ;# two warnings? (e.g., init and after 5 redraws?)
}

proc mriforce { updown } {
  global stressthresh mmid whitemid graymid
  if { $updown == "up" } {
    set mmid [expr $mmid + 1.0]
    logcmd "set mmid $mmid"
    #set whitemid [expr $whitemid + 1.0]
    #set graymid [expr $graymid + 1.0]
    set stressthresh [expr $stressthresh * 1.1]
    logcmd "set stressthresh $stressthresh"
  } elseif { $updown == "down" } {
    set mmid [expr $mmid - 1.0]
    logcmd "set mmid $mmid"
    #set whitemid [expr $whitemid - 1.0]
    #set graymid [expr $graymid - 1.0]
    set stressthresh [expr $stressthresh / 1.1]
    logcmd "set stressthresh $stressthresh"
  }
}

proc listcmd_val { combo } {
  global env subject isession scandir hemi surfdir labeldir
  #global val valabbrev

  # *.mgh, *.crv, *.vtk don't check hemisphere (no standard pattern)
  set fullfilelist1 [lsort [glob -nocomplain $isession/$scandir/*-$hemi.w]]
  set fullfilelist2 [lsort [glob -nocomplain $isession/$scandir/*.mgh]]
  set fullfilelist3 [lsort [glob -nocomplain $isession/$scandir/*.crv]]
  set fullfilelist4 [lsort [glob -nocomplain $isession/$scandir/*.vtk]]
  set fullfilelist5 \
    [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*.vtk]]
  set fullfilelist6 ""
  if {$hemi == "rh"} { set h R }
  if {$hemi == "lh"} { set h L }
  set fullfilelist6 \
[lsort [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*.$h.*.shape.gii]]
  set fullfilelist7 \
[lsort [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*.$h.*.func.gii]]
  set fullfilelist8 \
    [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*-$hemi.w]]
  set fullfilelist9 \
    [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*.mgh]]
  set fullfilelist10 [lsort [glob -nocomplain $isession/$scandir/*_000.bfloat]]
  set fullfilelist11 \
    [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*_000.bfloat]]
  set fullfilelist12 \
    [lsort [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$labeldir/*-?h.w]]

  ### next: manually re-abbreviate vs. clog log with many setfiles
  set abbrevlist "{==== SCANDIR VALFILES ====}"
  foreach fullfile "$fullfilelist1 $fullfilelist2 $fullfilelist3 \
    $fullfilelist4 $fullfilelist10" {
    #setfile val $fullfile; set abbrevlist "$abbrevlist $valabbrev"
    set abbrevlist "$abbrevlist */$scandir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== SUBJECTDIR VALFILES ====}"
  foreach fullfile "$fullfilelist5 $fullfilelist6 $fullfilelist7 \
    $fullfilelist8 $fullfilelist9 $fullfilelist11" {
    #setfile val $fullfile; set abbrevlist "$abbrevlist $valabbrev"
    set abbrevlist "$abbrevlist ~/$surfdir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== LABELDIR VALFILES ====}"
  foreach fullfile "$fullfilelist12" {
    #setfile val $fullfile; set abbrevlist "$abbrevlist $valabbrev"
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }

  $combo subwidget listbox delete 0 end
  foreach abbrev $abbrevlist { $combo insert end $abbrev }
}

proc read_realcomplex_or_samcomplex_label_to_val { } {
  global label labelabbrev hemi complexvalflag

  set type realcomplex
  if { [string match ${hemi}_pRF*_ecc_r.label [file tail $label]] || \
       [string match ${hemi}_pRF*_ecc_i.label [file tail $label]] } {
    set type samecc
  }
  if { [string match ${hemi}_pRF*_pol_r.label [file tail $label]] || \
       [string match ${hemi}_pRF*_pol_i.label [file tail $label]] } {
    set type sampol
  }

  if {$type == "realcomplex"} {
    read_label_to_val 0  ;# handles real (5col) or complex (6col) csurf label
    logcmd "read_label_to_val 0"
  }

  # special case: read SamPrf complex labels as two reals
  if {$type == "samecc" || $type == "sampol"} {
    set len [string length $label]
    set stem [string range $label 0 [expr $len - 9]]
    # read imaginary (as real 1-val-column label)
    set complexvalflag 0
    logcmd "set complexvalflag 0"
    setfile label ${stem}_i.label
    read_label_to_val 0
    logcmd "read_label_to_val 0"
    swap_val_val2
    logcmd "swap_val_val2"
    # read real (as real)
    setfile label ${stem}_r.label
    read_label_to_val 0
    logcmd "read_label_to_val 0"
    # fix colscale
    fix_samcomplex_colscale $type
  }
}

proc fix_samcomplex_colscale { type } {
  global complexvalflag angle_offset angle_cycles revphaseflag
  global colscale fthresh fmid fslope

  if {$type != "samecc" && $type != "sampol"} { return }

  set complexvalflag 1
  logcmd "set complexvalflag 1"
  set colscale 0
  logcmd "set colscale 0"
  set fthresh 0.0
  logcmd "set fthresh 0.0"
  set fmid 0.025
  logcmd "set fmid 0.025"
  set fslope 100.0
  logcmd "set fslope 100.0"
  if {$type == "samecc"} {
    set angle_cycles 1.0
    logcmd "set angle_cycles 1.0"
    set angle_offset 0.0
    logcmd "set angle_offset 0.0"
  }
  if {$type == "sampol"} {
    set angle_cycles 2.001
    logcmd "set angle_cycles 2.001"
    # N.B.: Sam polar uses same offset/reverse in both hemis!
    set angle_offset 0.5
    logcmd "set angle_offset 0.5"
    set revphaseflag 1
    logcmd "set revphaseflag 1"
  }
}

proc read_real_or_complex_binary_values { } {  ;# val: R button wrapper
  global val valabbrev complexvalflag hemi vertexcnt
  global frmctrlswin mghvalframe genstrret_1k
  global colctrlswin vtkvalcolumn colscale

  set goodinf 0
  set len [string length $val]
  if [string match *.w $val] {
    set vhemi [string range $val [expr $len - 4] [expr $len - 3]]  ;# neg->0
    set vinf [string range $val [expr $len - 7] [expr $len - 6]]
    set vstem [string range $val 0 [expr $len - 8]]
    if { $vinf == "_r" || $vinf == "_i" || $vinf == "_x" || $vinf == "_y" } {
      set goodinf 1
    }
  }
  if [string match *_000.bfloat $val] {
    set vhemi [string range $val [expr $len - 13] [expr $len - 12]]  ;# neg->0
    set vinf [string range $val [expr $len - 16] [expr $len - 15]]
    set vstem [string range $val 0 [expr $len - 17]]
    if { $vinf == "_r" || $vinf == "_i" || $vinf == "_x" || $vinf == "_y" } {
      set goodinf 1
    }
  }

  ### given one wfile, auto-read pair of valfiles for complex data
  if  { $complexvalflag && [string match *_?-?h.w $val] && $goodinf } {
    if { $vinf == "_r" || $vinf == "_i"} { set real _r; set imag _i }
    if { $vinf == "_x" || $vinf == "_y"} { set real _x; set imag _y }
    set vinf $imag
    setfile val ${vstem}${vinf}-${vhemi}.w
    if ![file exists $val] {
      confirmalert "val file:\n\n    $val\n\nnot found"
      return
    }
    read_binary_values
    logcmd "read_binary_values"
    copy_val_val2
    logcmd "copy_val_val2"
    set vinf $real
    setfile val ${vstem}${vinf}-${vhemi}.w
    read_binary_values
    logcmd "read_binary_values"
    # fix colscale if match SamSrf names (reformated by prf2sess label->wfile)
    if { [string match pRF*_ecc_r-$hemi.w [file tail $val]] || \
         [string match pRF*_ecc_i-$hemi.w [file tail $val]] } {
      fix_samcomplex_colscale samecc
    }
    if { [string match pRF*_pol_r-$hemi.w [file tail $val]] || \
         [string match pRF*_pol_i-$hemi.w [file tail $val]] } {
      fix_samcomplex_colscale sampol
    }
### don't need now since complexvalflag tick fixes
    #if {$complexvalflag} {
    #  if {$colscale == 6 || $colscale == 9 || $colscale == 11 ||
    #      $colscale == 12} {
    #    confirmalert "Complex-valued data may be incorrectly displayed\
    #                \nbecause real-valued color scale ($colscale) selected\
    #              \n\nFix: choose complex-valued color scale (e.g., \"w1\")"
    #  }
    #}
  } elseif { $complexvalflag && [string match *_?-?h_000.bfloat $val] &&
              $goodinf } {
    if { $vinf == "_r" || $vinf == "_i"} { set real _r; set imag _i }
    if { $vinf == "_x" || $vinf == "_y"} { set real _x; set imag _y }
    set vinf $imag
    setfile val ${vstem}${vinf}-${vhemi}_000.bfloat
    if ![file exists $val] {
      confirmalert "bfloat file:\n\n    $val\n\nnot found"
      return
    }
    read_binary_values
    logcmd "read_binary_values"
    copy_val_val2
    logcmd "copy_val_val2"
    set vinf $real
    setfile val ${vstem}${vinf}-${vhemi}_000.bfloat
    read_binary_values
    logcmd "read_binary_values"
  } else {  ;# read one file
    if ![file exists $val] {
      confirmalert "val file:\n\n    $val\n\nnot found"
      return
    }
    if [string match *.mgh $val] {  ;# MGH file
      if {$hemi == "lh" && [string match *.rh.* $val] } {
        confirmalert "Selected valfile name:\
                  \n\n    $val\
                  \n\ncontains an \"*.rh.*\" (but current hemi is: lh)\
                  \n\nPerhaps file belongs to other hemisphere?"
      }
      if {$hemi == "rh" && [string match *.lh.* $val] } {
        confirmalert "Selected valfile name:\
                  \n\n    $val\
                  \n\ncontains an \"*.lh.*\" (but current hemi is: rh)\
                  \n\nPerhaps file belongs to other hemisphere?"
      }
      read_mgh_header
      set nframes 0
      foreach line [split $genstrret_1k "\n"] {
        if { [lindex $line 0] == "version" } { set version [lindex $line 2] }
        if { [lindex $line 0] == "width" }   { set width   [lindex $line 2] }
        if { [lindex $line 0] == "height" }  { set height  [lindex $line 2] }
        if { [lindex $line 0] == "depth" }   { set depth   [lindex $line 2] }
        if { [lindex $line 0] == "nframes" } { set nframes [lindex $line 2] }
        if { [lindex $line 0] == "type" }    { set type    [lindex $line 2] }
      }
      # TODO: other read_binary_values checks to provide non-log feedback
      if {$nframes < 1} {
        confirmalert "read_mgh_header: found bad nframes: $nframes"
        return
      } elseif {$nframes == 1} {
        set mghvalframe 0  ;# N.B.: silent override/reset if not 0
        readmghvalframe
      } else {
        set title "This .mgh file has $nframes frames\
                 \nPick one (first frame=0, last=[expr $nframes - 1])"
        set frmctrlswin [controls $title mghvalframe "READY" readmghvalframe]
      }
      checkrealcolscale
    } elseif [string match *.vtk $val] {  ;# VTK file
      set ncols 0
      catch { set line1 [exec head -n 1 $val] } ret
      if { ![string match "# vtk DataFile Version*" $line1] &&
           ![string match "POINT_DATA*" $line1] } {
        confirmalert "First line of .vtk val file:\
                  \n\n    $line1\
                  \n\ndoesn't match one of these:\
                  \n\n    (1) \"# vtk DataFile Version ...\"\
                    \n    (2) \"POINT_DATA ...\"
                    \n... vtk file NOT read"
        return
      }
      set patt "SCALARS EmbedVertex"
      if { [catch { set line [exec grep "$patt" $val] } ret] } {
        confirmalert "search for \"$patt\" in vtk file failed:\
                  \n\ngrep \"$patt\" $val\
                  \n\n... vtk file NOT read"
        return
      } else {
        set ncols [lindex $ret 3]  ;# full line: SCALARS EmbedVertex float 21
        if {$ncols < 1} {
          confirmalert "grep .vtk file: found bad num columns: $ncols"
          return
        } elseif {$ncols == 1} {
          set vtkvalcolumn 0  ;# N.B.: silent override/reset if not 0
          readvtkvalcolumn
        } else {
          set title "This .vtx file has $ncols columns\
                 \n\nPick one (first col=0, last=[expr $ncols - 1])"
          set colctrlswin \
            [controls $title vtkvalcolumn "READY" readvtkvalcolumn]
        }
      }
      checkrealcolscale
    } elseif [string match *_000.bfloat $val] {  ;# 1D BFLOAT file
      set hdr [string range $val 0 [expr [string length $val] - 8]].hdr
      if ![file exists $hdr] {
        confirmalert "Header file corresponding to bfloat file:\
                  \n\n    $hdr\
                  \n\nnot found\
                  \n\nbfloat file NOT read"
        return
      }
      set id [open $hdr r]
      set lines [split [read -nonewline $id] "\n"]
      close $id
      set hdrvcnt [lindex [lindex $lines 0] 1]
      if { $hdrvcnt != $vertexcnt } {
        confirmalert "bfloat header file vertex count:\
                  \n\n    $hdrvcnt\
                  \n\ndoesn't match current surface vertex count:\
                  \n\n    $vertexcnt\
                  \n\nbfloat file NOT read"
        return
      } 
      read_binary_values
    } else {  ;# original *.w file
      read_binary_values
      logcmd "read_binary_values"
    }
  }
}

proc readmghvalframe { } {
  global frmctrlswin mghvalframe

  puts "using zero-based .mgh file frame: $mghvalframe"
  logcmd "set mghvalframe $mghvalframe"
  read_binary_values
  logcmd "read_binary_values"
  if { [info exists frmctrlswin] && [winfo exists $frmctrlswin] } {
    destroy $frmctrlswin
    set frmctrlswin ""
  }
  redrawbutton ;#read_real_or.. returns so R buttproc redraws before ctrls resp
}

proc readvtkvalcolumn { } {
  global colctrlswin vtkvalcolumn

  puts "using zero-based .vtk file column: $vtkvalcolumn"
  logcmd "set vtkvalcolumn $vtkvalcolumn"
  read_binary_values
  logcmd "read_binary_values"
  if { [info exists colctrlswin] && [winfo exists $colctrlswin] } {
    destroy $colctrlswin
    set colctrlswin ""
  }
  redrawbutton ;#read_real_or.. returns so R buttproc redraws before ctrls resp
}

proc readtemplateframe { } {
  global tfrmctrlswin templateframe

  puts "using zero-based .tif file frame: $templateframe"
  logcmd "set templateframe $templateframe"
  read_tif_template
  logcmd "read_tif_template"
  ### move to select_curv, don't kill if same template
  #if { [info exists tfrmctrlswin] && [winfo exists $tfrmctrlswin] } {
  #  destroy $tfrmctrlswin
  #  set tfrmctrlswin ""
  #}
  redrawbutton
}

proc read_real_or_complex_native_stats { } {
  global statpatt statpattabbrev complexvalflag colscale

  ## try to determine 3d file type by infix and suffix
  set suff unknown
  set filetype3d unknown
  if { [string match *_r+orig.BRIK $statpatt] || \
       [string match *_i+orig.BRIK $statpatt] } {
    set realinfix _r
    set imaginfix _i
    set filetype3d complex
    set suff +orig.BRIK
  }
  if { [string match *_r_%03d.bfloat $statpatt] || \
       [string match *_i_%03d.bfloat $statpatt] } {
    set realinfix _r
    set imaginfix _i
    set filetype3d complex
    set suff _%03d.bfloat
  }
  if { [string match *_x+orig.BRIK $statpatt] || \
       [string match *_y+orig.BRIK $statpatt] } {
    set realinfix _x
    set imaginfix _y
    set filetype3d complex
    set suff +orig.BRIK
  }
  if { [string match *_x_%03d.bfloat $statpatt] || \
       [string match *_y_%03d.bfloat $statpatt] } {
    set realinfix _x
    set imaginfix _y
    set filetype3d complex
    set suff _%03d.bfloat
  }
  if { [string match *_f+orig.BRIK $statpatt] } {
    set realinfix _f
    set filetype3d real
    set suff +orig.BRIK
  }
  if { [string match *_f_%03d.bfloat $statpatt] } {
    set realinfix _f
    set filetype3d real
    set suff _%03d.bfloat
  }
  if { [string match *_h+orig.BRIK $statpatt] } {
    set realinfix _h
    set filetype3d real
    set suff +orig.BRIK
  }
  if { [string match *_h_%03d.bfloat $statpatt] } {
    set realinfix _h
    set filetype3d real
    set suff _%03d.bfloat
  }

  ## if rec'd filetype3d type, check/warn/fix complexvalflag/colscale mismatch
  set warn ""
  if {$filetype3d == "complex" && !$complexvalflag} {
    set warn "3d data file to be read:\
              \n\n    $statpatt\
              \n\nis one of a complex-valued pair,\
              \nso changing colscale:\
              \n\n   \"cpx\" -> ON\
                \n    colorscale ->\"w1\"" 
    set complexvalflag 1
    set colscale 0
  } elseif {$filetype3d == "real" && $complexvalflag} {
    set warn "3d data file to be read:\
              \n\n    $statpatt\
              \n\nis real-valued stat, so changing colscale:\
              \n\n   \"cpx\" -> OFF\
                \n    colorscale ->\"BR\"" 
    set complexvalflag 0
    set colscale 6
  } else { ; }

  ## help (combine warn/help)
  set msg "N.B.: 3d data file just read will not be visible\
           \nuntil sampled to surface with \"PA\" (PAINT) button\
           \n\nN.B.: adjust sample-to-surface parms before PAINT\
           \n(use pop-up from L-click \"label:\")"
  if {"$warn" != ""} {set msg $warn\n\n-------------------------------\n\n$msg}
  confirmalert $msg

  # read files
  if {$complexvalflag && $suff != "unknown"} {  ;# 3: zero-based + 2 infixchars
    set stemend [expr [string length $statpatt] - [string length $suff] - 3]
    set stem [string range $statpatt 0 $stemend]
    setfile statpatt ${stem}${realinfix}${suff}
    set firstfile $statpatt
    if [string match *.bfloat $statpatt] {set firstfile [format "$statpatt" 0]}
    if ![file exists $firstfile] {
      confirmalert "val3d file:\n\n    $firstfile\n\nnot found"
      return
    }
    read_native_stat 0
    logcmd "read_native_stat 0"
    setfile statpatt ${stem}${imaginfix}${suff}
    set firstfile $statpatt
    if [string match *.bfloat $statpatt] {set firstfile [format "$statpatt" 0]}
    if ![file exists $firstfile] {
      confirmalert "val3d file:\n\n    $firstfile\n\nnot found"
      return
    }
    read_native_stat 1
    logcmd "read_native_stat 1"
  } else {
    set firstfile $statpatt
    if [string match *.bfloat $statpatt] {set firstfile [format "$statpatt" 0]}
    if ![file exists $firstfile] {
      confirmalert "val3d file:\n\n    $firstfile\n\nnot found"
      return
    }
    read_native_stat 0  ;# real
    logcmd "read_native_stat 0"
  }
}

proc fix_statpatt_if_bfloat { } {  ;# example bfloat -> printf, before read
  global statpatt statpattabbrev
  if { [string match *_???.bfloat $statpatt] } {
    set stem [string range $statpatt 0 [expr [string length $statpatt] - 12]]
    setfile statpatt ${stem}_%03d.bfloat   ;# also remakes abbrev (=entry)
  }
}

proc brikfromval { } {  ;# get predecessor BRIK of curr wfile
  global isession scandir hemi val valabbrev statpatt statpattabbrev
  set fullfilelist [glob -nocomplain $isession/$scandir/*+orig.BRIK]
  set found 0
  setfile val $valabbrev   ;# freshen val (valabbrev -> val)
  if [string match *-$hemi.w $val] {
    set targ [string range $val 0 [expr [string length $val] - 6]]+orig.BRIK
    foreach file $fullfilelist {
      if {"$file" == "$targ"} { set found 1 }
    }
  }
  if {$found} {
    setfile statpatt $targ
  } elseif [llength fullfilelist] {
    setfile statpatt [lindex $fullfilelist 0]
  } else { ;  }
}

proc paint_real_or_complex { { smoothflag 0 } } {
  global complexvalflag regdat thicknessloadedflag
  global normdfracflag normdsampsearchflag
  global normdsamp normdfracsamp normdmax normdfracmax normddstep normdop
  global nativerealloadedflag nativeimagloadedflag
  global smoothsteps smoothtype
  #global nativemaskloadedflag  ;# TODO

  if ![file exists $regdat] {
    confirmalert "Paint 3D Stats:  regdat:\n\n   $regdat\n\nnot found"
    return
  }
  if {!$nativerealloadedflag} {
    confirmalert "Paint 3D Stats (sample to surf):\
              \n\n    no real-valued 3D stats loaded\
              \n\n(1) select stats BRIK from dropdown\
                \n(2) use \"R\" on \"val3d:\" line"
    return
  }
  if {$complexvalflag && !$nativeimagloadedflag} {
    confirmalert "Paint 3D Stats (sample to surf):\
              \n\n    no complex-valued 3D stats loaded\
              \n\n(1) select stats BRIK from dropdown\
                \n(2) use \"R\" on \"val3d:\" line"
    return
  }
  if [searchlimitsBAD] { return }

  read_regdat
  logcmd "read_regdat"
  set fstatflag 0
  if {$complexvalflag} { set fstatflag 1 }  ;# also paints to .stat field
  paint_surface $fstatflag
  logcmd "paint_surface $fstatflag"
  if {$smoothflag} { smooth $smoothsteps $smoothtype }
  fix_nonzero_vals    ;# set .fixedval flag (for sparse smooth)
  logcmd "fix_nonzero_vals"
}

proc searchlimitsBAD { } {
  global normdsampsearchflag normdfracflag
  global normdfracsamp normdfracmax normdsamp normdmax

  set ret 0
  if {$normdsampsearchflag} {
    if {!$normdfracflag && $normdsamp > $normdmax} {
      confirmalert "Sample/PAINT 3D Timeseries/Stats to surf:\
               \n\nsearch (mm) max below min:\
               \n\n    normdmax =  $normdmax\
                 \n    normdsamp = $normdsamp\
               \n\nFix order, and try again\
               \n\n(click \"label:\" to get NormSamp pop-up)"
      set ret 1
    }
    if {$normdfracflag && $normdfracsamp > $normdfracmax} {
      confirmalert "Sample/PAINT 3D Timeseries/Stats to surf:\
               \n\nsearch (frac) max below min:\
               \n\n    normdfracmax =  $normdfracmax\
                 \n    normdfracsamp = $normdfracsamp\
               \n\nFix order, and try again\
               \n\n(click \"label:\" to get NormSamp pop-up)"
      set ret 1
    }
  } else {
    if { $normdfracflag && 
         [expr abs($normdfracsamp - $normdfracmax) < 0.000001] } {
      confirmalert "Sample/PAINT 3D Timeseries/Stats to surf:\
               \n\nnorm search OFF, but non-zero (frac) range:\
               \n\n    normdsampsearchflag = $normdsampsearchflag\
                 \n    normdfracmax =  $normdfracmax\
                 \n    normdfracsamp = $normdfracsamp\
               \n\nTurn ON search (normdsampsearchflag), or zero frac range\
               \n\n(click \"label:\" to get NormSamp pop-up)"
      set ret 1
    }
    if { !$normdfracflag && 
         [expr abs($normdsamp - $normdmax) < 0.000001] } {
      confirmalert "Sample/PAINT 3D Timeseries/Stats to surf:\
               \n\nnorm search OFF, but non-zero (mm) range:\
               \n\n    normdsampsearchflag = $normdsampsearchflag\
                 \n    normdmax =  $normdmax\
                 \n    normdsamp = $normdsamp\
               \n\nTurn ON search (normdsampsearchflag), or zero mm range\
               \n\n(click \"label:\" to get NormSamp pop-up)"
      set ret 1
    }
  }
  return $ret
}

proc uniqsampBAD { } {
  global normdsampuniqvtxflag nativerealloadedflag nativemaskloadedflag
  global valloadedflag statloadedflag uniqvoxcntloadedflag paintTODOflag

  if {!$normdsampuniqvtxflag} { return 0 }
  if {!$nativerealloadedflag && !$nativemaskloadedflag} {
    confirmalert "Write Label Timecourses: with normdsampuniqvtxflag=1\
              \n\n    native 3D data not loaded\
              \n\nUse \"R\" on \"val3d:\" line\
              \n\n(click \"val:\" if not visible)\
                \n(do \"PA\" and \"UQ\" after)"
    return 1
  }
  if {$paintTODOflag} {
    confirmalert "Write Label Timecourses: with normdsampuniqvtxflag=1\
              \n\n    3D data not sampled to surf (or stale)\
              \n\nUse \"PA\" on \"val3d:\" line\
              \n\n(do \"UQ\" after)"
    return 1
  }
  if {!$uniqvoxcntloadedflag} {
    confirmalert "Write Label Timecourses:\
              \n\n    uniqsamp vtxs calculation stale or not read/done\
              \n\nSelect UniqSampVtxs, ctrl-left-click \"label:\" line \"R\"\
              \n\n    or\
              \n\nUse \"UQ\" on \"val3d:\" line"
    return 1
  }
  return 0
}

proc find_uniqsamp_vertices_real_or_complex { action } {
  global uniqvoxnumloadedflag scandir hemi label origcoords statpatt

  if {$action != "select" && $action != "mklabel"} {
    confirmalert \
      "find_uniqsamp_vertices_real_or_complex: bad action:\n\n    $action"
  }
  if {!$uniqvoxnumloadedflag} {
    confirmalert "Find Uniq Sample Voxel Vertices:\
              \n\n    must first sample 3D stats to surface\
              \n\nuse \"PA\" on \"val3d:\" line\
                \n(after loading 3D stats with \"R\")"
    return
  }
  find_uniqsamp_vertices
  logcmd "find_uniqsamp_vertices"
  if {$action == "select"} {
    select_uniqsamp_vertices   ;# display is 100x slower than find
    logcmd "select_uniqsamp_vertices"
  }
  if {$action == "mklabel"} {
    select_uniqsamp_vertices   ;# omit?
    logcmd "select_uniqsamp_vertices"
    # force generic name
    uplevel #0 "setfile label */$scandir/$hemi-UniqSampVtxs.label" ;#scandir
    if [testreplace $label write_uniqsamp_vertices] {
      logcmd "write_uniqsamp_vertices"
      confirmalert "Uniq sample voxel vertices for 3Dfile + surface:\
                \n\n    $statpatt\
                  \n             +\
                  \n    $origcoords\
                \n\nwritten to:\
                \n\n    $label\
                \n\n(see \"label:\" pop-up for current sampling parms)"
    }
  }
}

proc regrawctrls { } {  ;# popup from RD (rawdata) butt on "val3d:" line
  global regrawctrlswin statpattabbrev regdat isession scandir
  global selbgcol ffont hfont bgcol

  if [winfo exists $regrawctrlswin] { raise $regrawctrlswin; return }
  set title "READ RAWDATA BRIK and REGISTRATION\
         \n\nExamples:                                                  \
         \n\n(1) fMRI time-course series, register.dat\
           \n(2) 21-vol 3dDWItoDT output, register.dat\n"
  set variablelist "statpattabbrev regdat whitespace whitespace"
  set regrawctrlswin \
    [controls $title $variablelist "READ RAWDATA and REGISTRATION" do_regraw 30]

  ### hack: repl controls-made entry w/filled tix dropdown copy of val3d entry
  pack forget $regrawctrlswin.statpattabbrev
  tixComboBox $regrawctrlswin.cbx -label "val3d:" -dropdown true \
    -editable true -variable statpattabbrev -listwidth 418
  $regrawctrlswin.cbx subwidget frame config -bg $bgcol  ;# N.B.: inside -bd
  $regrawctrlswin.cbx subwidget label config -font $ffont -bg $bgcol
  $regrawctrlswin.cbx subwidget entry config -font $hfont \
    -selectbackground $selbgcol -highlightbackground $bgcol -width 30 \
    -selectforeground black  ;# last: linux
  $regrawctrlswin.cbx subwidget listbox config -font $hfont
  pack $regrawctrlswin.cbx -after $regrawctrlswin.la -side top
  set fullfilelist [glob -nocomplain $isession/$scandir/*+orig.BRIK]
  # next: manually re-abbrev vs. clog log w/setfile's
  set abbrevlist ""
  foreach fullfile $fullfilelist {
    #setfile statpatt $fullfile; set abbrevlist "$abbrevlist $statpattabbrev"
    set abbrevlist "$abbrevlist */$scandir/[file tail $fullfile]"
  }
  foreach abbrev $abbrevlist { $regrawctrlswin.cbx insert end $abbrev }

  ### hack: manually align w/cbx, show end
  $regrawctrlswin.regdat.la config -width 5
  $regrawctrlswin.regdat.e xview moveto 1

  bind $regrawctrlswin <ButtonRelease-3> { helpwin val3d_raw }
}

proc do_regraw { } {
  global regdat rawdata statpattabbrev rawdataloaded

  setfile regdat $regdat      ;# just for logcmd
  ## re-use 3dval ent ($statpatt, 1vol statBRIK) for timeseries name ($rawdata)
  #uplevel #0 "setfile rawdata $statpattabbrev"
  setfile rawdata $statpattabbrev

  if ![file exists $regdat] {
    confirmalert "Rawdata: register.dat file:\n\n    $regdat\n\nnot found"
    return
  }
  if ![file exists $rawdata] {
    confirmalert "Rawdata: rawdata BRIK:\n\n    $rawdata\n\nnot found"
    return
  }
  if {$rawdataloaded} {
    if ![okreplace "" \
         "Rawdata already loaded:\n\n   $rawdata\n\nRe-load it?"\
         "Re-Read Rawdata"] { return }
  }

  read_regdat
  logcmd "read_regdat"
  read_rawdata
  logcmd "read_rawdata"
  confirmalert "register.dat read from:\
            \n\n    $regdat\
            \n\nrawdata read from:\
            \n\n    $rawdata"
}

proc write_real_or_complex_binary_values { } {  ;# val: W button wrapper
  global val valabbrev complexvalflag

  set len [string length $val]
  set vhemi [string range $val [expr $len - 4] [expr $len - 3]]  ;# neg->0
  set vinf [string range $val [expr $len - 7] [expr $len - 6]]
  set vstem [string range $val 0 [expr $len - 8]]
  set goodinf 0
  if { $vinf == "_r" || $vinf == "_i" || $vinf == "_x" || $vinf == "_y" } {
    set goodinf 1
  }
  if  { $complexvalflag && [string match *_?-?h.w $val] && $goodinf } {
    if { $vinf == "_r" || $vinf == "_i"} { set real _r; set imag _i }
    if { $vinf == "_x" || $vinf == "_y"} { set real _x; set imag _y }
    # assumes complex data properly displayed (val=real, val2=imag)
    swap_val_val2
    logcmd "swap_val_val2"
    set vinf $imag
    setfile val ${vstem}${vinf}-${vhemi}.w
    write_binary_values
    logcmd "write_binary_values"
    swap_val_val2
    logcmd "swap_val_val2"
    set vinf $real
    setfile val ${vstem}${vinf}-${vhemi}.w
    write_binary_values
    logcmd "write_binary_values"
  } else {  ;# old behavior
    write_binary_values
    logcmd "write_binary_values"
  }
}

proc dtivecctrls { } {  ;# DTi popup from "V" (vect) button on "val3d:" line
  global dtivecctrlswin

  if [winfo exists $dtivecctrlswin] { raise $dtivecctrlswin; return }
  set title "READ VECTORS, SAMPLE TO SURFACE\
           \nDISPLAY AS OUTWARD VECTORS\
         \n\n(1) Enter zero-based BRIK indices of:  \
           \n-- x-comp of 3D vector           \
           \n-- scalefact (-1=don't rescale)\
         \n\n(e.g., for AFNI 3dDWItoDT output BRIK:\
           \n9 for x-comp 1st eigenvector \
           \n5 to scale by 1st eigenvalue) \
         \n\n(2) Adjust cortical depth sampling point"
  set variablelist "whitespace \
                    xvect_subbrik \
                    scale_subbrik \
                    whitespace \
                    normdsampsearchflag \
                    normdfracflag \
                    wmgmext \
                    normdsamp_pnt \
                    normdfracsamp_pnt"
  set dtivecctrlswin \
    [controls $title $variablelist "VOLUME VECTORS to SURF" do_dtivec]
  bind $dtivecctrlswin <ButtonRelease-3> { helpwin val3d_vecs }
  # live update of single sampling point on Return (also done on go)
  bind $dtivecctrlswin.normdsamp_pnt.e <Return> {
    set normdsamp $normdsamp_pnt
    set normdmax $normdsamp_pnt
  }
  bind $dtivecctrlswin.normdfracsamp_pnt.e <Return> {
    set normdfracsamp $normdfracsamp_pnt
    set normdfracmax $normdfracsamp_pnt
  }
}

proc do_dtivec { } {
  global dtivecctrlswin rawdata regdat runbgcol bgcol
  global rawdataloaded registerdatloaded normdfracflag normdsampsearchflag
  global xvect_subbrik scale_subbrik normdsamp_pnt normdfracsamp_pnt
  global normdsamp normdfracsamp normdmax normdfracmax dipolesflag
  global env subject surfdir hemi wmgmext

  if { !$rawdataloaded } {
    confirmalert "DTi to Vectors:  rawdata not loaded:\
              \n\n    click \"val:\" to get \"val3d:\"\
                \n    click \"RD\" for pop-up, pick DTi BRIK, read it\
              \n\nor\
              \n\n    ctrl-mid-clk brain in DTi-BRIK-containing scandir\
              \n\nor\
              \n\n    use tcl/C ('setfile' is globbing 'set'):\
              \n\n        setfile rawdata */<DTi-scandir>/<DTi-brik>\
                \n        read_rawdata\
                \n        setfile redgat */<DTi-scandir>/register.dat\
                \n        read_regdat\
              \n\ncurrent value \$rawdata, \$regdat:\
              \n\n    $rawdata\
                \n    $regdat"
    return
  }
  if { !$registerdatloaded } {
    confirmalert "DTi to Vectors:\n\nregister.dat not loaded (use read_regdat)"
    return
  }
  set sampsurf $env(SUBJECTS_DIR)/$subject/$surfdir/$hemi.$wmgmext
  if ![file exists $sampsurf] {
    confirmalert "DTi to Vectors:\
               \n\nsampling surface:\
               \n\n    $sampsurf\
               \n\nnot found"
    return
  }
  #TODO: need more tcl var exports for other read_vec2surf checks

  if {$normdsampsearchflag} {  ;# force single sample depth
    if {$normdfracflag} {
      set normdfracsamp $normdfracsamp_pnt
      set normdfracmax $normdfracsamp_pnt
    } else {
      set normdsamp $normdsamp_pnt
      set normdmax $normdsamp_pnt
    }
  }
  read_vecs2surf $xvect_subbrik $scale_subbrik
  logcmd "read_vecs2surf $xvect_subbrik $scale_subbrik"
  set dipolesflag 1
  logcmd "set dipolesflag 1"
  redrawbutton

### or: execute functs called by read_vecs2surf in tcl
#  swap_val_valbak
#  for {set i 0} {$i < 3} {incr i} {
#    rawdatasubbrik_to_paintable [expr $xvectbrik + $i]
#    paint_surface 0
#    copy_val_dip $i
#  }
#  set dipolesloaded 1
#  calc_dipavglen
#  if {$scalebrik >= 0} {
#    rawdatasubbrik_to_paintable $scalebrik
#    paint_surface 0
#    swap_stat_val
#    scale_dipxyz_by_stat
#  }
#  rotate_dti
#  swap_val_valbak  ;# restore curr ovelay
#  set dipolesflag 1

### purple-button works here, but mv'd to more gen location in proc controls
#  # purple/disable/rename butt b/c takes a while
#  $dtivecctrlswin.aREADY.bu config -text RUNNING \
#    -background $runbgcol -disabledforeground black -state disabled
#  update idletasks
#  read_vecs2surf $xvect_subbrik
#  logcmd "read_vecs2surf $xvect_subbrik"
#  # unpurple/enable butt
#  $dtivecctrlswin.aREADY.bu config -text READY -background $bgcol -state normal

  ## leave window up for redo
  #if [winfo exists $dtivecctrlswin] { destroy $dtivecctrlswin }
  #set corrctrlswin ""
}

proc sphimctrls { } {  ;# popup from F3 interface bold "im:" for sphim samp
  global sphimctrlswin sphvoltype minsphdata maxsphdata hemi
  global write_mgz_for_debug_flag

  if [winfo exists $sphimctrlswin] { raise $sphimctrlswin; return }
  set title "WRITE DATA TO SPHIM\
           \n(OPTIONAL: SAVE AS MGZ)\
         \n\nEnter sphvoltype:\
           \n(which surf data => sphvol):\
         \n\n   0: curv (.curv)\
           \n  1: stat (.stat)\
           \n2: real (.val)\
           \n   3: imag (.val2)\
           \n      4: real2 (.valbak)\
           \n          5: imag2 (.val2bak)\
         \n\nOptional: enter max/min data:\
           \n(b/c sample to byte vol)\
           \n(data beyond is clamped)\
         \n\n  SUBJECTS_DIR outfile:\
           \n~/mri/sphim.$hemi.mgz"
  set variablelist "whitespace \
                    sphvoltype \
                    whitespace \
                    write_mgz_for_debug_flag
                    minsphdata \
                    maxsphdata \
                    whitespace"
  set sphimctrlswin [controls $title $variablelist "READY" do_sphim]
  ### hack: enable/disable rest of panel on toggle write_mgz_for_debug_flag
  $sphimctrlswin.ck0 config -command {
    if {$write_mgz_for_debug_flag} {
      foreach z "minsphdata maxsphdata" {
        $sphimctrlswin.$z.la config -state normal
        $sphimctrlswin.$z.e config -state normal
      }
    } else {
      foreach z "minsphdata maxsphdata" {
        $sphimctrlswin.$z.la config -state disabled
        $sphimctrlswin.$z.e config -state disabled
      }
    }
    unset z
  }
  if {!$write_mgz_for_debug_flag} { ;# init
    foreach z "minsphdata maxsphdata" {
      $sphimctrlswin.$z.la config -state disabled
      $sphimctrlswin.$z.e config -state disabled
    }
    unset z
  }
  bind $sphimctrlswin <ButtonRelease-3> { helpwin read_im_label }
}

proc do_sphim { } {
  global sphvoltype minsphdata maxsphdata
  global env subject hemi inim inimabbrev
  global curvloadedflag statloadedflag valloadedflag val2loadedflag
  global valbakloadedflag val2bakloadedflag write_mgz_for_debug_flag

  if { $sphvoltype < 0 || $sphvoltype > 5 } {
    confirmalert "SurfData to Sphim to Mgz:\n\n### bad sphvoltype type (OK:0-5)"
    return
  }
  if {$sphvoltype == 0} { set datatype .curv }
  if {$sphvoltype == 1} { set datatype .stat }
  if {$sphvoltype == 2} { set datatype .val }
  if {$sphvoltype == 3} { set datatype .val2 }
  if {$sphvoltype == 4} { set datatype .valbak }
  if {$sphvoltype == 5} { set datatype .val2bak }
  if { $sphvoltype == 0 && !$curvloadedflag } {
    confirmalert "SurfData to Sphim to Mgz:\n\n$datatype field not loaded"
    return
  }
  if { $sphvoltype == 1 && !$statloadedflag } {
    confirmalert "SurfData to Sphim to Mgz:\n\n$datatype field not loaded"
    return
  }
  if { $sphvoltype == 2 && !$valloadedflag } {
    confirmalert "SurfData to Sphim to Mgz:\n\n$datatype field not loaded"
    return
  }
  if { $sphvoltype == 3 && !$val2loadedflag } {
    confirmalert "SurfData to Sphim to Mgz:\n\n$datatype field not loaded"
    return
  }
  if { $sphvoltype == 4 && !$valbakloadedflag } {
    confirmalert "SurfData to Sphim to Mgz:\n\n$datatype field not loaded"
    return
  }
  if { $sphvoltype == 5 && !$val2bakloadedflag } {
    confirmalert "SurfData to Sphim to Mgz:\n\n$datatype field not loaded"
    return
  }
  setfile inim ~/mri/orig.mgz
  if ![file exists $inim] {
    confirmalert "SurfData to Sphim to Mgz:\n\nmodel volume not found:\n$inim"
    return
  }

  read_images   ;# load header vals for write
  logcmd "read_images"
  surf2sphim $sphvoltype
  logcmd "surf2sphim $sphvoltype"
  if {$write_mgz_for_debug_flag} {
    write_sphim2byte $sphvoltype $minsphdata $maxsphdata
    logcmd "write_sphim2byte $sphvoltype $minsphdata $maxsphdata"
  }
  if {$write_mgz_for_debug_flag} {
    confirmalert "(1) sampled $datatype to sphim\
              \n\n(2) wrote sphim to (for debug):\
              \n\n    $env(SUBJECTS_DIR)/$subject/mri/sphim.$hemi.mgz"
  } else {
    confirmalert "sampled $datatype to sphim"
  }
}

proc do_labeltick { } {
  prune_annotbord
  logcmd "prune_annotbord"
  redrawbutton
}

proc labeltickctrls { } {  ;# added to right-click on label tickbox
  global labeltickctrlswin ffontb inclFTGLflag

  #if [winfo exists $labeltickctrlswin] { raise $labeltickctrlswin; return }
  ## workaround: winfo says exists after destroyed, raises lut2annot instead
  if [winfo exists $labeltickctrlswin] { destroy $labeltickctrlswin }
  set title "LABEL CONTROLS"
  if {$inclFTGLflag} {
    set variablelist "whitespace \
                      labelflag \
                      vtxcolflag \
                      annotbordflag \
                      areanamesflag \
                      fontsize \
                      dthreshfact \ 
                      newreadfulllabflag \
                      annotmaskflag \
                      padlabelvtxsflag \
                      whitespace \
                      annotborddotflag \
                      pointsize \
                      meshr \
                      meshg \
                      meshb \
                      whitespace"
  } else {  ;# don't ref ifdef'd out variables
    set variablelist "whitespace \
                      labelflag \
                      vtxcolflag \
                      annotbordflag \
                      newreadfulllabflag \
                      annotmaskflag \
                      padlabelvtxsflag \
                      whitespace \
                      annotborddotflag \
                      pointsize \
                      meshr \
                      meshg \
                      meshb \
                      whitespace"
  }
  set labeltickctrlswin \
    [controls $title $variablelist "PRUNE ANNOT DOTS" "do_labeltick"]
  # hack in another button (sorry)
  update idletasks
  button $labeltickctrlswin.bu2 -text "RESTORE ANNOT BORD" -font $ffontb \
    -pady 2 -padx 2
  $labeltickctrlswin.bu2 config -command {
    find_annot_borders
    logcmd "find_annot_borders"
    redrawbutton
  }
  pack $labeltickctrlswin.bu2 -side top
  # hack in added binding to areanamesflag
  if {$inclFTGLflag} {
    bind $labeltickctrlswin.ck3 <ButtonRelease-1> {+ ;#plus: add to def redraw
      if {$areanamesflag && !$annotloadedflag} {
        confirmalert "Can't display area names:\
                  \n\n    no annotation loaded\
                  \n\n(1) select .annot from dropdown\
                    \n(2) load with \"D\" button on \"label:\" line"
      }
    }
  }
  # hack in added binding to annotbordflag
  bind $labeltickctrlswin.ck2 <ButtonRelease-1> {+  ;#plus: add to def redraw
    reselect_selected_list
  }
  # end hacks
  bind $labeltickctrlswin <ButtonRelease-3> { helpwin label_toggle }
}

proc isoconttickctrls { } {  ;# added to right-click on isocont tickbox
  global isoconttickctrlswin

  if [winfo exists $isoconttickctrlswin] { raise $isoconttickctrlswin; return }
  #if [winfo exists $isoconttickctrlswin] { destroy $isoconttickctrlswin }
  set title "ISOCONTOUR CONTROLS \
         \n\nisoconttype's (0-4):                                  \
         \n\n0: x,y,z isocontours at 10 mm spacing    \
           \n1: 3 orthogonal latitudes 10 deg spacing  \
           \n2: latitude/longitude with right/left poles \
           \n3: latitude/longitude with ant/post poles  \
           \n4: latitude/longitude with sup/inf poles     \
         \n\nspacing units: deg/mm                             \
         \n\nlinewidth units: pixels (floating point)        "
  set variablelist "whitespace \
                    isoconttype \
                    isocontourflag \
                    whitespace \
                    contourspacingRL \
                    contourspacingAP \
                    contourspacingSI \
                    whitespace \
                    contourlinewidthRL \
                    contourlinewidthAP \
                    contourlinewidthSI \
                    whitespace"
  set isoconttickctrlswin \
    [controls $title $variablelist "(RE)MAKE ISOCONTOURS" "mkisocont"]
  bind $isoconttickctrlswin <ButtonRelease-3> { helpwin isocont }
}

proc mkisocont { } {
  global isocontourflag isoconttype

  if {$isoconttype < 0 || $isoconttype > 4} {
    confirmalert "### bad isoconttype:\n\n  =>  $isoconttype  <=\n\nvalid: 0-4"
  }
  # log popup values
  logcmd "set isoconttype $isoconttype"
  logcmd "set isocontourflag $isocontourflag"
  logcmd "set contourspacingRL $contourspacingRL"
  logcmd "set contourspacingAP $contourspacingAP"
  logcmd "set contourspacingSI $contourspacingSI"
  logcmd "set contourlinewidthRL $contourlinewidthRL"
  logcmd "set contourlinewidthAP $contourlinewidthAP"
  logcmd "set contourlinewidthSI $contourlinewidthSI"
  # go
  set isocontourflag 1
  logcmd "set isocontourflag 1"
  redraw
}

proc lightsctrls { } {  ;# added to right-click help REDRAW buttonbar
  global lightsctrlswin

  if [winfo exists $lightsctrlswin] { raise $lightsctrlswin; return }
  set title "FIXED (to viewer) LIGHTS\
           \nlight0 (0.4): from viewer\
           \nlight1 (0.0): behind(=off)\
           \nlight2 (0.8): upper right  \
           \nlight3 (0.2): mid left        "
  set variablelist "light0 \
                    light0x \
                    light0y \
                    light0z \
                    whitespace \
                    light1 \
                    light1x \
                    light1y \
                    light1z \
                    whitespace \
                    light2 \
                    light2x \
                    light2y \
                    light2z \
                    whitespace \
                    light3 \
                    light3x \
                    light3y \
                    light3z
                    whitespace \
                    insidesurffact \
                    lighttwosidedflag"
  set lightsctrlswin \
    [controls $title $variablelist none none ]
  bind $lightsctrlswin <ButtonRelease-3> { helpwin lights }
}

proc do_prune_arrows { } {
  global gridsize

  prune_arrows $gridsize
  logcmd "prune_arrows $gridsize"
  redrawbutton
}

proc findgradrevctrls { } {
  global findgradrevctrlswin pvalborddotflag dthresh
  global mindiffphase gradrevprobname meshr meshg meshb pointsize
  global gradvecbakflag gradvecbak3dflag

  if [winfo exists $findgradrevctrlswin] { raise $findgradrevctrlswin; return }
  set title "FIND GRADIENT REVERSALS\
        \n\nFirst calc/display 2D/3D gradient arrows\
          \nfor curv, real- or complex-valued data\
        \n\nReversal detected if neighboring vertex\
          \ngradient angle diffs exceed mindiffphase\
          \n(units of mindiffphase: 0.5 = 180 deg)"

  set variablelist "whitespace \
                    mindiffphase \
                    gradrevprobname \
                    whitespace \
                    whitespace \
                    gradvecbakflag \
                    gradvecbak3dflag \
                    pvalborddotflag \
                    dthresh \
                    meshr \
                    meshg \
                    meshb \
                    pointsize \
                    whitespace"
  set findgradrevctrlswin \
    [controls $title $variablelist "FIND REVERSALS" "do_gradrev" 18]
  bind $findgradrevctrlswin <ButtonRelease-3> { helpwin comp_grad }
  # set default dot col to cyan
  set meshr 0
  logcmd "set meshr 0"
  set meshg 255
  logcmd "set meshg 255"
  set meshb 255
  logcmd "set meshb 255"
  set pvalborddotflag 1   ;# N.B.: req's pval-using functs to turn it OFF
  logcmd "set pvalborddotflag 1"
}

proc do_gradrev { } {
  global flag2d gradvecflag gradvecbakflag gradvecbak3dflag gradrevprobname
  global overlayflag complexvalflag colscale fslope fmid fthresh val
  global hemi scandir isession pvalborddotflag mindiffphase 
  global dthresh meshr meshg meshb pointsize

  if {!$gradvecbakflag && !$gradvecbak3dflag} {
    confirmalert "Calculate Gradient Reversals:\
              \n\nFirst calculate/display gradient\
              \n\nIf already calculated, tick gradvecbak\{3d\}flag's"
    return
  }
  if {$gradvecflag} {
    confirmalert "Calculate Gradient Reversals:\
              \n\nIgnoring gradvecflag (which displays gradient arrows\
                \nfrom the *top* of complex stack)\
              \n\nReversals will be found using data on *bottom* of\
                \ncomplex stack (.valbak,.val2bak)"
  }

  # log popup values
  logcmd "set mindiffphase $mindiffphase"
  logcmd "set gradrevprobname $gradrevprobname"
  logcmd "set pvalborddotflag $pvalborddotflag"
  logcmd "set dthresh $dthresh"
  logcmd "set meshr $meshr"
  logcmd "set meshg $meshg"
  logcmd "set meshb $meshb"
  logcmd "set pointsize $pointsize"

  # go
  find_gradient_reversals  ;# output to .pval, write before optional display
  logcmd "find_gradient_reversals"

  # write out .pval as wfile (N.B.: could be gradient of curv,real,phaseamp!)
  swap_pval_val
  logcmd "swap_pval_val"
  setfile val */$scandir/$gradrevprobname-$hemi.w   ;# 1: myglob curr scandir
  if ![canwriteormakefile $val] {  ;# 2: else subject or session scriptsdir
    setfile val $isession/scripts/$gradrevprobname-$hemi.w
  }
  if [file exists $val] { if ![okreplace $val] { return } }
  write_binary_values
  logcmd "write_binary_values"
  swap_pval_val  ;# put val back (for pval dots, or if skip val display)
  logcmd "swap_pval_val"
  confirmalert "Calculate Gradient Reversals:\
            \n\nwrote border probability file to:\
            \n\n    $val\
            \n\nN.B.: \$gradvacbak\{3d\}flag's unticked to reveal borders"

  # turn off gradient vec's so borders not obscured
  set gradvecbakflag 0
  logcmd "set gradvecbakflag 0"
  set gradvecbak3dflag 0
  logcmd "set gradvecbak3dflag 0"

  # optional display
  if {!$pvalborddotflag} {
    if ![okreplace "" \
               "Calculate Gradient Reversals:\
            \n\nReady to swap .pval into view and reset colscale as follows:\
            \n\n  swap_pval_val           (redo to recover curr cmplx data)\
              \n  set overlayflag 1        (current: $overlayflag)\
              \n  set complexvalflag 0  (current: $complexvalflag)\
              \n  set colscale 11           (current: $colscale)\
              \n  set fslope 2.0              (current: $fslope)\
              \n  set fmid 0.5                 (current: $fmid)\
              \n  set fthresh 0.0            (current: $fthresh)\
            \n\nOK to display .pval output? (cancel: output left in .pval)"\
       "Swap .pval Into View, Reset ColScale"] {return }
    swap_pval_val    ;# redo to recover complex data
    logcmd "swap_pval_val"
    set overlayflag 1
    logcmd "set overlayflag 1"
    set complexvalflag 0
    logcmd "set complexvalflag 0"
    set colscale 11
    logcmd "set colscale 11"
    set fslope 2.0
    logcmd "set fslope 2.0"
    set fmid 0.5
    logcmd "set fmid 0.5"
    set fthresh 0.0
    logcmd "set fthresh 0.0"
  }
  redrawbutton
}

proc fstickctrls { } {  ;# added to right-click on fs tickbox
  global fstickctrlswin gridsize ffontb

  if [winfo exists $fstickctrlswin] { raise $fstickctrlswin; return }
  set title "FIELDSIGN and\nGRADIENT ARROWS\nCONTROLS"
  set variablelist "whitespace \
                    nonbinaryfsflag \
                    whitespace \
                    gradvecflag \
                    gradvecbakflag \
                    gradvecbak3dflag \
                    reggradvecbakflag \
                    reggradvecbak3dflag \
                    whitespace \
                    arrownormflag \
                    filledarrowsflag \
                    centerarrowsflag \
                    angoffrevarrflag \
                    flipRHpolararrowsflag \
                    arrowscale \
                    arrowline \
                    arrowheadfracauto \
                    arrowheadmin \
                    line_arrowbarbangle \
                    filled_arrowtipangle \
                    filled_arrowbarbangle \
                    gridsize \
                    sdoutlierfact \
                    areaoutliermin \
                    rmgradoutliersflag \
                    prunearrowsflag"
  set fstickctrlswin \
    [controls $title $variablelist "PRUNE ARROWS" "do_prune_arrows"]
  bind $fstickctrlswin <ButtonRelease-3> { helpwin gradfsarrows }
  bind $fstickctrlswin.gridsize.e <Return> { do_prune_arrows }
  bind $fstickctrlswin.sdoutlierfact.e <Return> {
    if {$flag2d} {
      confirmalert "Re-calc gradient to see effect of changing \$stoutlierfact"
    } else {
      confirmalert "no effect on 3d surf gradient"
    }
  }
  bind $fstickctrlswin.areaoutliermin.e <Return> {
    if {$flag2d} {
      confirmalert "Re-calc gradient to see effect of changing \$areaoutliermin"
    } else {
      confirmalert "no effect on 3d surf gradient"
    }
  }

  # hack: internal ck window name: fix if anything added, rearranged
  bind $fstickctrlswin.ck10 <ButtonRelease-1> {
    if {$flag2d} {
      confirmalert "Re-calculate gradient to see effect of this change:\
               \n\n    rmgradoutliersflag -> $rmgradoutliersflag"
    } else {
      confirmalert "no effect on 3d surf gradient (use fthresh/sfthresh)"
    }
  }
  # hack: add filledarrowsflag bind (N.B.: no space between left bracket,plus!)
  bind $fstickctrlswin.ck5 <ButtonRelease-1> {+  ;# intern: ck5 -> sixth check
    if {$filledarrowsflag && !$flag2d} {
      confirmalert "filled arrows not (yet) implemented on curved surface"
    }
  }
  # hack: fix arrowscale Return somehow bound to PRUNE ARROWS action butt!
  bind $fstickctrlswin.arrowscale.e <Return> {
    logcmd "set arrowscale $arrowscale"
    redrawbutton
  }
  # hack in two more buttons (sorry)
  update idletasks
  button $fstickctrlswin.bu2 -text "DENSE ARROWS DEFAULTS" -font $ffontb \
    -pady 2 -padx 2
  $fstickctrlswin.bu2 config -command {
    if {$filledarrowsflag} {
      set arrownormflag 0;            logcmd "set arrownormflag 0"
      set arrowscale 3.0;             logcmd "set arrowscale 3.0"
      set arrowline 1.2;              logcmd "set arrowline 1.2"
      set arrowheadfracauto 0.0;      logcmd "set arrowheadfracauto 0.0"
      set arrowheadmin 0.2;           logcmd "set arrowheadmin 0.2"
      set filled_arrowtipangle 15.0;  logcmd "set filled_arrowtipangle 15.0"
      set filled_arrowbarbangle 60.0; logcmd "set filled_arrowbarbangle 60.0"
    } else {
      set arrownormflag 0;            logcmd "set arrownormflag 0"
      set arrowscale 2.0;             logcmd "set arrowscale 2.0"
      set arrowline 1.0;              logcmd "set arrowline 1.0"
      set arrowheadfracauto 0.3;      logcmd "set arrowheadfracauto 0.3"
      set arrowheadmin 0.1;           logcmd "set arrowheadmin 0.1"
      set line_arrowbarbangle 22.5;   logcmd "set line_arrowbarbangle 22.5"
    }
    redrawbutton
  }
  pack $fstickctrlswin.bu2 -side top
  # third button
  button $fstickctrlswin.bu3 -text "SPARSE ARROWS DEFAULTS" -font $ffontb \
    -pady 2 -padx 2
  $fstickctrlswin.bu3 config -command {
    if {$filledarrowsflag} {
      set arrownormflag 0;            logcmd "set arrownormflag 0"
      set arrowscale 15.0;             logcmd "set arrowscale 15.0"
      set arrowline 5.0;              logcmd "set arrowline 5.0"
      set arrowheadfracauto 0.0;      logcmd "set arrowheadfracauto 0.0"
      set arrowheadmin 0.9;           logcmd "set arrowheadmin 0.9"
      set filled_arrowtipangle 15.0;  logcmd "set filled_arrowtipangle 15.0"
      set filled_arrowbarbangle 60.0; logcmd "set filled_arrowbarbangle 60.0"
    } else {
      set arrownormflag 0;            logcmd "set arrownormflag 0"
      set arrowscale 15.0;            logcmd "set arrowscale 15.0"
      set arrowline 2.0;              logcmd "set arrowline 2.0"
      set arrowheadfracauto 0.4;      logcmd "set arrowheadfracauto 0.4"
      set arrowheadmin 0.2;           logcmd "set arrowheadmin 0.2"
      set line_arrowbarbangle 22.5;   logcmd "set line_arrowbarbangle 22.5"
    }
    redrawbutton
  }
  pack $fstickctrlswin.bu3 -side top
  # move up these ctrls to un-overlap if from GR buttonbar (not if from fstick)
  if [winfo exists .buttonbar-fsGR_2d_curv] { ;#intern: buttbar win nm=1st proc
    set g [split [wm geometry $fstickctrlswin] "+x"]
    wm geometry $fstickctrlswin +[lindex $g 2]+[expr [lindex $g 3]-650]
  }
  # end hacks
}

proc valfiletypectrls { } {
  global valfiletypectrlswin allverticesflag val2newcurvflag

  if [winfo exists $valfiletypectrlswin] { raise $valfiletypectrlswin; return }
  set title "VAL FILE OUTPUT TYPE CONTROLS\
         \n\n\$allverticesflag:  OFF (=0) by default  \
           \n so valfiles only contain vtxs with\
           \nnon-zero values (.val field)        \
         \n\n\$val2newcurvflag:  OFF (=0) by def   \
           \n so older style valfiles are written\
           \n(3-byte vtx index, 4-byte value).\
           \nTurn ON to write newcurv type file    \
           \n  (all vtxs, no indices, 4-byte value)\
           \n(if ON, ignores \$allverticesflag)   "
  set variablelist "whitespace allverticesflag val2newcurvflag"
  set valfiletypectrlswin [controls $title $variablelist none none]
}

proc writedftampctrls { } {  ;# middle-click W button on "val:" line wrapper
  global avg_rawamp time_points writedftampctrlswin ffontb

  if [winfo exists $writedftampctrlswin] { raise $writedftampctrlswin; return }
  set title "RAW FOURIER TO PERCENT RESPONSE\
         \n\n(1) Load raw Fourier amp surface data:   \
           \npick _x wfile from \"val:\" dropdown\
           \nclick \"R\" (read) on \"val:\" line         \
         \n\n(2) Load 3D rawdata time series:             \
           \nclick \"val:\" label to get \"val3d:\"       \
         \nclick \"RD\" to get rawdata popup      \
         \nselect timeseries BRIK in dropdown\
         \nclick READ RAWDATA & REGISTR. \
         \n\nN.B.: if no raw data:                      \
           \nenter avg raw data amplitude\
           \nenter time points in raw data \
         \n\n(3) COMPUTE AVG t-SERIES EACH VTX  \
           \nN.B.: skip this step if no rawdata\
         \n\n(4) COMPUTE PERCENT RESPONSE       \
           \noutput (percent) to .stat field   \
           \n*and* wfile with _% infix     "
  set variablelist "whitespace avg_rawamp time_points whitespace"
  set writedftampctrlswin \
    [controls $title $variablelist "COMPUTE PERCENT RESP" "do_writedftamp" 10]

  # hack in another button before main butt
  update idletasks
  button $writedftampctrlswin.bu2 -text "COMPUTE AVG t-SERIES EACH VTX" \
    -font $ffontb -pady 2 -padx 2
  $writedftampctrlswin.bu2 config -command { do_computetseravgs }
  pack $writedftampctrlswin.bu2 \
    -before "$writedftampctrlswin.aCOMPUTE PERCENT RESP" -side top
  # end hack
}

proc do_computetseravgs { } {  ;# COMPUTE AVG t-SERIES EACH VTX button
  global rawdataloaded avg_rawamp time_points rawdata_tdim

  if {$rawdataloaded} {
    if ![okreplace "" "Compute VertexWise t-Series Avg to .stat:\
                   \n\n(takes a few sec)\
                   \n\nOK to go?"\
         "Compute Vtxwise t-Series Avg"] { return }
    clear_stats
    logcmd "clear_stats"
    compute_tseriesavg2stat
    logcmd "compute_tseriesavg2stat"
    set avg_rawamp vtxwise  ;# "vtxwise": flag conv'd to amp=-1 for Cfunc flag
    set time_points $rawdata_tdim
  } else {
    confirmalert "Compute Avg t-Series Each Vertex:\
             \n\n    ### 3D rawdata not loaded\
             \n\n    ctrl-mid-click surface (autoloads rawdata)\
             \n\n          OR\
             \n\n    click \"val:\" label to get \"val3d:\"\
               \n    click \"RD\" to get rawdata popup\
               \n    select timeseries BRIK in dropdown\
               \n    click READ RAWDATA & REGISTRATION\
             \n\nIf no rawdata:\
             \n\n    \[skip: COMPUTE AVG t-SERIES EACH VTX\]\
               \n    enter avg raw data amplitude (brain)\
               \n    enter raw data time points\
               \n    COMPUTE PERCENT RESP"
    return
  }
}

proc do_writedftamp { } {  ;# COMPUTE PERCENT RESP button
  global complexvalflag val valabbrev hemi valloadedflag val2loadedflag
  global avg_rawamp time_points
  global revphaseflag invphaseflag truncphaseflag statmaskampflag
  global colscale fthresh fmid fslope writedftampctrlswin

  ## check input state
  if  { !$complexvalflag } {
    confirmalert "Convert Raw Fourier to Percent Response:\
              \n\nfirst read complex-valued data to surface (_x,_y)"
    return
  }
  if  { !$valloadedflag || !$val2loadedflag } {
    confirmalert "Convert Raw Fourier to Percent Response:\
              \n\nfirst read complex-valued data to surface (_x,_y)"
    return
  }
  ## check infix (even if dropdown picked, $val won't be updated till R)
  set len [string length $val]
  set vhemi [string range $val [expr $len - 4] [expr $len - 3]]  ;# neg->0
  set vinf [string range $val [expr $len - 7] [expr $len - 6]]
  set vstem [string range $val 0 [expr $len - 8]]
  if { $vinf != "_x" && $vinf != "_y" } {
    confirmalert "Convert Raw Fourier to Percent Response:\
              \n\n    last read \"val:\" file infix:  $vinf\
              \n\nwas not raw fourier amp (infix: _x or _y):\
              \n\nFirst select _x or _y wfile from \"val:\"\
                \ndropdown, and click and \"R\""
    return
  }

  ## check panel parms
  if {"$avg_rawamp" == 0 || $time_points == 0} {
    confirmalert "avg_rawamp, time_points:\n\nbad value:  0"
    return  ;# leave ctrls up, allow retry
  }
  if { ![string is double $avg_rawamp] && "$avg_rawamp" != "vtxwise"} {
    confirmalert "bad avg_rawamp:\
              \n\n    $avg_rawamp\
              \n\nOK: positive floating point number OR \"vtxwise\"\
              \n\nIf \"vertexwise\", .stat field must contain avg amp\
                \n(load with COMPUTE AVG-tSERIES EACH VTX)"
    return  ;# leave ctrls up, allow retry
  }

  ## go convert, kill setup panel before 2 feedback popups
  set avg_rawamp2 $avg_rawamp
  if {"$avg_rawamp" == "vtxwise"} {
    set avg_rawamp2 -1.0   ;# flag to C funct to get amp from .stat field
    #logcmd "set avg_rawamp2 -1.0"  ;# not crucial since funct arg logged below
  } else {
    clear_stats
    logcmd "clear_stats"
  }
  compute_dftamp2pcnt2stat $avg_rawamp2 $time_points
  logcmd "compute_dftamp2pcnt2stat $avg_rawamp2 $time_points"
  if [winfo exists $writedftampctrlswin] { destroy $writedftampctrlswin }
  set writedftampctrlswin ""

  ## show
  clear_annot
  logcmd "clear_annot"
  swap_stat_val
  logcmd "swap_stat_val"
  swap_settings
  #logcmd "swap_settings"  ;# don't log
  set complexvalflag 0
  logcmd "set complexvalflag 0"
  set revphaseflag 0
  logcmd "set revphaseflag 0"
  set invphaseflag 0
  logcmd "set invphaseflag 0"
  set truncphaseflag 0
  logcmd "set truncphaseflag 0"
  set colscale 6
  logcmd "set colscale 6"
  set fthresh 0.0
  logcmd "set fthresh 0.0"
  set fmid 0.6
  logcmd "set fmid 0.6"
  set fslope 2.0
  logcmd "set fslope 2.0"
  set statmaskampflag 0
  logcmd "set statmaskampflag 0"
  secondsquashents
  logcmd "secondsquashents"
  redrawbutton
  confirmalert "View Percent Response:\
            \n\n    swap_stat_val\
              \n    colscale -> real-valued\
              \n    tweak flags\
            \n\nN.B.: fthresh/fmid units are percent"

  ## write wfile
  set vinf _%
  setfile val ${vstem}${vinf}-${vhemi}.w
  write_binary_values
  logcmd "write_binary_values"
  after 250
  confirmalert "Also wrote percent response to:\n\n$val"
}

proc swap_settings { } {
  foreach varName { fthresh sfthresh fmid sfmid fslope sfslope colscale \
                    angle_cycles angle_offset revphaseflag ipsiyellowfact } {
    global $varName last$varName
    if [info exists last$varName] {
      set tmp$varName [set $varName]
      set $varName [set last$varName]
      set last$varName [set tmp$varName]
    } else {
      set last$varName [set $varName]
    }
  }
}

proc secondsquashents { } {
  global statmaskampflag
  if {$statmaskampflag} {
    pack .display.le.fthresh.st
    pack .display.mi.to.ri.fslope.st
    pack .display.mi.to.ri.fmid.st
    .display.le.fthresh.la config -text "fthr:" -width 3
    .display.mi.to.ri.fslope.la config -text "fslo:" -width 3
    .display.mi.to.ri.fmid.la config -text "fmid" -width 3
  } else {
    pack forget .display.le.fthresh.st
    pack forget .display.mi.to.ri.fslope.st
    pack forget .display.mi.to.ri.fmid.st
    .display.le.fthresh.la config -text "fthresh:" -width 6
    .display.mi.to.ri.fslope.la config -text "fslope:" -width 7
    .display.mi.to.ri.fmid.la config -text "fmid:" -width 7
  }
}

proc smooth { steps {type none} } {  ;# SMOOTH button
  global complexvalflag statmaskampflag statloadedflag

  ## alternate functions if text entered instead of numbers (
  # if '<steps>' is annotholes/.., <type> arg (e.g., from smoothbutton!) ignored
  if {"$steps" == "annotholes" || "$steps" == "labelholes"} {
    fill_annot_holes
    logcmd "fill_annot_holes"
    return
  }
  if {"$steps" == "annotholes-neigh" || "$steps" == "labelholes-neigh"} {
    fillholesneighctrls
    return
  }
  if {"$steps" == "valholes" || "$steps" == "valueholes"} {
    fill_val_holes
    logcmd "fill_val_holes"
    return
  }
  if {"$steps" == "annoterode"} {
    erode_annot
    logcmd "erode_annot"
    return
  }
  if ![string is int "$steps"] {
    confirmalert "smooth: ### bad argument:\n\n    $steps\
              \n\nOnly valid non-integer args are:\
              \n\n    valholes                   (=valueholes)\
                \n    annotholes              (=labelholes)\
                \n    annoterode\
                \n    annotholes-neigh   (=labelholes-neigh)"
    return
  }

  if { $type == "none" } {  ;# after drop thru all no-steps calls
    confirmalert "smooth: ### missing smooth <type>\
              \n\nusage: smooth <steps> <type>"
    return
  } elseif { $type == "curv" } {
    smooth_curv $steps
    logcmd "smooth_curv $steps"
  } elseif { $type == "stat" } {
    smooth_stat $steps
    logcmd "smooth_stat $steps"
  } elseif { $type == "grad" || $type == "valbakonly" } { ;# last not yet used
    swap_valval2_valbakval2bak 
    logcmd "swap_valval2_valbakval2bak"
    swap_val_val2
    logcmd "swap_val_val2"
    smooth_val $steps
    logcmd "smooth_val $steps"
    swap_val_val2
    logcmd "swap_val_val2"
    smooth_val $steps
    logcmd "smooth_val $steps"
    swap_valval2_valbakval2bak
    logcmd "swap_valval2_valbakval2bak"
  } elseif { $type == "cpxreal" } {  ;# all-in-one complex angle w/real amp
    smooth_complexang_realamp $steps
    logcmd "smooth_complexang_realamp $steps"
  } else {  ;# val, weight, sparse
    if {$complexvalflag} {
      ## smooth imaginary
      swap_val_val2
      logcmd "swap_val_val2"
      if { $type == "valonly" || $type == "val" } {
        smooth_val $steps
        logcmd "smooth_val $steps"
      }
      if { $type == "weight" } {
        smooth_val_weighted $steps
        logcmd "smooth_val_weighted $steps"
      }
      if { $type == "sparse" } {
        smooth_val_sparse $steps
        logcmd "smooth_val_sparse $steps"
      }
      ## smooth real
      swap_val_val2
      logcmd "swap_val_val2"
      if { $type == "valonly" || $type == "val" } {
        smooth_val $steps
        logcmd "smooth_val $steps"
      }
      if { $type == "weight" } {
        smooth_val_weighted $steps
        logcmd "smooth_val_weighted $steps"
      }
      if { $type == "sparse" } {
        smooth_val_sparse $steps
        logcmd "smooth_val_sparse $steps"
      }
      ## smooth stats if loaded
      if { $type == "val" && $statmaskampflag && $statloadedflag} {
        swap_stat_val
        logcmd "swap_stat_val"
        smooth_val $steps
        logcmd "smooth_val $steps"
        swap_stat_val
        logcmd "swap_stat_val"
      }
      if { $type == "weight" && $statmaskampflag && $statloadedflag} {
        swap_stat_val
        logcmd "swap_stat_val"
        smooth_val_weighted $steps
        logcmd "smooth_val_weighted $steps"
        swap_stat_val
        logcmd "swap_stat_val"
      }
      if { $type == "sparse" && $statmaskampflag && $statloadedflag} {
        swap_stat_val
        logcmd "swap_stat_val"
        smooth_val_sparse $steps
        logcmd "smooth_val_sparse $steps"
        swap_stat_val
        logcmd "swap_stat_val"
      }
    } else { ;# real
      ## smooth real
      if { $type == "valonly" || $type == "val" } {
        smooth_val $steps
        logcmd "smooth_val $steps"
      }
      if { $type == "weight" } {
        smooth_val_weighted $steps
        logcmd "smooth_val_weighted $steps"
      }
      if { $type == "sparse" } {
        smooth_val_sparse $steps
        logcmd "smooth_val_sparse $steps"
      }
      ## smooth stats if loaded
      if { $type == "val" && $statmaskampflag && $statloadedflag} {
        swap_stat_val
        logcmd "swap_stat_val"
        smooth_val $steps
        logcmd "smooth_val $steps"
        swap_stat_val
        logcmd "swap_stat_val"
      }
      if { $type == "weight" && $statmaskampflag && $statloadedflag} {
        swap_stat_val
        logcmd "swap_stat_val"
        smooth_val_weighted $steps
        logcmd "smooth_val_weighted $steps"
        swap_stat_val
        logcmd "swap_stat_val"
      }
      if { $type == "sparse" && $statmaskampflag && $statloadedflag} {
        swap_stat_val
        logcmd "swap_stat_val"
        smooth_val_sparse $steps
        logcmd "smooth_val_sparse $steps"
        swap_stat_val
        logcmd "swap_stat_val"
      }
    }
  }
}

#proc do_smooth { } {
#  global smoothsteps
#
#  if ![string is int "$smoothsteps"] {
#    set smoothsteps 5
#    logcmd "set smoothsteps 5"
#  }
#  smoothbutton
#}

proc do_smooth_curv { } { 
  global smoothsteps smoothtype curvloadedflag

  if {!$curvloadedflag} { confirmalert "curv field not loaded"; return }
  if ![string is int "$smoothsteps"] {
    set smoothsteps 5
    logcmd "set smoothsteps 5"
  }
  set smoothtype curv  ;# just tcl (radio var), don't log
  smoothbutton         ;# calls proc smooth which logs cmds
}

proc do_smooth_valonly { } { 
  global smoothsteps smoothtype valloadedflag

  if {!$valloadedflag} { confirmalert "val field not loaded"; return }
  if ![string is int "$smoothsteps"] {
    set smoothsteps 5
    logcmd "set smoothsteps 5"
  }
  set smoothtype valonly
  smoothbutton
}

proc do_smooth_stat { } { 
  global smoothsteps smoothtype statloadedflag

  if {!$statloadedflag} { confirmalert "stat field not loaded"; return }
  if ![string is int "$smoothsteps"] {
    set smoothsteps 5
    logcmd "set smoothsteps 5"
  }
  set smoothtype stat
  smoothbutton
}

proc do_smooth_val { } { 
  global smoothsteps smoothtype valloadedflag

  if {!$valloadedflag} { confirmalert "val field not loaded"; return }
  if ![string is int "$smoothsteps"] {
    set smoothsteps 5
    logcmd "set smoothsteps 5"
  }
  set smoothtype val
  smoothbutton
}

proc do_smooth_cpxreal { } { 
  global smoothsteps smoothtype valloadedflag val2loadedflag

  if {!$valloadedflag || !$val2loadedflag} {
    confirmalert "val/val2 fields not loaded"
    return
  }
  if ![string is int "$smoothsteps"] {
    set smoothsteps 5
    logcmd "set smoothsteps 5"
  }
  set smoothtype cpxreal
  smoothbutton
}

proc do_smooth_weight { } { 
  global smoothsteps smoothtype valloadedflag

  if {!$valloadedflag} { confirmalert "val field not loaded"; return }
  if ![string is int "$smoothsteps"] {
    set smoothsteps 5
    logcmd "set smoothsteps 5"
  }
  set smoothtype weight
  smoothbutton
}

proc do_smooth_sparse { } { 
  global smoothsteps smoothtype valloadedflag

  if {!$valloadedflag} { confirmalert "val field not loaded"; return }
  if ![string is int "$smoothsteps"] {
    set smoothsteps 5
    logcmd "set smoothsteps 5"
  }
  set smoothtype sparse
  smoothbutton
}

proc do_smooth_grad { } { 
  global smoothsteps smoothtype valbakloadedflag val2bakloadedflag

  if {!$valbakloadedflag || !$val2bakloadedflag} {
    confirmalert "gradient (valbak,val2bak fields) not loaded"
    return
  }
  if ![string is int "$smoothsteps"] {
    set smoothsteps 5
    logcmd "set smoothsteps 5"
  }
  set smoothtype grad
  smoothbutton
}

proc do_annotholes { } { 
  global smoothsteps annotloadedflag

  if {!$annotloadedflag} { confirmalert "no label/annotation loaded"; return }
  set smoothsteps annotholes
  logcmd "set smoothsteps annotholes"
  smoothbutton
}

proc do_valholes { } { 
  global smoothsteps valloadedflag

  if {!$valloadedflag} { confirmalert "val field not loaded"; return }
  set smoothsteps valholes
  logcmd "set smoothsteps valholes"
  smoothbutton
}

proc fillholesneighctrls { } { 
  global fillholesneighctrlswin neighord annotedfrac annotloadedflag

  if [winfo exists $fillholesneighctrlswin] {
    raise $fillholesneighctrlswin; return
  }
  set neighord 2   ;# also used by neighop_val2stat (init default: 4)
  set title "FILL ANNOTATION/LABEL HOLES USING:  \
             \n(1) ADJUSTABLE NEIGHBORHOOD     \
             \n (2) ADJUSTABLE ANNOT'ED FRACTION\
         \n\n\$neighord (OK: 1-5) sets the size of the\
           \nneighborhood surrounding each un-annotated\
           \nvertex that is considered, where 1 means\
           \njust nearest neighbors, 2 means include\
           \nneighbors of nearest neighbors, and so on\
           \n(neighord->cnt:  1:7,  2:19,  3:37,  4:61,  5:91)\
         \n\n\$annotedfrac is the fraction of annot'ed\
           \nneighbors over total neighbors (def: 0.5)\
           \nthat is req'd to fill a central vertex hole\
         \n\nlarger neighborhoods (3-5) are increasingly\
           \nslower (can cut away surface to speed up)"
  set variablelist "whitespace \
                    neighord \
                    annotedfrac \
                    whitespace"
  set fillholesneighctrlswin \
    [controls $title $variablelist "FILL HOLES" do_fillholesneigh 7]
  bind $fillholesneighctrlswin <ButtonRelease-3> { helpwin smooth_steps }
}

proc do_fillholesneigh { } {
  global neighord annotedfrac labelflag annotloadedflag

  if {!$annotloadedflag} { confirmalert "no label/annotation loaded"; return }
  if  { $neighord < 1 || $neighord > 5 } {
    confirmalert "Fill Annot Holes Using Neighborhood:\
              \n\nbad \$neighord:\n\n    $neighord\n\n(OK:1-5)"
    return
  }
  if {!$labelflag} {
    confirmalert "Fill Annot Holes Using Neighborhood:\
              \n\nno label(s) (to fill) currently displayed"
    return
  }

  fill_annot_holes_neigh $neighord $annotedfrac
  logcmd "fill_annot_holes_neigh $neighord $annotedfrac"
  set annotbordflag 0    ;# ON confusingly enlarges holes
  logcmd "set annotbordflag 0"
  redrawbutton  ;# only here: other non-int 'steps' get redraw from SMOOTH butt
  confirmalert "To save new label:\
         \n\n  (1) re-cut new label (ctrl-L-clk \"C\" on \"label:\" line)\
           \n  (2) CHANGE NAME in \"label:\" line entry to avoid overwrite!\
           \n  (3) save label with \"W\" on \"label:\" line"
}

proc do_annoterode { } { 
  global smoothsteps annotloadedflag

  if {!$annotloadedflag} { confirmalert "no label/annotation loaded"; return }
  set smoothsteps annoterode
  logcmd "set smoothsteps annoterode"
  smoothbutton
}

proc transform { } {
  global xrot yrot zrot xtrans ytrans scalepercent

  if {$xrot != 0} {
    rotate_brain_x $xrot
    logcmd "rotate_brain_x $xrot"
  }
  if {$yrot != 0} {
    rotate_brain_y $yrot
    logcmd "rotate_brain_y $yrot"
  }
  if {$zrot != 0} {
    rotate_brain_z $zrot
    logcmd "rotate_brain_z $zrot"
  }
  if {$xtrans != 0} {
    translate_brain_x $xtrans
    logcmd "translate_brain_x $xtrans"
  }
  if {$ytrans != 0} {
    translate_brain_y $ytrans
    logcmd "translate_brain_y $ytrans"
  }
  if {$scalepercent != 100} {
    scale_brain [expr $scalepercent/100.0]
    logcmd "scale_brain [expr $scalepercent/100.0]"
  }
}

proc resettransform { } {   ;# re-zero sliders
  global xrot yrot zrot xtrans ytrans scalepercent

  set xrot 0
  set yrot 0
  set zrot 0
  set xtrans 0
  set ytrans 0
  set scalepercent 100
}

proc redrawbutton { {raiseflag 1} } {  ;# for speed, use plain 'redraw'
  global openglwindowflag tksurferlogflag delayredrawflag
  global vtxcolflag warnvtxcolflag

  # N.B.: tksurfer.c do_one_gl_event() pose changes call this from C
  if {$openglwindowflag} {  ;# prevent (harmless) errs before GLwin open
    transform
    resize_window 0
    do_lighting_model
    if {$raiseflag} { raise_window }
    redraw
    logcmd "redraw"
    resettransform
    if {$delayredrawflag} {after 100} ;#fix runaway var incr w/fast trough clks
    if {$vtxcolflag && $warnvtxcolflag} {
      confirmalert "N.B.: \$vtcolflag=ON so vtxcol \"paint\" may occlude data!"
      set warnvtxcolflag 0  ;# once, new read vtxcol re-arms
    }
  }
}

proc restore {  } {
  global env flag2d flatzrot flatxtrans flatytrans flatscale patch subject

  resettransform
  if {$flag2d && ![string match *.3d $patch] } {
    restore_zero_position
    logcmd "restore_zero_position"
    rotate_brain_x -90
    logcmd "rotate_brain_x -90"
    # setdefpatchview.tcl sets vars to touch up translate/scale flat
    if [file exists $env(CSURF_DIR)/lib/tcl/setdefpatchview.tcl] {
      uplevel #0 {
        source $env(CSURF_DIR)/lib/tcl/setdefpatchview.tcl
        logcmd "# source $env(CSURF_DIR)/lib/tcl/setdefpatchview.tcl"
      }
      prompt
    }  ;# from csurf patch: combo, whether started w/flat or 3D
    if [info exists flatzrot]   {
      rotate_brain_z $flatzrot
      logcmd "rotate_brain_z $flatzrot"
    }
    if [info exists flatxtrans] {
      translate_brain_x $flatxtrans
      logcmd "translate_brain_x $flatxtrans"
    }
    if [info exists flatytrans] {
      translate_brain_y $flatytrans
      logcmd "translate_brain_y $flatytrans"
    }
    if [info exists flatscale] {
      scale_brain $flatscale
      logcmd "scale_brain $flatscale"
    }
  } else {
    make_lateral_view
    logcmd "make_lateral_view"
    if [string match "*cereb*" $subject] {  ;# hack
      rotate_brain_y -90
      logcmd "rotate_brain_y -90"
    }
  }
  redraw
  logcmd "redraw"
}

proc select_surfext { combo value } {   ;# tixcombo appends entry value
  global insurf insurfabbrev hemi surfext lastsurfext flag2d

  ### 4 other!: cbxinit, tksurfer:make_filenames, csurf:tksurfercmd,fixsurfaces
  ## N.B.: w/obj,srf, if tksurfer can't find $hemi.$surfext, it tries $surfext
  # strip correct hemi from suff if there
  if [string match $hemi.* $surfext] {
    set surfext [string range $surfext 3 end]
  }
  # override preappend hemi special cases
  if [string match /* $surfext] {  ;# silently accept/fix abspath as '$surfext'
    setfile insurf $surfext
    set surfext [string range [file tail $surfext] 3 end]
  } elseif { [string match *.surf.gii $surfext] &&
             ![string match "\[rl\]h.*" $surfext] } { ;# non-conform GIFTI
    setfile insurf $surfext
  } elseif { [string match *.obj $surfext] &&
             ![string match "\[rl\]h.*" $surfext] } {
    setfile insurf $surfext          ;# .../surf/asdf.obj
    if ![file exists $insurf] {
      setfile insurf $hemi.$surfext  ;# .../surf/rh.asdf.obj
    }
  } elseif { [string match *.srf $surfext] &&
             ![string match "\[rl\]h.*" $surfext] } {
    setfile insurf $surfext
    if ![file exists $insurf] { setfile insurf $hemi.$surfext }
  } else {  ;# add back hemi prefix
    setfile insurf $hemi.$surfext
  }

  ### TODO: new flag: also redraw if last flat and new is 3D (to patch cuts)
  # block redraw same b/c in here twice (from select event *and* change -value)
  if { ![info exists lastsurfext] || $lastsurfext != $surfext || $flag2d} {
    set lastsurfext $surfext  ;# N.B.: set before rereaddrawsurf b/c reentry!
    rereaddrawsurf
  }
}

proc rereaddrawsurf { } {
  global insurf insurfabbrev subject hemi surfext surfextorig flag2d

  if ![file exists $insurf] {
    confirmalert \
      "no such surf:\n\n    $insurf\n\nstartup surf reloaded: $surfextorig"
    set surfext $surfextorig
    setfile insurf $hemi.$surfext
    resettransform
    make_lateral_view
    logcmd "make_lateral_view"
    if [string match "*cereb*" $subject] {  ;# hack
      rotate_brain_y -90
      logcmd "rotate_brain_y -90"
    }
  } else {  ;# flat->3D: reset view, 3D->3D: leave pose
    if {$flag2d} {  ;# reset next
      resettransform
      make_lateral_view
      logcmd "make_lateral_view"
      if [string match "*cereb*" $subject] {  ;# hack
        rotate_brain_y -90
        logcmd "rotate_brain_y -90"
      }
    }
  }
  set flag2d 0
  logcmd "set flag2d 0"
  clear_ripflags
  logcmd "clear_ripflags"
  read_binary_surface
  logcmd "read_binary_surface"
  redrawbutton
  wm title . "tksurfer ($subject $hemi $surfext)"
  chkclearself
  chklefthandedsurf $surfext
}

proc chklefthandedsurf { surfext } {
  global chkleftcnt lastleftsubject subject

  if ![info exists lastleftsubject] { set lastleftsubject $subject }
  if [string match *.srf $surfext] {  ;# currently just by suffix!
    if ![info exists chkleftcnt] { set chkleftcnt 0 } 
    if {"$subject" != "$lastleftsubject"} { set chkleftcnt 0 }  ;# re-arm
    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 lastleftsubject $subject
}

proc select_curv { combo value } {   ;# tixcombo appends entry value
  global curv curvabbrev cslope cmid inside_select_curv lastframecnt
  global env tfrmctrlswin genstrret_1k template sphregcoordsloaded lasttemplate

  # N.B.: this proc called if bound var, $curvabbrev, is touched
  # N.B.: here 2x if change $curv AND click/unclk, select from persist dropdown
  $combo config -disablecallback true  ;# N.B.: makes $curv stale

  if [string match *.tif $value] { ;# multiframe tif (9:H/sulc/curv,av/var/dof)
    set template $value  ;# fname for read_tif_header, read_tif_template
    if { ![info exists env(FSURF_DIR)] || \
         ![string match $env(FSURF_DIR)/average/* $curv] } {  ;# leave abs tif
      #uplevel #0 "setfile template $value"  ;# fails w/space
      uplevel #0 "setfile template \"$value\"" ;# glob/reabbrev sess dir *.tif
    }
    if ![file exists $template] {
      confirmalert "template file:\n\n    $template\n\nnot found"
      $combo config -disablecallback false
      return
    }
    if {!$sphregcoordsloaded} {
      confirmalert "Registered sphere coords not yet loaded:\
                \n\nfirst load sphere.reg one time"
      $combo config -disablecallback false
      return
    }
    read_tif_header
    if ![info exists lasttemplate] { set lasttemplate no_previous_file }
    if ![info exists lastframecnt] { set lastframecnt -1 }
    set framecnt 0
    foreach line [split $genstrret_1k "\n"] {
      if [string match "frames = *" $line]  { set framecnt [lindex $line 2] }
    }
    if {$framecnt < 1} {
      confirmalert "read_tif_header: found bad num frames: $framecnt"
      set lastframecnt $framecnt
      set lasttemplate $template
      $combo config -disablecallback false
      return
    } else {  ;# at least one frame
      if { [info exists tfrmctrlswin] && [winfo exists $tfrmctrlswin] &&
           $framecnt == $lastframecnt && "$template" == "$lasttemplate" } {
        raise $tfrmctrlswin  ;# re-use existing popup
      } else {  ;# make/re-make pop-up
        if { [info exists tfrmctrlswin] && [winfo exists $tfrmctrlswin] } {
          destroy $tfrmctrlswin
          set tfrmctrlswin ""
        }
        if {$framecnt == 9} {
          set title "This .tif file has $framecnt frames\
                   \nPick one (first frame=0, last=[expr $framecnt - 1])\
               \n\nMorph target template frames:\
               \n\n 0, 1, 2:  avg/var/dof inf.H\
                 \n3, 4, 5:  avg/var/dof sulc\
                 \n6, 7, 8:  avg/var/dof curv"
        } else {  ;# frames > 0 but not 9 frames
          set title "This .tif file has $framecnt frames\
                   \nPick one (first frame=0, last=[expr $framecnt - 1])\
                 \n\nN.B.: not standard format, which is:\
                   \n9-frame Mercator proj.: H/sulc/curv)"
        }
        set tfrmctrlswin \
          [controls $title templateframe "READY" readtemplateframe]
      }
      set lastframecnt $framecnt
      set lasttemplate $template
    }
  } else {  ;# orig: curv file of some kind
    #uplevel #0 "setfile curv $value"  ;# fails w/space
    uplevel #0 "setfile curv \"$value\""
    if ![file exists $curv] {
      ### N.B.: here if abbrev directly touched (setfile blocks callbacks)
      ### N.B.: so just touch non-abbrev if for non-interactive script
      confirmalert "curvature file:\n\n    $curv\n\nnot found"
      puts "tksurfer.tcl: ### curvature file not found\ntksurfer.tcl:  $curv"
      $combo config -disablecallback false
      return
    }
    read_binary_curv
    logcmd "read_binary_curv"
    set curvflag 1
    logcmd "set curvflag 1"
  }
  # auto-tweak color settings
  if [string match *.curv $curv] { set cslope 3.0; set cmid 0.0 }
  if [string match *.curv2 $curv] { set cslope 3.0; set cmid 0.0 } ;#for test
  if [string match *.sulc $curv] { set cslope 1.0; set cmid 0.0 }
  if [string match *.sulc2 $curv] { set cslope 1.0; set cmid 0.0 }
  if [string match *.area $curv] { set cslope -1.0; set cmid 1.0 }
  if [string match *.area2 $curv] { set cslope -1.0; set cmid 1.0 }
  if [string match *.area.mid $curv] { set cslope -1.0; set cmid 1.0 }
  if [string match *.area.pial $curv] { set cslope -1.0; set cmid 1.0 }
  if [string match *.area.arat $curv] { set cslope -0.75; set cmid 1.0 }
  if [string match *.area.logarat $curv] { set cslope -0.75; set cmid 0.0 }
  if [string match *.thickness $curv] { set cslope 1.0; set cmid 2.3 }
  if [string match *.tif $value] { set cslope 3.0; set cmid 0.0 }
  set surfcolor 1
  logcmd "set surfcolor $surfcolor"
  redrawbutton
  $combo config -disablecallback false
  after 1000 "$combo config -disablecallback false"
  after 100 "$combo subwidget entry xview moveto 1"
}

proc listcmd_curv { combo } {
  global env subject hemi surfdir curvlooklist templatelooklist
  #global curv curvabbrev

  #set fullfilelist ""
  set fullfilelist {}
  foreach suff $curvlooklist {
    set globlist [lsort [glob -nocomplain \
      $env(SUBJECTS_DIR)/$subject/$surfdir/$hemi.${suff}*]]
    foreach fullfile $globlist {
      #if [file exists $fullfile] { set fullfilelist "$fullfilelist $fullfile" }
      if [file exists $fullfile] { lappend fullfilelist $fullfile } ;# space OK
    }
  }
  if [info exists env(FSURF_DIR)] {
    foreach patt $templatelooklist {  ;#curr matches: average,CURVATURE,buckner
      set globlist [lsort [glob -nocomplain \
        $env(FSURF_DIR)/average/$hemi.${patt}*]]
      foreach fullfile $globlist {
        #if [file exists $fullfile] {set fullfilelist "$fullfilelist $fullfile"}
        if [file exists $fullfile] { lappend fullfilelist $fullfile } ;#space OK
      }
    }
  }
  ### next: manually re-abbreviate vs. clog log with many setfiles
  #set abbrevlist ""
  set abbrevlist {}
  foreach fullfile $fullfilelist {
    #setfile patch $fullfile; set abbrevlist "$abbrevlist $patchabbrev"
    if [string match *.tif $fullfile] {
      #set abbrevlist "$abbrevlist $fullfile"  ;# no abbrev
      lappend abbrevlist $fullfile  ;# space OK
    } else {
      #set abbrevlist "$abbrevlist ~/$surfdir/[file tail $fullfile]"
      lappend abbrevlist ~/$surfdir/[file tail $fullfile]  ;# space OK
    }
  }
  $combo subwidget listbox delete 0 end
  foreach abbrev $abbrevlist { $combo insert end $abbrev }
}

proc select_area { combo value } {   ;# tixcombo appends entry value
  global area areaabbrev area2flag

  # N.B.: in here twice if change area
  # N.B.: this proc called if bound var, $areaabbrev, is touched
  $combo config -disablecallback true
  uplevel #0 "setfile area \"$value\""
  if ![file exists $area] {
    confirmalert "area file:\n\n    $area\n\nnot found"
    puts "tksurfer.tcl: ### area file not found\ntksurfer.tcl:  $area"
    $combo config -disablecallback false
    return
  }
  if {$area2flag} {
    read_binary_areas2
    logcmd "read_binary_areas2"
  } else {
    read_binary_areas
    logcmd "read_binary_areas"
    confirmalert "Original area (.origarea field) redefined by:\n\n$area"
  }
  redrawbutton
  $combo config -disablecallback false
  after 100 "$combo subwidget entry xview moveto 1"
}

proc listcmd_area { combo } {
  global env subject surfdir hemi arealooklist
  #global area areaabbrev

  set fullfilelist {}
  foreach suff $arealooklist {
    set fullfile $env(SUBJECTS_DIR)/$subject/$surfdir/$hemi.$suff
    if [file exists $fullfile] { lappend fullfilelist $fullfile }
  }
  ### next: manually re-abbreviate vs. clog log with many setfiles
  set abbrevlist ""
  foreach fullfile $fullfilelist {
    #setfile area $fullfile; set abbrevlist "$abbrevlist $areaabbrev"
    lappend abbrevlist ~/$surfdir/[file tail $fullfile]
  }
  $combo subwidget listbox delete 0 end
  foreach abbrev $abbrevlist { $combo insert end $abbrev }
}

proc chkareaoverwrite { } {
  global area hemi surfext
  if { [string match *$hemi.area $area] || \
       [string match *$hemi.area.mid $area] || \
       [string match *$hemi.area.pial $area] } {
    set atail [file tail $area]
    confirmalert " N.B.: this will overwrite an \"original area\" file\n\
                   $atail made from $hemi.white surface during\n\
                   initial surface reconstruction with areas calc'd\n\
                   from current surface ($hemi.$surfext)\n\n\
                   (next popup allows cancel)\n\n\
                   (to avoid: add suffix to $atail, then write)"
  }
}

proc calcdisp_arat { } {
  global hemi area2flag area2loaded
  global area areaabbrev curv curvabbrev cmid cslope
  global colscalebarflag colscalerectflag minstatcolscale maxstatcolscale

  if ![okreplace "" " OK to do this?\n\n\
       (1)  \[re\]load area:  $hemi.area\n\
       (2)  load area2:  $hemi.area.pial\n\
       (3)  calculate area ratio (pial/white area)\n\
       (4)  put result in .area to save as $hemi.area.arat\n\
       (5)  read in area ratio as 'curvature'\n\
       (6)  lightly smooth\n\
       (7)  cslope/cmid for inverted/allpos (cslope=-0.75,cmid=1.75)\n\
       (8)  reinstate curr surface area (.area)" \
       "Calc ARatio, Show As Curv"] {
    confirmalert "curv, area, settings untouched"
    return
  } else {
    setfile area ~/surf/$hemi.area       ;# approx flat (objective funct!)
    read_binary_areas
    logcmd "read_binary_areas"
    setfile area ~/surf/$hemi.area.pial  ;# gyral crowns expand
    read_binary_areas2
    logcmd "read_binary_areas2"
    if {!$area2loaded} {
      confirmalert " Calc Area Ratio failed:\n\n\
                     area2 file:\n\n    $areaabbrev\n\n could not be loaded"
      return
    }
    compute_area_ratio
    logcmd "compute_area_ratio"
    setfile area ~/surf/$hemi.area.arat
    write_binary_areas
    logcmd "write_binary_areas"
    setfile curv ~/surf/$hemi.area.arat
    read_binary_curv
    logcmd "read_binary_curv"
    smooth_curv 5
    logcmd "smooth_curv 5"
    set cmid 1.75
    logcmd "set cmid 1.75"
    set minstatcolscale 0.0
    set maxstatcolscale 2.0
    set cslope -0.75
    logcmd "set cslope -0.75"
    set colscalebarflag 1
    logcmd "set colscalebarflag 1"
    # skip log next
    set colscalerectflag 0
    .draw.mesh.rect.arect.bu config -text "rect" -width 4
    redrawbutton
    compute_normals_areas
    logcmd "compute_normals_areas"
  }
}

proc calcdisp_curr2orig_arat { } {
  global hemi area areaabbrev curv curvabbrev cmid cslope
  global colscalebarflag colscalerectflag minstatcolscale maxstatcolscale

  if ![okreplace "" " OK to do this?\n\n\
       (1)  \[re\]load area:  $hemi.area\n\
       (2)  calculate area ratio (curr/orig area)\n\
       (3)  put result in .area to save as $hemi.area.arat\n\
       (4)  read in area ratio as 'curvature'\n\
       (5)  lightly smooth (5 steps)\n\
       (6)  cslope/cmid for inverted/allpos (cslope=-0.75,cmid=1.0)\n\
       (7)  reinstate curr surface area (.area)" \
       "Calc Curr/Orig ARatio, Show As Curv"] {
    confirmalert curv, area, settings untouched"
    return
  } else {
    setfile area ~/surf/$hemi.area
    read_binary_areas
    logcmd "read_binary_areas"
    compute_curr2orig_area_ratio
    logcmd "compute_curr2orig_area_ratio"
    setfile area ~/surf/$hemi.area.arat
    write_binary_areas
    logcmd "write_binary_areas"
    setfile curv ~/surf/$hemi.area.arat
    read_binary_curv
    logcmd "read_binary_curv"
    smooth_curv 5
    logcmd "smooth_curv 5"
    set cmid 1.0
    logcmd "set cmid 1.0"
    set minstatcolscale 0.0
    set maxstatcolscale 2.0
    set cslope -0.75
    logcmd "set cslope -0.75"
    set colscalebarflag 1
    logcmd "set colscalebarflag 1"
    # skip log next
    set colscalerectflag 0
    .draw.mesh.rect.arect.bu config -text "rect" -width 4
    redrawbutton
    compute_normals_areas
    logcmd "compute_normals_areas"
  }
}

proc calcdisp_curr2orig_logarat { } {
  global hemi area areaabbrev curv curvabbrev cmid cslope
  global colscalebarflag colscalerectflag minstatcolscale maxstatcolscale

  if ![okreplace "" " OK to do this?\n\n\
       (1)  \[re\]load area:  $hemi.area\n\
       (2)  calculate area ratio (curr/orig area)\n\
       (3)  take log of area ratio\n\
       (4)  put result in .area to save as $hemi.area.logarat\n\
       (5)  read in log area ratio as 'curvature'\n\
       (6)  lightly smooth (5 steps)\n\
       (7)  cslope/cmid for inverted/zero (cslope=-0.75/cmid=0.0)\n\
       (8)  reinstate curr surface area (.area)" \
       "Calc Curr/Orig LogARatio, Show As Curv"] {
    confirmalert "curv, area, settings untouched"
    return
  } else {
    setfile area ~/surf/$hemi.area
    read_binary_areas
    logcmd "read_binary_areas"
    compute_curr2orig_area_ratio
    logcmd "compute_curr2orig_area_ratio"
    compute_logarea
    logcmd "compute_logarea"
    setfile area ~/surf/$hemi.area.logarat
    write_binary_areas
    logcmd "write_binary_areas"
    setfile curv ~/surf/$hemi.area.logarat
    read_binary_curv
    logcmd "read_binary_curv"
    smooth_curv 5
    logcmd "smooth_curv 5"
    set cmid 0.0
    logcmd "set cmid 0.0"
    set minstatcolscale -1.0
    set maxstatcolscale  1.0
    set cslope -0.75
    logcmd "set cslope -0.75"
    set colscalebarflag 1
    logcmd "set colscalebarflag 1"
    set colscalebarflag 1
    logcmd "set colscalebarflag 1"
    # skip log next
    set colscalerectflag 0
    .draw.mesh.rect.arect.bu config -text "rect" -width 4
    redrawbutton
    compute_normals_areas
    logcmd "compute_normals_areas"
  }
}

proc select_patch { combo value } {   ;# tixcombo appends entry value
  global patch patchabbrev subject hemi surfext flag2d
  global patchsufflooklist openglwindowflag
  global lastpatch shiftkeypressed

  after 100    ;# improve missed shiftkey?
  if {$shiftkeypressed} { return }  ;# select w/o autoload for patch as mask 

  # N.B.: fix in here twice if change patch (just once if re-read same)
  # N.B.: this proc called if bound var, $patchabbrev, is touched
  # N.B.: if click/unclick get dropdown, then select, goes back to flat (revOK)
  if { ![string match *.flat* $value] && ![string match *.3d* $value] } {
    return    ;# if no flattened patch there, patch will be just "?h."
  }
  $combo config -disablecallback true
  uplevel #0 "setfile patch \"$value\""  ;# touches patchabbrev
  if ![file exists $patch] {
    confirmalert "patch file:\n\n    $patch\n\nnot found"
    puts "tksurfer.tcl: ### patch not found\ntksurfer.tcl:  $patch"
    $combo config -disablecallback false
    return
  }
  # mk patchname (e.g., full.patch.flat) for setdefpatchview.tcl not there
  foreach suff $patchsufflooklist {
    if [string match */$hemi.*.patch.${suff}* $patch] {
      uplevel #0 {set patchname [string trimleft [file tail $patch] $hemi.]}
    }
  }
  if {$flag2d} { set was2d 1 } else { set was2d 0 } 
  read_binary_patch  ;# sets flag2d
  logcmd "read_binary_patch"
  if {$openglwindowflag} {  ;# prevent (harmless) errs before GLwin open
    if [string match *.3d $patch] {
      set flag2d 0   ;# back to 3d
      logcmd "set flag2d 0"
      if {$was2d} {  ;# if 2D make lateral view, else leave prev 3D pose
        restore_initial_position
        logcmd "restore_initial_position"
        make_lateral_view
        logcmd "make_lateral_view"
      }
      #rotate_brain_y 180           ;# viewcuts only
      #logcmd "rotate_brain_y 180"  ;# viewcuts only
    } else {  ;# flat
      set dorestore 1
      if [info exists lastpatch] {
        if { [string match [string trimright $patch 0123456789]* $lastpatch] &&
             "$patch" != "$lastpatch" } {
            set dorestore 0  ;# keep pose for flatten steps of same patch
        }
      }
      if {$dorestore} { restore }   ;# does setdefpatchview.tcl
    }
    redrawbutton
  }
  wm title . "tksurfer -- $subject $hemi $surfext ([file tail $patch])"
  set lastpatch $patch
  $combo config -disablecallback false
}

proc listcmd_patch { combo } {
  global env subject hemi surfdir patchtypelooklist patchsufflooklist
  #global patch patchabbrev

  set fullfilelist {}
  foreach type $patchtypelooklist {
    foreach suff $patchsufflooklist {  ;# star after known types, suffs
      set globlist [lsort [glob -nocomplain \
        $env(SUBJECTS_DIR)/$subject/$surfdir/$hemi.${type}*.patch.${suff}*]]
      foreach fullfile $globlist {
        if [file exists $fullfile] { lappend fullfilelist $fullfile }
      }
    }
  }
  # append non-standard patch types, rm copies
  foreach suff $patchsufflooklist {
    set globlist [lsort [glob -nocomplain \
      $env(SUBJECTS_DIR)/$subject/$surfdir/$hemi.*.patch.${suff}*]]
    foreach fullfile $globlist {
      set found 0
      foreach f $fullfilelist { if {"$fullfile" == "$f"} {set found 1} }
      if {!$found} { lappend fullfilelist $fullfile }
    }
  }

  ### next: manually re-abbreviate vs. clog log with many setfiles
  set abbrevlist ""
  foreach fullfile $fullfilelist {
    #setfile patch $fullfile; set abbrevlist "$abbrevlist $patchabbrev"
    lappend abbrevlist ~/$surfdir/[file tail $fullfile]
  }
  $combo subwidget listbox delete 0 end
  foreach abbrev $abbrevlist { $combo insert end $abbrev }
}

proc listcmd_label { combo } {
  global env subject isession scandir hemi labeldir prfdir surfdir
  #global label labelabbrev

  set fullsub $env(SUBJECTS_DIR)/$subject
  set fullfilelist1 [lsort [glob -nocomplain $fullsub/$labeldir/$hemi-*.label]]
  set fullfilelist2 [lsort [glob -nocomplain $fullsub/$labeldir/$hemi-*.cols]]
  set fullfilelist3 [lsort [glob -nocomplain $fullsub/$labeldir/$hemi.*.label]]
  set fullfilelist4 [lsort [glob -nocomplain $fullsub/$prfdir/${hemi}_*.label]]
  set fullfilelist5 [lsort [glob -nocomplain $fullsub/$labeldir/$hemi-*.annot]]
  set fullfilelist6 [lsort [glob -nocomplain $fullsub/$labeldir/$hemi.*.annot]]
  set fullfilelist7 [lsort [glob -nocomplain $fullsub/$labeldir/*.poi]]
  set fullfilelist8 [lsort [glob -nocomplain $fullsub/$surfdir/*.obj]] ;#surfdir
  set fullfilelist9 [lsort [glob -nocomplain $fullsub/$labeldir/$hemi-*.gii]];#-
 set fullfilelist10 [lsort [glob -nocomplain $fullsub/$labeldir/$hemi.*.gii]];#.
 set fullfilelist11 [lsort [glob -nocomplain $isession/$scandir/$hemi*.label]]
  ### next: manually re-abbreviate vs. clog log with many setfiles
  set abbrevlist "{==== CSURF LABELS ====}"
  foreach fullfile $fullfilelist1 {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== CSURF VTXCOLS ====}"
  foreach fullfile $fullfilelist2 {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== MGH LABELS ====}"
  foreach fullfile $fullfilelist3 {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== SamSrf LABELS (prfdir) ====)}"
  foreach fullfile $fullfilelist4 {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist ~/$prfdir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== CSURF ANNOT FILES ====}"
  foreach fullfile $fullfilelist5 {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== MGH ANNOT FILES ====}"
  foreach fullfile $fullfilelist6 {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== POI ANNOT FILES ====}"
  foreach fullfile $fullfilelist7 {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== OBJ SURFACE+COLOR FILES (surfdir) ====}"
  foreach fullfile $fullfilelist8 {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist ~/$surfdir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== GIFTI ANNOTATION FILES ====}"
  foreach fullfile "$fullfilelist9 $fullfilelist10" {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist ~/$labeldir/[file tail $fullfile]"
  }
  set abbrevlist "$abbrevlist {==== SCANDIR LABELS ====}"
  foreach fullfile $fullfilelist11 {
    #setfile label $fullfile; set abbrevlist "$abbrevlist $labelabbrev"
    set abbrevlist "$abbrevlist */$scandir/[file tail $fullfile]"
  }
  $combo subwidget listbox delete 0 end
  foreach abbrev $abbrevlist { $combo insert end $abbrev }
}

proc select_lut { combo value } {   ;# tixcombo appends entry value
  after 100 "$combo subwidget entry xview moveto 1"
}

proc listcmd_lut { combo } {
  global env isession scandir scriptsdir
  #global val2rgblut val2rgblutabbrev

  set fullfilelist1 [glob -nocomplain $isession/$scandir/*.lut]
  set fullfilelist2 [glob -nocomplain $isession/$scriptsdir/*.lut]
  set fullfilelist3 [glob -nocomplain $env(CSURF_DIR)/lib/lut/*.lut]
  ### next: manually re-abbreviate vs. clog log with many setfiles
  set abbrevlist "{==== SCAN DIR LUT's ====}"
  foreach fullfile $fullfilelist1 {
    #setfile val2rgblut $fullfile;set abbrevlist "$abbrevlist $val2rgblutabbrev"
    lappend abbrevlist */$scandir/[file tail $fullfile]
  }
  set abbrevlist "$abbrevlist {==== SCRIPTS DIR LUT's ====}"
  foreach fullfile $fullfilelist2 {
    #setfile val2rgblut $fullfile;set abbrevlist "$abbrevlist $val2rgblutabbrev"
    lappend abbrevlist */$scriptsdir/[file tail $fullfile]
  }
  set abbrevlist "$abbrevlist {==== LIB DIR LUT's ====}"
  foreach fullfile $fullfilelist3 {
    #setfile val2rgblut $fullfile;set abbrevlist "$abbrevlist $val2rgblutabbrev"
    lappend abbrevlist $fullfile  ;# no abbrev for lib/lut
  }
  $combo subwidget listbox delete 0 end
  foreach abbrev $abbrevlist { $combo insert end $abbrev }
}

proc defmissinglutfile { } {
  global val2rgblut

  logcmd "defmissinglutfile"
  if ![file exists $val2rgblut] {
    if ![canwriteormakefile $val2rgblut] {
      confirmalert "Permissions don't allow create default color look-up table"
      return
    }
    set id [open $val2rgblut w 0644]
    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\t88\t88\t88"
    puts $id "1.0\t255\t0\t0"
    puts $id "2.0\t0\t0\t255"
    puts $id "3.0\t0\t255\t0"
    close $id
  } else { return }
}

proc notdivider { fname } {  ;# label,scripts
  if [string match "*====*====" $fname] { return 0 } else { return 1 }
}

proc divider { fname } {  ;# label,scripts
  if [string match "*====*====" $fname] { return 1 } else { return 0 }
}

proc fixmghlabelandcplx { } {  ;# no-op unless complexflag+label
  global hemi label complexvalflag statmaskampflag colscale fslope fthresh fmid

  if { $complexvalflag && [string match *${hemi}.*.label $label] } {
    set labname [string trimleft [file extension [file rootname $label]] .]
    if ![okreplace "" \
           "Can't read real MGH label to complex val display:\n\
           \n    [file tail $label]\n\n\
           (recognized by \".\" instead of \"-\"\n\
           between \"$hemi\" and \"$labname\") into\n\
           COMPLEX-VALUED display.\n\n\
           OK to read MGH label as follows?\n\
           \n  (1) clear currently displayed values\
           \n  (2) turn OFF cpx (complexvalflag)\
           \n  (3) turn OFF stat mask (statmaskampflag)\
           \n  (4) reset colscale to BRy (11)\
           \n  (5) reset fslope to 2.0\
           \n  (6) reset fmid to 0.05\
           \n  (7) reset fthresh to 0.0" \
           "Display MGH label" ] {
      confirmalert "Read MGH label ignored"
      return
    } else {
      clear_values
      logcmd "clear_values"
      set complexvalflag 0
      logcmd "set complexvalflag 0"
      set statmaskampflag 0
      logcmd "set statmaskampflag 0"
      secondsquashents
      logcmd "secondsquashents"
      set colscale 11
      logcmd "set colscale 11"
      set fslope 2.0
      logcmd "set fslope 2.0"
      set fmid 0.05
      logcmd "set fmid 0.05"
      set fthresh 0.0
      logcmd "set fthresh 0.0"
    }
  }
}

proc getsampinfix { } {
  global normdfracflag normdsamp normdmax normdfracsamp normdfracmax
  if {!$normdfracflag} {
    set sampinf mm=[format "%1.1f" $normdsamp]to[format "%1.1f" $normdmax]
  } else {
    set sampinf \
      fr=[format "%1.1f" $normdfracsamp]to[format "%1.1f" $normdfracmax]
  }
  return $sampinf
}

# needed b/c format proc fails (just prints format string) inside bind proc
proc fmtfloat31 { flt } {
  return [format "%3.1f" $flt]
}
### min wish8.5 demo of problem fixed by above
#button .a -text TEST
#pack .a
#bind .a <ButtonRelease-1> {
#  set zz 25.198276543
#  puts "zz=$zz"
#  # next fails -> 3.1f
#  puts "run-3.1-format-inside-bind: [format "%3.1f" $zz]"
#  # next works -> 25.2
#  puts "run-3.1-format-in-proc: [fmtfloat31 $zz]"
#}
#proc fmtfloat31 { flt } {
#  return [format "%3.1f" $flt]
#}

### prev hack method to make no-arg procs for buttonbar that trigger bindings
# [all button code was in bind's, not proc's]
# =================================================================
# setup no-arg 'event generate' procs for buttonbar buttons
# =================================================================
#proc button_proc1 { } {
#  event generate .files.label.br <ButtonRelease-1>
#}
#proc button_proc2 { } {
#  event generate .files.label.br <ButtonRelease-2>
#}
#bind $f.aBUTTON.bu <ButtonRelease-3> {
#  helpwin thisbutton_helpfile
#  buttonbar \
#    "\"Text On First Button (left-click-BUTTON)\" \
#     \"Text on Second Button (mid-clk-BUTTON)\"" \
#    "button_proc1 button_proc2" \
#    ver "BUTTON Button" thisbutton_helpfile
#}
## rm most b/c difficult to maintain, convert bind code into full procs (next)

# begin label D (display) no-arg button procs
############################################################################
proc labelD_display { } {
  global label labelabbrev anlabel anlabelabbrev genstrret_1k
  global labelflag overlayflag annotbordflag padlabelvtxsflag newreadfulllabflag
  global subject filled_currarea filled_origarea labelalpha meshr meshg meshb

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]

  if { [file extension $currabbrev] == ".cols" } {
    confirmalert "Can't use vtx col \"paint\" (*.cols suffix) as label:\
              \n\n    $currabbrev\
              \n\nInstead, middle-click \"R\" to load this file"
    return
  }
  if { [file extension $currabbrev] != ".label" &&
       [file extension $currabbrev] != ".annot" &&
       [file extension $currabbrev] != ".poi" &&
       [file extension $currabbrev] != ".obj" &&
       [file extension $currabbrev] != ".gii"} {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not:\
              \n\n    .label\n    .annot\n    .poi\n    .obj\n    .gii\
              \n\nAssuming file is a .label"
  }
  if { [file extension $currabbrev] == ".label" } {
    setfile label [.files.label.cbx subwidget entry get]
    if ![file exists $label] {
      confirmalert "Label file:\n\n    $label\n\nnot found"
      return
    }
    if ![checkreadlabeldir] { return }  ;# generates error msg
    if {$padlabelvtxsflag} {
      if ![okreplace "" \
           "N.B.: \$padlabelvtxsflag is ON\
        \n\nThis means all *neighbors* of each vertex in label\
          \nwill be same color as that vertex \
          \n(makes isolated vertices more visible) \
        \n\nOK to pad each vertex in label? \
        \n\nIf not, cancel, R-click tickbox to left of \"label:\", \
         \nuntick \"padlabelvtxsflag\", and try again" \
           "Display Label Padding Each Vertex" ] {
        confirmalert "Label not displayed"
        return
      }
    }
    # data ignored, don't check match complexvalflag
    read_label_to_annot_using_col $meshr $meshg $meshb
    logcmd "read_label_to_annot_using_col $meshr $meshg $meshb"
    confirmalert "Display border of label:\n\n    $label\
       \n\ncurr area: [fmtfloat31 $filled_currarea] mm^2\
         \norig area: [fmtfloat31 $filled_origarea] mm^2  (from area file)\
       \n\ncurr color: (rgb: $meshr, $meshg, $meshb)\
         \nreset color: change r,g,b (to right of MESH), redisplay (\"D\")\
       \n\nview filled: R-click tick left of \"label:\", untick annotbordflag"
  } elseif { [file extension $currabbrev] == ".annot" ||
             [file extension $currabbrev] == ".poi" ||
             [file extension $currabbrev] == ".obj" ||
             [file extension $currabbrev] == ".gii"} {
    setfile anlabel [.files.label.cbx subwidget entry get]
    if ![file exists $anlabel] {
      confirmalert "Annotation file:\n\n    $anlabel\n\nnot found"
      return
    }
    if ![checkreadlabeldir] { return }  ;# generates error msg
    if [string match fsaverage* $subject] {
      confirmalert "Display MGH (or POI) annotation borders from:\
                \n\n    $anlabel\
                \n\nR-click \"label\" tick for label controls popup\
                  \n    (e.g., toggle borders: tick/untick annotbordflag)\
                \n\nR-click \"label\" D button for alt functs buttonbar\
                  \n    (e.g., Pick Annot Idnums to View/Mask)\
                \n\nDisplay-window clicks:\
                \n\n    click region to select its color (by MESH), name->log\
                  \n    double-middle-clk region for col/id/neigh/area popup\
                \n\nHOWTO sample this fsaverage .annot to a single subject:\
                \n\n  (1) open single subject\
                  \n  (2) run annot2roi.tcl from \"tcl:\" dropdown"
    } else {
      confirmalert "Display MGH (or POI) annotation transparently:\
                \n\n    $anlabel\
                \n\nLabel control popups:\
                \n\n    R-click \"label\" tick for label controls popup\
                  \n        (e.g., toggle borders: tick/untick annotbordflag)\
                \n\n    R-click \"label\" D button for alternate functions\
                  \n        (e.g., Pick Annot Idnums to View/Mask)\
                \n\nDisplay-window clicks:\
                \n\n    click region to select its color (by MESH), name->log\
                  \n    double-middle-clk region for col/id/neigh/area popup"
    }
    if { [file extension $currabbrev] == ".annot" } {
      read_mgh_annot
      logcmd "read_mgh_annot"
      display_ctab   ;# TODO: rm if too irritating
      set labelalpha 255    ;# redundant, read_mgh_annot does this
      logcmd "set labelalpha 255"  ;# leave single *.label's transparent
      puts \
      "tksurfer.tcl: orig area all regions (except Unknown): $genstrret_1k mm^2"
    }
    if { [file extension $currabbrev] == ".poi" } {
      read_poi_to_annot
      logcmd "read_poi_to_annot"
    }
    if { [file extension $currabbrev] == ".obj" } {
      read_obj_to_annot   ;# ignores surface coords
      logcmd "read_obj_to_annot"
    }
    if { [file extension $currabbrev] == ".gii" } {
      read_gifti_to_annot   ;# ignores surface coords
      logcmd "read_gifti_to_annot"
      display_ctab   ;# TODO: rm if too irritating
    }
    set_annot_alpha $labelalpha  ;# else def MGH annot alpha=0=invisible
    logcmd "set_annot_alpha $labelalpha"
  } else {
    setfile label [.files.label.cbx subwidget entry get]
    if ![checkreadlabeldir] { return }
    read_label_to_annot_using_col $meshr $meshg $meshb
    logcmd "read_label_to_annot_using_col $meshr $meshg $meshb"
  }
  set labelflag 1
  logcmd "set labelflag 1"
  set overlayflag 1    ;# less confusing w/colored labels
  logcmd "set overlayflag 1" 
  if {$newreadfulllabflag} {  ;# OFF by default, so startup is just border
    set annotbordflag 0  ;# constantly doing this w/label construction
    logcmd "set annotbordflag 0"
  } else {
    set annotbordflag 1  ;# constantly doing this w/overlay data
    logcmd "set annotbordflag 1"
  }
  redrawbutton
  reselect_selected_list  ;# after redraw
  logcmd "reselect_selected_list"
  labeltickctrls  ;# for immed. acces to annotbordflag
}

proc labelD_undocut { } {
  global label labelabbrev

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return 
  }

  if ![checkreadlabeldir] { return }  ;# generates error msg
  if ![okreplace "" "OK to use surface label:\
      \n\n    $label\
      \n\nto undo cuts in current surface?" "Undo Cuts Using Label"] {
    confirmalert "No cuts undone"
  } else {
    read_label_to_undo_cut
    logcmd "read_label_to_undo_cut"
    redrawbutton
  }
}

proc labelD_label2roi3d { } {
  global subject isession scandir label labelabbrev registerdatloaded

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return
  }
  if ![checkreadlabeldir] { return }  ;# generates error msg
  if [string match fsaverage* $subject] {
    if ![okreplace "" "Designed to convert surface label to 3D AFNI ROI\
                     \nin rawdata voxels for single-subject funct session:\
        \n\nUse on fsaverage anyway?" "Use fsaverage"] {
      confirmalert "No surface label converted"
      return
    }
  }
  if {$scandir == "__noscandir__"} {
    confirmalert "Scandir not defined: start tksurfer from funct session"
    return
  }
  if {!$registerdatloaded} {
    confirmalert "register.dat not loaded"
    return
  }
  if ![okreplace "" "OK to convert surface label:\
      \n\n    $label\
      \n\nto AFNI ROI mask BRIK?" "Convert Surface Label"] {
    confirmalert "No surface label converted"
    return
  }
  write_label_timecourses_stats 3  ;# 3=3dROI special case
  logcmd "write_label_timecourses_stats 3"
  confirmalert "surface label:\
            \n\n    [file tail $label]\
            \n\nexported to rawdata-resolution 3D ROI (0/1) BRIK:\
            \n\n    [file rootname [file tail $label]]-[getsampinfix]+orig.BRIK\
            \n\nin scandir:\
            \n\n    $isession/$scandir"
}

proc labelD_annot2roi3d { } {
  global subject isession scandir hemi label labelabbrev meshr meshg meshb
  global brainregioncnt brainregionname registerdatloaded

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".annot" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .annot"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return
  }
  if ![checkreadlabeldir] { return } ;# generates error msg
  if [string match fsaverage* $subject] {
    if ![okreplace "" "Designed to convert surface label to 3D AFNI ROI\
                     \nin rawdata voxels for single-subject funct session:\
        \n\nUse on fsaverage anyway?" "Use fsaverage"] {
      confirmalert "No surface label converted"
      return
    }
  }
  if {!$brainregioncnt} {
    confirmalert "No MGH annot loaded:\n\nUse \"D\" button on label line"
    return
  }
  annotcol2brainregionname $meshr $meshg $meshb  ;# before genstrret_1k
  if {$brainregionname == ""} {
    confirmalert "No region found with:\
              \n\n    rgb = ($meshr, $meshg, $meshb)\
              \n\nFirst click an annotation region\
                \nto load its r,g,b color"
    return
  } 
  if {$scandir == "__noscandir__"} {
    confirmalert "Scandir not defined: start tksurfer from funct session"
    return
  }
  if {!$registerdatloaded} {
    confirmalert "register.dat not loaded"
    return
  }
  if ![okreplace "" "OK to convert brain region:\
        \n\n    $brainregionname\
          \n    rgb = ($meshr, $meshg, $meshb)\
        \n\nin MGH annotation:\
        \n\n    $label\
        \n\nto AFNI ROI mask BRIK?" "Convert Annot Region"] {
    confirmalert "No .annot regions converted"
    return
  }
  # next makes tmplabel w/brainreg name to pass to write_label_timecourses_...
  write_annotcol_timecourses_stats $meshr $meshg $meshb 3 ;#3=3dROI
  logcmd "write_annotcol_timecourses_stats $meshr $meshg $meshb 3"
  confirmalert "rawdata-res 3D ROI BRIK written for:\
            \n\n    MGH annot col: r=$meshr g=$meshg b=$meshb\
            \n\nscandir: $isession/$scandir\
              \nfile: $hemi-region_$brainregionname+orig.BRIK"
}

proc labelD_masksubset { } {
  # annotmaskctrls wrapped for labelD_* name consistency
  annotmaskctrls
}

proc labelD_annots2roi { } {
  global subject isession scandir label labelabbrev
  global brainregioncnt registerdatloaded

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".annot" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .annot"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return 
  }
  if ![checkreadlabeldir] { return }
  if [string match fsaverage* $subject] {
    if ![okreplace "" "Designed to convert surface labels to 3D AFNI ROIs\
                     \nin rawdata voxels for single-subject funct session:\
        \n\nUse on fsaverage anyway?" "Use fsaverage"] {
      confirmalert "No surface label converted"
      return
    }
  }
  if {!$brainregioncnt} {
    confirmalert "No MGH annot loaded:\n\nUse \"D\" button on label line"
    return
  }
  if {$scandir == "__noscandir__"} {
    confirmalert "Scandir not defined: start tksurfer from funct session"
    return
  }
  if {!$registerdatloaded} {
    confirmalert "register.dat not loaded"
    return
  }
  if ![okreplace "" "OK to convert ALL brain regions in\n\n  $label\
          \n\nto AFNI ROI mask BRIK's?   (takes 1-2 min)\
          \n\nN.B.: faster if sampling surf (usu. orig) loaded"\
          "Convert All Annot Regions"] {
    confirmalert "No .annot regions converted"
  } else {
    #next mks tmp labs w/brainregion names to pass to write_timecou..()
    write_annotcols_timecourses_stats 3  ;#3=3dROI
    logcmd "write_annotcols_timecourses_stats 3"
    confirmalert "rawdata-res 3D ROI BRIK's written for:\
              \n\n    all labels in MGH annot: [file tail $label]\
              \n\nto: $isession/$scandir\
              \n\nSee log for ROI BRIK names (brain region prefix)"
  }
}

proc labelD_countnei { } {
  global annotloadedflag statloadedflag

  if {!$annotloadedflag} {
    confirmalert "Can't count annotation neighbors:\
              \n\n    no annotation loaded\
              \n\n    (1) select .annot file from \"label:\" line dropdown\
                \n    (2) left-click \"D\" to load"
    return
  }
  confirmalert "Count neighbors of each MGH annotation region\
            \n\nOutput to:\
            \n\n    .stat field\
              \n    ~/scripts/AnnotRegionsNeighborCounts.txt (incl neighbors)"
  if {$statloadedflag} {
    if ![okreplace "" "The .stat field is already loaded\n\nOK to overwrite?"\
          "Overwrite .stat"] {
      confirmalert "Border count canceled:\n\n.stat field not overwritten"
    } else {
      areaneigh2stat
      logcmd "areaneigh2stat"
    }
  } else {
    areaneigh2stat
    logcmd "areaneigh2stat"
  }
}

proc labelD_label2select { } {
  global label labelabbrev

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return
  }
  if ![checkreadlabeldir] { return }
  confirmalert "Read label, select every vtx in it (as if left-clicked)"
  read_label_to_select
  logcmd "read_label_to_select"
}

proc labelD_calcoverlap { } {
  global env subject hemi annotloadedflag valloadedflag genstrret_1k

  if {!$annotloadedflag} {
    confirmalert "Calc Percent Overlap Annotations and Non-Neg .val:\
              \n\n### annotation not loaded! (from *.annot file)\
              \n\n(1) select .annot file from \"label:\" line dropdown\
                \n(2) left-click \"D\" to load it"
    return
  }
  if {!$valloadedflag} {
    confirmalert "Calc Percent Overlap of Annotations and Non-Neg .val:\
     \n\n### .val field not loaded! (from read *.w, *.mgh, or *.label)\
     \n\n(1) select valfile from \"val:\" dropdown, click \"val:\" \"R\"\
       \n    *or*\
       \n(2) select labelfile from \"label:\" dropdown, click \"label:\" \"R\""
    return
  }
  if [file exists $env(SUBJECTS_DIR)/$subject/scripts/$hemi.overlap.txt] {
    if ![okreplace "" "Overlap Calculation Output File:\
                 \n\n    $env(SUBJECTS_DIR)/$subject/scripts/$hemi.overlap.txt\
                 \n\nexists.  OK to overwrite?" "Overwrite"] {
      return
    }
  }
  calc_annots_nzval_overlap
  logcmd "calc_annots_nzval_overlap"
  confirmalert $genstrret_1k
}

proc labelD_currcol2vtxcol { } {
  currcol_to_vtxcol
  logcmd "currcol_to_vtxcol"
  confirmalert "Copied DATA colors to fixed vtxcol \"paint\" fields\
              \n(.vr/.vg/.vb)\
            \n\nTo save to *.cols file, use ctrl-R-clk \"W\" on \"label:\" line\
            \n\nN.B.: first mid-clk-CLR vtxcols to omit results of prev copying\
              \nN.B.: all visible vertices copied - recut label for subset\
              \nN.B.: ignores displayed transparent labels/annotations"
}

proc labelD_labelcol2vtxcol { } {
  labelcol_to_vtxcol
  logcmd "labelcol_to_vtxcol"
  confirmalert "Copied LABEL / ANNOT colors to fixed vtxcol \"paint\" fields\
              \n(.vr/.vg/.vb)\
            \n\nTo save to *.cols file, use ctrl-R-clk \"W\" on \"label:\" line\
            \n\nN.B.: first mid-clk-CLR vtxcols to omit results of prev copying\
              \nN.B.: all visible vertices copied - recut label for subset\
              \nN.B.: ignores displayed data if any"
}

proc labelD_displaynearest { } {  ;# no-hotkey (all used), button bar only
  global label labelabbrev anlabel anlabelabbrev genstrret_1k
  global labelflag overlayflag annotbordflag padlabelvtxsflag
  global subject filled_currarea filled_origarea labelalpha meshr meshg meshb

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]

  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Read Label to Nearest Vertices: requires *.label suffix:\
              \n\nBad suffix:\
              \n\n    $currabbrev"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return
  }
  if ![checkreadlabeldir] { return }  ;# generates error msg
  if {$padlabelvtxsflag} {
    if ![okreplace "" \
         "N.B.: \$padlabelvtxsflag is ON\
      \n\nThis means all *neighbors* of each vertex in label\
        \nwill be same color as that vertex \
        \n(makes isolated vertices more visible) \
      \n\nOK to pad each vertex in label? \
      \n\nIf not, cancel, R-click tickbox to left of \"label:\", \
       \nuntick \"padlabelvtxsflag\", and try again" \
         "Display Label Padding Each Vertex" ] {
      confirmalert "Label not displayed"
      return
    }
  }

  # allow bugout (long run time w/lg surf), add info
  if ![okreplace "" "Read Label to Nearest Vertices:\
                 \n\n    $label\
                 \n\nEstimate location on current surface of label\
                   \nwritten from different, but closely similar, surface\
                   \n(e.g., two different edits of same subject)\
                 \n\nN.B.: label (args 2,3,4) must contain .orig coords!\
                 \n\n-- computation time proportional to label size\
                   \n-- slow with large surface (40m on 5M vtx cerebellum)\
                   \n-- can speed up by cutting away irrelavant surf parts" \
                 "Est. Foreign-Surf Label Loc."] { return }

  # data ignored, don't check match complexvalflag
  read_label_to_nearest_annot_using_col $meshr $meshg $meshb
  logcmd "read_label_to_nearest_annot_using_col $meshr $meshg $meshb"

  set labelflag 1
  logcmd "set labelflag 1"
  set overlayflag 1    ;# less confusing w/colored labels
  logcmd "set overlayflag 1"
  set annotbordflag 0  ;# show whole label!
  logcmd "set annotbordflag 0"
  redrawbutton
  labeltickctrls  ;# for immed. acces to annotbordflag
  confirmalert "Displayed (maybe diff vtx cnt) label on nearest vertices:\
         \n\n    $label\
         \n\ncurr area: [fmtfloat31 $filled_currarea] mm^2\
           \norig area: [fmtfloat31 $filled_origarea] mm^2  (from area file)\
         \n\nN.B.: this new label NOT YET SAVED !!\
         \n\nTo save new label:
           \n  (1) re-cut new label (ctrl-L-clk \"C\" on \"label:\" line)\
           \n  (2) CHANGE NAME in \"label:\" line entry to avoid overwrite!\
           \n  (3) save label with \"W\" on \"label:\" line"
}

# begin label C (cut) no-arg button procs
############################################################################
proc labelC_recut { } {
  global label labelabbrev labelflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return
  }
  if ![checkreadlabeldir] { return }
  if [okreplace "" "Re-cut label file:\n\n$label" "OK" none none "PROCEED"] {
    read_label_cut_clearvals 0
    logcmd "read_label_cut_clearvals 0"
    set labelflag 1
    logcmd "set labelflag 1"
    redrawbutton
  }
}

proc labelC_hole { } {
  global label labelabbrev labelflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return
  }
  if ![checkreadlabeldir] { return }
  if [okreplace "" "Cut hole using label file:\
                \n\n$label\
                \n\n#################################\
                  \n  Be sure to reset label name before save!\
                  \n#################################" "OK" \
        none none "PROCEED"] {
    read_label_cut_clearvals 1
    logcmd "read_label_cut_clearvals 1"
    set labelflag 1
    logcmd "set labelflag 1"
    redrawbutton
  }
}

proc labelC_add { } {
  global label labelabbrev labelflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return
  }
  if ![checkreadlabeldir] { return }
  if [okreplace "" "Restore vertices in label file:\
                \n\n    $label\
                \n\n(N.B.: no effect if those vertices already visible)" "OK" \
        none none "PROCEED"] {
    read_label_cut_clearvals 2
    logcmd "read_label_cut_clearvals 2"
    set labelflag 1
    logcmd "set labelflag 1"
    redrawbutton
  }
}

proc labelC_recutcurr { } {
  global label annotloadedflag labelflag

  if {!$annotloadedflag} {
    confirmalert "Cut current labeled:\n\nFirst load a label"
    return
  }
  if {!$labelflag} {
    confirmalert "Cut current labeled:\n\nFirst display loaded label"
    return 
  }
  if [okreplace \
       "" "Cut current labeled (from):\n\n$label" "OK" none none "PROCEED"] {
    labeled_cut_clearvals 0
    logcmd "labeled_cut_clearvals 0"
    redrawbutton
  }
}

proc labelC_holecurr { } {
  global label annotloadedflag labelflag

  if {!$annotloadedflag} {
    confirmalert "Cut hole using current labeled:\n\nFirst load a label"
    return
  }
  if {!$labelflag} {
    confirmalert "Cut hole using current labeled:\n\nFirst display loaded label"
    return 
  }
  if [okreplace "" "Cut hole using current labeled:\
                \n\n$label\
                \n\n#################################\
                  \n  Be sure to reset label name before save!\
                  \n#################################" "OK" \
        none none "PROCEED"] {
    labeled_cut_clearvals 1
    logcmd "labeled_cut_clearvals 1"
    redrawbutton
  }
}

proc labelC_recutuniq { } {
  global scandir hemi label labelabbrev
  global normdsampuniqvtxflag pointsflag labelflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![checkreadlabeldir] { return } ;#ignore data, don't chk match cmplxvalflag
  set labelsaved $label
  setfile label */$scandir/$hemi-UniqSampVtxs.label  ;# always re-read
  if ![file exists $label] {
    confirmalert "Re-cut label w/uniq vertices:\
              \n\n    uniq vtx label file:   [file tail $label]\
              \n\nnot found in scandir:\
              \n\n    $scandir\
              \n\nRe-run PAINT w/Setup Funct panel \"UniqVtx\" ON\
                \n(or make w/middle-click UQ on \"val3d:\" line)"
    setfile label $labelsaved
    return
  }
  if {!$normdsampuniqvtxflag} {
    confirmalert "Re-cut label w/uniq vertices:\
              \n\n    setting normdsampuniqvtxflag to 1\
              \n\n(left-click \"label:\" to get pop-up to reset)"
    set normdsampuniqvtxflag 1
    logcmd "set normdsampuniqvtxflag 1"
  }
  clear_uniqvoxdata  ;# else stale used if there from prev run
  read_uniqsamp_vertices
  logcmd "read_uniqsamp_vertices"
  setfile label $labelsaved
  confirmalert "Re-cut label w/uniq vertices:\n\n$label"
  read_label_cut_clearvals 0
  logcmd "read_label_cut_clearvals 0"
  after 100
  confirmalert "N.B.: sparse label can't be displayed as faces:\
            \n\n    turning on pointsflag\
            \n\nAfter saving label:\
            \n\n    (1) use INIT to restore surface\
              \n    (2) middle-click MESH to toggle off pointsflag"
  set pointsflag 1
  logcmd "set pointsflag 1"
  set labelflag 1
  logcmd "set labelflag 1"
  redrawbutton
}

# begin label CLR (clear) no-arg button procs
############################################################################
proc labelCLR_annot { } {
  global labelflag

  if ![okreplace "" \
        "Clear (transparently) displayed labels/annotation" \
        "Clear All Labels"] { return }
  clear_annot
  logcmd "clear_annot"
  set labelflag 0
  logcmd "set labelflag 0"
  redrawbutton
}

proc labelCLR_vtxcol { } {
  global vtxcolflag

  if ![okreplace "" \
        "Clear all vertex color label \"paint\"" \
        "Clear Vtxcol \"Paint\""] { return }
  clear_vtxcol_labels
  logcmd "clear_vtxcol_labels"
  set vtxcolflag 0
  logcmd "set vtxcolflag 0"
  redrawbutton
}

proc labelCLR_annotvtxcol { } {
  global labelflag vtxcolflag

  if ![okreplace "" \
        "Clear annotation AND vertex color label \"paint\"" \
        "Clear Labels+Vtxcols"] { return }
  clear_annot
  logcmd "clear_annot"
  set labelflag 0
  logcmd "set labelflag 0"
  clear_vtxcol_labels
  logcmd "clear_vtxcol_labels"
  set vtxcolflag 0
  logcmd "set vtxcolflag 0"
  redrawbutton
}

proc labelCLR_label { } {
  global label labelabbrev

  if ![okreplace "" \
        "Clear annotation just under one label:\n\n    $label" \
        "Clear One Annotation"] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return
  }
  if [checkreadlabeldir] {
    read_label_to_clear_annot
    logcmd "read_label_to_clear_annot"
    redrawbutton
  }
}

proc labelCLR_color { } {
  global meshr meshg meshb

  if ![okreplace "" \
       "Clear annotation with this color?\n\n    r,g,b = $meshr,$meshg,$meshb" \
       "Clear One Annotation"] { return }
  clear_annot_with_col $meshr $meshg $meshb
  logcmd "clear_annot_with_col $meshr $meshg $meshb"
  redrawbutton
}

# begin label R (read) no-arg button procs
############################################################################
proc labelR_val { } {
  global label labelabbrev overlayflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] == ".cols" } {
    confirmalert "Suffix on file is .cols, not .label:\
              \n\nUse mid-clk-R to read vertex cols (vs. vals in label)"
    return
  }
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if [checkreadlabeldir] {
    if [checklabelfile] {
      confirmalert "Read values from label to .val(.val2):\n\n$label"
      set overlayflag 1
      logcmd "set overlayflag 1"
      fixmghlabelandcplx
      logcmd "fixmghlabelandcplx"
      read_realcomplex_or_samcomplex_label_to_val
      fix_nonzero_vals  ;# for sparse smooth
      logcmd "fix_nonzero_vals"
      redrawbutton
    }
  }
}

proc labelR_vtxcol { } {
  global label labelabbrev vclabel vclabelabbrev

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] == ".label" } {
    setfile label [.files.label.cbx subwidget entry get]
    if ![file exists [file rootname $label].cols] {
      confirmalert "Vtxcol (\"paint\") label:\
                \n\n    [file rootname $label].cols\
                \n\nmatching filename pattern of label:\
                \n\n    $label\
                \n\n. . . not found"
      return
    }
    confirmalert "Read vtxcol (\"paint\") label:\
              \n\n    [file rootname $label].cols\
              \n\nmatching filename pattern of label:\
              \n\n    $label"
  } elseif { [file extension $currabbrev] == ".cols" } {
    setfile label [.files.label.cbx subwidget entry get]
    # readvtxcols does next, also do here to avoid stale feedback message
    set vclabel $label
    logcmd "set vclabel $label"
    confirmalert "Read vtxcol (\"paint\") label:\n\n$vclabel"
  } else {
    confirmalert "Bad suffix:\
             \n\n    $currabbrev\
             \n\n(must be *.label or *.cols)"
    return
  }
  if { ![file exists $label] && ![file exists $vclabel] } {
    confirmalert "Vtxcol file:\
              \n\n    $vclabel\
              \n\nNot found.  First make vertex-color label file from an\
                \nexisting label with:\
              \n\n    (1) read label with \"label:\" \"R\"\
                \n    (2) adj displayed label to desired cols\
                \n    (3) middle-click \"W\" on \"label:\" line"
    return
  }
  readvtxcols
  logcmd "readvtxcols"
  redrawbutton
}

proc labelR_valcut { } {
  global label labelabbrev overlayflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if [checkreadlabeldir] {
    if [checklabelfile] {
      confirmalert \
        "Read values from label to .val(.val2) and re-cut it:\n\n$label"
      set overlayflag 1
      logcmd "set overlayflag 1"
      fixmghlabelandcplx
      logcmd "fixmghlabelandcplx"
      read_label_to_val 1
      logcmd "read_label_to_val 1"
      redrawbutton
    }
  }
}

proc labelR_uniqsamp { } {
  global hemi label labelabbrev

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file tail $currabbrev] != "$hemi-UniqSampVtxs.label" } {
    confirmalert "Read UniqSamp Vertices: requires label filename like:\
              \n\n    \?h-UniqSampVtxs.label\
              \n\n. . . quitting Read Uniqsamp Vtxs"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return
  }
  if [checkreadlabeldir] {
    confirmalert "Read uniqsamp vertices from label to .uniqvox{num,cnt}:\
              \n\nNo initial visible effect, but used by:\
              \n\n    \"T\" button (write_label_timecourses_stats)\
                \n    \"X\" button (corr_over_label) searchlight-based xcorr\
                \n    find_FDR_from_pvals"
    read_uniqsamp_vertices
    logcmd "read_uniqsamp_vertices"
  }
}

# begin label W (write) no-arg button procs
############################################################################
proc labelW_write { } {
  global label labelabbrev
  global complexvalflag transform_loaded
  global usecurrcoordsflag usetalcoordsflag normdsampsearchflag
  global xform_mni_305to152_flag normdfracflag normdsamp normdfracsamp

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if ![checknospaces $currabbrev] { return }
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on intended output file in \"label:\" entry:\
              \n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if [checkwritelabeldir] {
    if {$complexvalflag} {set targ ".val/.val2"} else {set targ ".val"}
    if {$usecurrcoordsflag} {
      set coords "N.B.: x,y,z coords in file: from CURRENT surface"
    } elseif {$usetalcoordsflag && $transform_loaded} {
      if {$xform_mni_305to152_flag} {
        set coords "N.B.: x,y,z coords in file: MNI Talairach 152"
      } else {
        set coords "N.B.: x,y,z coords in file: MNI Talairach 305"
      }
    } else {
      set coords "N.B.: x,y,z coords in file: from freesurfer .orig surface"
    }
    if {$normdsampsearchflag && !$usecurrcoordsflag} {
      if {$normdfracflag} {
        set normsearch \
   "N.B.: x,y,z coords INCLUDE move along normal ($normdfracsamp ctx thk)\
  \n            (left-click \"label:\" label for curr parms)\
  \n            (for no move, untick normdsampsearchflag)"
      } else {
        set normsearch \
                "N.B.: x,y,z coords INCLUDE move ($normdsamp mm) along normal\
               \n            (left-click \"label:\" label for curr parms)\
               \n            (for no move, untick normdsampsearchflag)"
      }
    } else {
      set normsearch "N.B.: x,y,z coords NOT modified by move along normal"
    }
    set mesg "Write $targ for currently visible vertices to:\
          \n\n    $label\
          \n\n$coords\
            \n$normsearch\
          \n\n(next checks overwrite)"
    if ![okreplace "" "$mesg" "Write *.label File"] { return }
    testreplace $label write_val_visible_vertices
  }
}

proc labelW_vtxcol { } {
  global label labelabbrev

  if [divider $labelabbrev] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if ![file exists $label] {
    confirmalert "Input file to convert to vtxcol \"paint\":\
              \n\n    $label\
              \n\nnot found.  First save a label with:\
              \n\n    (1) define label by cuts and/or ROI\
                \n    (2) left-click \"W\" on \"label:\" line"
    return
  }
  if ![okreplace "" "Render label data from:\
                 \n\n    $label\
                 \n\nusing current color scale settings and\
                 \nconvert to vtxcol label (fixed \"paint\")" \
                   "Write vtxcol (*.cols) File"] { return }
  labeltovtxcols
}

proc labelW_annot { } {
  global label labelabbrev annotbordflag
  global complexvalflag transform_loaded
  global usetalcoordsflag usecurrcoordsflag normdsampsearchflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  if {$annotbordflag} {
    if [okreplace "" "N.B.: \$annotbordflag is ON\
               \n\nSince this would result in label with data only\
                 \nunder label border, OK to turn it OFF?\
               \n\n(if you actually want this, hit \"Cancel\")" \
                   "Turn OFF \$annotbordflag"] {
      set annotbordflag 0
      logcmd "set annotbordflag 0"
    }
  }
  setfile label [.files.label.cbx subwidget entry get]
  if [checkwritelabeldir] {
    if {$complexvalflag} {set targ ".val/.val2"} else {set targ ".val"}
    if {$usecurrcoordsflag} {
      set coords "N.B.: x,y,z coords in file: from CURRENT surface"
    } elseif {$usetalcoordsflag && $transform_loaded} {
      set coords "N.B.: x,y,z coords in file: .orig conv -> MNI Talairach"
    } else {
      set coords "N.B.: x,y,z coords in file: from .orig surface"
    }
    if {$normdsampsearchflag && !$usecurrcoordsflag} {
      set normsearch "N.B.: x,y,z coords INCLUDE move along normal\
                    \n            (left-click \"label:\" label for curr parms)\
                    \n            (for no move, untick normdsampsearchflag)"
    } else {
      set normsearch "N.B.: x,y,z coords NOT modified by move along normal"
    }

    if ![okreplace "" "Write $targ under all annotated vertices to:\
                   \n\n    $label\
                   \n\n$coords\
                     \n$normsearch\
                   \n\n(next checks overwrite)" \
                   "Write *.label File"] { return }
    testreplace $label write_val_annoted_vertices
  }
}

proc labelW_annotcol { } {
  global label labelabbrev annotbordflag meshr meshg meshb
  global complexvalflag transform_loaded
  global usetalcoordsflag usecurrcoordsflag normdsampsearchflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on intended output file in \"label:\" entry:\
              \n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  if {$annotbordflag} {
    if [okreplace "" "N.B.: \$annotbordflag is ON\
               \n\nSince this would result in label with data only\
                 \nunder label border, OK to turn it OFF?\
               \n\n(if you actually want this, hit \"Cancel\")" \
                   "Turn OFF \$annotbordflag"] {
      set annotbordflag 0
      logcmd "set annotbordflag 0"
    }
  }
  setfile label [.files.label.cbx subwidget entry get]
  if [checkwritelabeldir] {
    if {$complexvalflag} {set targ ".val/.val2"} else {set targ ".val"}
    if {$usecurrcoordsflag} {
      set coords "N.B.: x,y,z coords in file: from CURRENT surface"
    } elseif {$usetalcoordsflag && $transform_loaded} {
      set coords "N.B.: x,y,z coords in file: .orig conv -> MNI Talairach"
    } else {
      set coords "N.B.: x,y,z coords in file: from .orig surface"
    }
    if {$normdsampsearchflag && !$usecurrcoordsflag} {
      set normsearch "N.B.: x,y,z coords INCLUDE move along normal\
                    \n            (left-click \"label:\" label for curr parms)\
                    \n            (for no move, untick normdsampsearchflag)"
    } else {
      set normsearch "N.B.: x,y,z coords NOT modified by move along normal"
    }
    if ![okreplace "" \
          "Write $targ under MGH annot label col:\
       \n\n    rgb = ($meshr, $meshg, $meshb)\
       \n\n    (current r,g,b from entries right of \"MESH\" butt)\
         \n    (click an annotation region to load its r,g,b vals)\
       \n\nto label:\
       \n\n    $label\
       \n\n$coords\
         \n$normsearch\
       \n\n(next checks overwrite)" \
          "Write *.label File"] { return }
    testreplace $label write_val_annotedcol_vertices $meshr $meshg $meshb
  }
}

proc labelW_annotcols { } {
  global label labelabbrev hemi annotbordflag brainregioncnt
  global complexvalflag transform_loaded
  global usetalcoordsflag usecurrcoordsflag normdsampsearchflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if {$brainregioncnt == 0} {
    confirmalert "No MGH annotation loaded (\$brainregioncnt = 0)"
    return
  }
  # next 4 also in C funct write_val_annotedcols_vertices()
  if ![string match ${hemi}* [file tail $currabbrev]] {
    confirmalert "Write labels for every MGH annotation region:\
              \n\nPrefix for output labels:\
              \n\n    [file tail $currabbrev]\
              \n\ndoesn't match current hemi:\
              \n\n    $hemi\
              \n\n. . . quitting"
    return
  }
  if { [string length [file tail $currabbrev]] < 4 } {
    confirmalert "Write labels for every MGH annotation region:\
              \n\nPrefix for output labels:\
              \n\n    [file tail $currabbrev]\
              \n\nlacks infix of at least 1 char.  Should look like:\
              \n\n    $hemi-<infix>\
              \n\n. . . quitting"
    return
  }
  if { [string range [file tail $currabbrev] 2 2] != "-" } {
    confirmalert "Write labels for every MGH annotation region:\
              \n\nPrefix for output labels:\
              \n\n    [file tail $currabbrev]\
              \n\nmust have '-' (dash) as third character, like this:\
              \n\n    $hemi-<infix>\
              \n\n. . . quitting"
    return
  }
  if [string match *.label $currabbrev] {
    confirmalert "Write labels for every MGH annotation region:\
              \n\nMust omit \".label\" from output prefix in \"label:\" entry:\
              \n\n    [file tail $currabbrev]\
              \n\nIt will be auto-appended after region name\
              \n\n. . . quitting"
    return
  }
  if {$annotbordflag} {
    if [okreplace "" "N.B.: \$annotbordflag is ON\
               \n\nSince this would result in label with data only\
                 \nunder label borders, OK to turn it OFF?\
               \n\n(if you actually want this, hit \"Cancel\")" \
                   "Turn OFF \$annotbordflag"] {
      set annotbordflag 0
      logcmd "set annotbordflag 0"
    }
  }
  if [checkwritelabeldir] {
    if {$complexvalflag} {set targ ".val/.val2"} else {set targ ".val"}
    if {$usecurrcoordsflag} {
      set coords "N.B.: x,y,z coords in file: from CURRENT surface"
    } elseif {$usetalcoordsflag && $transform_loaded} {
      set coords "N.B.: x,y,z coords in file: .orig conv -> MNI Talairach"
    } else {
      set coords "N.B.: x,y,z coords in file: from .orig surface"
    }
    if {$normdsampsearchflag && !$usecurrcoordsflag} {
      set normsearch "N.B.: x,y,z coords INCLUDE move along normal\
                    \n            (left-click \"label:\" label for curr parms)\
                    \n            (for no move, untick normdsampsearchflag)"
    } else {
      set normsearch "N.B.: x,y,z coords NOT modified by move along normal"
    }
    if [okreplace "" "Write separate labels of $targ data\
                    \nunder every region in displayed MGH annotation?\
                  \n\nEach label will have prefix:\
                  \n\n    [file tail $currabbrev]\
                  \n\n$coords\
                    \n$normsearch\
                  \n\n(next checks overwrite)" \
                     "Write $brainregioncnt Labels"] {
      setfile label [.files.label.cbx subwidget entry get]
      write_val_annotedcols_vertices
      logcmd "write_val_annotedcols_vertices"
    } else { confirmalert "no labels written from MGH annotation" }
  }
}

proc labelW_selected { } {
  global label labelabbrev bigcursorflag nmarked
  global complexvalflag transform_loaded annotbordflag
  global usetalcoordsflag usecurrcoordsflag normdsampsearchflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on intended output file in \"label:\" entry:\
              \n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  set annotbordflag 0  ;# silent (error message confusing with indiv vertices)
  logcmd "set annotbordflag 0"
  setfile label [.files.label.cbx subwidget entry get]
  if [checkwritelabeldir] {
    if {$complexvalflag} {set targ ".val/.val2"} else {set targ ".val"}
    if {$usecurrcoordsflag} {
      set coords "N.B.: x,y,z coords in file: from CURRENT surface"
    } elseif {$usetalcoordsflag && $transform_loaded} {
      set coords "N.B.: x,y,z coords in file: .orig conv -> MNI Talairach"
    } else {
      set coords "N.B.: x,y,z coords in file: from .orig surface"
    }
    if {$normdsampsearchflag && !$usecurrcoordsflag} {
      set normsearch "N.B.: x,y,z coords INCLUDE move along normal\
                    \n            (left-click \"label:\" label for curr parms)\
                    \n            (for no move, untick normdsampsearchflag)"
    } else {
      set normsearch "N.B.: x,y,z coords NOT modified by move along normal"
    }
    if {$bigcursorflag} {
      if ![okreplace "" "Write currently selected vertex list (n=$nmarked)\
                       \n(including any $targ data) to label:\
                     \n\n    $label\
                     \n\n$coords\
                       \n$normsearch\
                     \n\nN.B.: since \$bigcursorflag=1, also write neighbors\
                     \n\n(next checks overwrite)" \
                         "Write *.label File"] { return }
      testreplace $label write_val_selected_list_to_label
    } else {
      if ![okreplace "" "Write currently selected vertex list (n=$nmarked)\
                       \n(including any $targ data) to label:\
                     \n\n    $label\
                     \n\n$coords\
                       \n$normsearch\
                     \n\n(next checks overwrite)" \
                         "Write *.label File"] { return }
      testreplace $label write_val_selected_list_to_label
    }
  }
}

proc labelW_mghannot { } {
  # already no-arg lut2annotctrls wrapped for labelW_* name consistency
  lut2annotctrls
}

proc labelW_searchlights { } {
  global env subject hemi surfext label
  global fillneartype num,sqmm,mm searchlightuniqflag numafteruniqflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if ![okreplace "" \
               "Write ASCII searchlights for curr label:\
            \n\n    [file tail $label]\
            \n\nto file:\
            \n\n    $env(SUBJECTS_DIR)/$subject/label/$hemi-Searchlights.txt\
            \n\nusing surface:\
            \n\n    $hemi.$surfext\
            \n\nand searchlight parameters:\
            \n\n    fillneartype = $fillneartype   (0=num, 1=area, 2=rad)\
              \n    criterion = ${num,sqmm,mm}\
              \n    searchlightuniqflag = $searchlightuniqflag\
              \n    numafteruniqflag = $numafteruniqflag\
            \n\nestimated time: 1 min for every 2500 vertices in label" \
                 "Write Searchlights"] { return }
  write_searchlights $fillneartype ${num,sqmm,mm}
  logcmd "write_searchlights $fillneartype ${num,sqmm,mm}"
}

proc labelW_annotcolname { } {
  global annotloadedflag meshr meshg meshb genstrret_1k annotbordflag
  global complexvalflag transform_loaded
  global usetalcoordsflag usecurrcoordsflag normdsampsearchflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  if {!$annotloadedflag} {
    confirmalert "Extract Single Annotation Region to Label:\
              \n\n    no annotation loaded\
              \n\nFirst do following, then try again:\
              \n\n    (1) select  *.annot from \"label:\" dropdown\
                \n    (2) use \"D\" button to read it"
    return
  }
  if {$annotbordflag} {
    if [okreplace "" "N.B.: \$annotbordflag is ON\
               \n\nSince this would result in label with data only\
                 \nunder label border, OK to turn it OFF?\
               \n\n(if you actually want this, hit \"Cancel\")" \
                   "Turn OFF \$annotbordflag"] {
      set annotbordflag 0
      logcmd "set annotbordflag 0"
    }
  }
  if [checkwritelabeldir] {
    if {$complexvalflag} {set targ ".val/.val2"} else {set targ ".val"}
    if {$usecurrcoordsflag} {
      set coords "N.B.: x,y,z coords in file: from CURRENT surface"
    } elseif {$usetalcoordsflag && $transform_loaded} {
      set coords "N.B.: x,y,z coords in file: .orig conv -> MNI Talairach"
    } else {
      set coords "N.B.: x,y,z coords in file: from .orig surface"
    }
    if {$normdsampsearchflag && !$usecurrcoordsflag} {
      set normsearch "N.B.: x,y,z coords INCLUDE move along normal\
                    \n            (left-click \"label:\" label for curr parms)\
                    \n            (for no move, untick normdsampsearchflag)"
    } else {
      set normsearch "N.B.: x,y,z coords NOT modified by move along normal"
    }
    if [okreplace "" "Write $targ under MGH annot label col:\
                   \n\n    rgb = ($meshr, $meshg, $meshb)\
                   \n\nOutput label name uses MGH annot region name\
                   \n\n$coords\
                     \n$normsearch\
                   \n\n(N.B.: doesn't check overwrite)" \
                  "Write Label"] {  ;# allow bail no overwrite check
      write_val_annotedcol_autoname $meshr $meshg $meshb
      logcmd "write_val_annotedcol_autoname $meshr $meshg $meshb"
      confirmalert "wrote label file:\n\n    $genstrret_1k"
    } else { confirmalert "no labels written from MGH annotation" }

  }
}

proc labelW_vtxcol2vtxcol { } {
  global label labelabbrev vclabel vclabelabbrev

  set currabbrev [.files.label.cbx subwidget entry get]
  if [divider $currabbrev] { return }
  if ![string match *.cols $currabbrev] {
    confirmalert "Bad vtxcol label suffix:\
             \n\n    $currabbrev\
             \n\n(must be *.cols)"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  # writevtxcols does next, also do here to avoid stale feedback message
  set vclabel $label  ;# vclabel only used for C/tcl {read,write}_vtxcol_label
  logcmd "set vclabel $label"
  if ![okreplace "" \
         "Save current vtxcol's (fixed \"paint\") to:\
      \n\n    $vclabel" \
         "Write vtxcol (*.cols) File"] { return }
  writevtxcols
}

proc labelW_writeadjphase { } {
  global label labelabbrev
  global valloadedflag val2loadedflag complexvalflag angle_cycles

  if [divider [.files.label.cbx subwidget entry get]] { return }
  set currabbrev [.files.label.cbx subwidget entry get]
  if ![checknospaces $currabbrev] { return }
  if { [file extension $currabbrev] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  if {!$valloadedflag} {
    confirmalert "Write Phase-Adjusted Label:\
              \n\n    .val field not loaded\n\nuse R on .val line"
    return
  }
  if {!$val2loadedflag} {
    confirmalert "Write Phase-Adjusted Label:\
              \n\n    .val2 field not loaded\n\nuse R, S/V on .val line"
    return
  }
  if {!$complexvalflag} {
    confirmalert "Write Phase-Adjusted Label:\n\n    for complex data only"
    return
  }
  if { [expr fmod($angle_cycles,1)] != 0.0 } {
    confirmalert "Write Phase-Adjusted Label:\
             \n\n    for non-integral \$angle_cycles (polar angle) only"
    return
  }
  setfile label [.files.label.cbx subwidget entry get]
  if [checkwritelabeldir] {
    if ![okreplace "" \
                   "Write adjusted phase for currently visible vertices to:\
                \n\n    $label\n\n(next checks overwrite)" \
                   "Write *.label File"] { return }
    testreplace $label write_adjphase_vertices
  }
}  

proc labelW_randcolannot { } {  ;# no-hotkey (all used), button bar only
  global statloadedflag anlabel anlabelabbrev anlabelcombo

  if {!$statloadedflag} {
    confirmalert "Write RandCol Annot: .stat field not loaded:\
             \n\nFirst run neighop_val2stat (shift-mid-clk-SMOOTH)"
    return
  }
  setfile anlabel [.files.label.cbx subwidget entry get]  ;# update!
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $anlabel] != ".annot" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .annot"
    return
  }
  # N.B.: above alternate okreplace usage doesn't check overwrite
  if ![okreplace "" "OK to write RandCol MGH Annot from\
                   \nintegers (assumed!) in .stat field to:\
                 \n\n    $anlabel ?\
                 \n\nN.B.: using curr \"label:\" entry for outfile name" \
                 "Write RandCol Annot"] { return }
  if [file exists $anlabel] {
    if ![okreplace "" "The file:\
               \n\n    $anlabel\
               \n\nalready exists.\
               \n\nReplace it?" \
               "Replace"] { return }
  }
  write_statids2randcolannot
  logcmd "write_statids2randcolannot"
  confirmalert "Wrote file:\
            \n\n  $anlabel\
            \n\nTo see result, load it with \"D\" on \"label:\" line"
}

proc labelW_sortbydist { } {  ;# no-hotkey (all used), button bar only
  global anlabel anlabelabbrev anlabelcombo nmarked

  setfile anlabel [.files.label.cbx subwidget entry get]  ;# update!
  set currabbrev [.files.label.cbx subwidget entry get]
  if { [file extension $anlabel] != ".label" } {
    confirmalert "Suffix on file:\n\n    $currabbrev\n\nis not\n\n    .label"
    return
  }
  if {$nmarked < 1} {
    confirmalert "Sort Label By Euclidean Distance from Last Selected:\
              \n\nNo vertex selected (e.g., select path label origin)"
    return
  }
  if ![okreplace "" "OK to sort label by Euclidean dist from last selected?\
                   \n(each next vtx is closest to previous closest on path)\
                   \n(result saved back to input file):\
                 \n\n    $anlabel\
                 \n\nN.B.: current label will be moved aside to:\
                 \n\n    $anlabel~" \
                 "Distance-Sort/Save Label"] { return }
  write_sorted_by_pathdist_label
  logcmd "write_sorted_by_pathdist_label"
  confirmalert "Wrote file:\
            \n\n    $anlabel\
            \n\nInput vertex-order label moved aside to:\
            \n\n    $anlabel~"
}

proc labelW_centers { } {  ;# no-hotkey (all used), button bar only
  global annotloadedflag env subject scriptsdir

  if {!$annotloadedflag} {
    confirmalert "No annotation loaded\
              \n\nfirst load annotation with \"D\" on \"label:\" line"
    return
  }
  if ![okreplace "" "OK to write annot region centers and nearest vertices\
                   \nto ASCII file:\
                 \n\n    AnnotRegionCenters.txt\
                 \n\nin subject's scriptsdir?\
                 \n\n    $env(SUBJECTS_DIR)/$subject/$scriptsdir" \
                 "Write Region Centers File"] { return }
  set outfile $env(SUBJECTS_DIR)/$subject/$scriptsdir/AnnotRegionCenters.txt
  if [okreplace $outfile] { write_annot_region_centers }
  logcmd "write_annot_region_centers"
  confirmalert "Wrote file:\n\n    $outfile"
}

# begin label T (time-series) no-arg button procs
############################################################################
proc labelT_tseries_at_label { } {
  gettseries label
}

proc labelT_tseries_at_label_amp { } {
  gettseries amp 
}

proc labelT_tseries_at_annotcol { } {
  gettseries rgb 
}

proc labelT_tseries_all_annotcols { } {
  gettseries all 
}

# begin label S (stat/time-series) no-arg button procs
############################################################################
proc labelS_stat_tseries_at_label { } {
  getstattseries label
}

proc labelS_stat_tseries_at_annotcol { } {
  getstattseries rgb 
}

proc labelS_stat_tseries_all_annotcols { } {
  getstattseries all 
}

proc labelS_stat_at_label { } {
  getstat label
}

proc labelS_stat_at_annotcol { } {
  getstat rgb
}

proc labelS_stat_all_annotcols { } {
  getstat all
}
# begin label X (searchlight corr) no-arg button procs
############################################################################
proc labelX_searchlight_corr_at_label { } {
  corrctrls label
}
proc labelX_searchlight_corr_at_annotcol { } {
  corrctrls rgb
}
############################################################################
# end "label:" line no-arg button procs

proc lut2annotctrls { } {  ;# popup to mk MGH annot (ctrl-mid-click "label:" W)
  global lut2annotctrlswin lulabel lulabelabbrev anlabel anlabelabbrev
  global subject hemi env bgcol ffont hfont selbgcol
  global lulabelcombo anlabelcombo

  if [winfo exists $lut2annotctrlswin] { raise $lut2annotctrlswin; return }
  # next so no accid existing label overwrite - N.B. csurf style! (dash not dot)
  setfile anlabel ~/label/$hemi-MY_ANNOT.annot
  set title "ASSEMBLE CSURF LABELS\
           \nINTO MGH ANNOTATION\
         \n\nAll structure names in MGH-style ColorLUT\
           \nmust exist as csurf dash-style labels in\
           \ncurrent subject's ($subject) label dir\
         \n\nFor example, color LUT region name: \"VIP\"\
           \nrequires: $subject/label/$hemi-VIP.label\
         \n\n(1) lulabel: Enter MGH-style Color LUT name\
           \n(2) anlabel: Enter output .annot file name       "
  set variablelist "whitespace lulabel anlabel whitespace"
  set lut2annotctrlswin \
    [controls $title $variablelist "READY" "do_lut2annot" 55]
  ### hack: repl controls-made entry w/tix dropdown filled w/lut (*.txt) files
  pack forget $lut2annotctrlswin.lulabel
  tixComboBox $lut2annotctrlswin.cbx -label "lulabel:" -dropdown true \
    -editable true -variable lulabel -listwidth 400 \
    -command "select_viewend $lut2annotctrlswin.cbx"
  $lut2annotctrlswin.cbx subwidget label config -font $ffont -bg $bgcol
  $lut2annotctrlswin.cbx subwidget entry config -font $hfont \
    -selectbackground $selbgcol -highlightbackground $bgcol -width 55
  $lut2annotctrlswin.cbx subwidget listbox config -font $hfont
  pack $lut2annotctrlswin.cbx -after $lut2annotctrlswin.la -side top
  $lut2annotctrlswin.cbx subwidget entry xview moveto 1
  set globfulllulabels [glob -nocomplain $env(CSURF_DIR)/lib/lut/*]
  foreach fulllulabel $globfulllulabels {
    #$lut2annotctrlswin.cbx insert end [file tail $fulllulabel]
    $lut2annotctrlswin.cbx insert end $fulllulabel
  }
  set lulabelcombo $lut2annotctrlswin.cbx  ;# global for no-arg controls proc
  ### hack2: repl controls-made entry w/tix dropdown filled with .annot files
  pack forget $lut2annotctrlswin.anlabel
  tixComboBox $lut2annotctrlswin.cbx2 -label "anlabel:" -dropdown true \
    -editable true -variable anlabel -listwidth 400 \
    -command "select_viewend  $lut2annotctrlswin.cbx2"
  $lut2annotctrlswin.cbx2 subwidget label config -font $ffont -bg $bgcol
  $lut2annotctrlswin.cbx2 subwidget entry config -font $hfont \
    -selectbackground $selbgcol -highlightbackground $bgcol -width 55
  $lut2annotctrlswin.cbx2 subwidget listbox config -font $hfont
  pack $lut2annotctrlswin.cbx2 -after $lut2annotctrlswin.cbx -side top
  $lut2annotctrlswin.cbx2 subwidget entry xview moveto 1
  set globfullanlabels \
    [glob -nocomplain $env(SUBJECTS_DIR)/$subject/label/*.annot]
  foreach fullanlabel $globfullanlabels {
    #$lut2annotctrlswin.cbx2 insert end [file tail $fullanlabel]
    $lut2annotctrlswin.cbx2 insert end $fullanlabel
  }
  set anlabelcombo $lut2annotctrlswin.cbx2   ;# global for no-arg controls proc
  bind $lut2annotctrlswin <ButtonRelease-3> { helpwin label_write_annot }
}

proc select_viewend { combo value } {   ;# tixcombo appends entry value
  after 100 "$combo subwidget entry xview moveto 1"
}

proc do_lut2annot { } {
  global anlabel lulabel labelflag labelalpha hemi env subject
  global overlayflag statmaskampflag colscale fthresh fmid fslope
  global labelflag complexvalflag revphaseflag invphaseflag truncphaseflag
  global lulabelcombo anlabelcombo pvalborddotflag

  # force read latest cbx entries for hacked lulabel/anlabel controls combos
  set lulabel [$lulabelcombo subwidget entry get]
  set anlabel [$anlabelcombo subwidget entry get]
  if ![file exists $lulabel] {
    confirmalert "FreeSurfer Color LUT:\n\n    $lulabel\n\nnot found"
    return
  }
  if ![string match *.annot $anlabel] {
    confirmalert "Suffix on outfile:\n\n    $currabbrev\n\nis not\n\n    .annot"
    return
  }

  # do write_mgh_annot chks here too (interface fail vs. hidden log file fail)
  set id [open $lulabel r]
  set lines [split [read -nonewline $id] "\n"] ;# nonewline: no last empty elem
  close $id
  set regids ""
  set missingnames ""
  set ignoreflag 0
  foreach line $lines {
    if [string match "### include_following" $line] {set ignoreflag 0; continue}
    if [string match "### exclude_following" $line] {set ignoreflag 1; continue}
    if {$ignoreflag} { continue }
    if [string match #* $line] { continue }
    if { [llength $line] == 6 } {
      set regid [lindex $line 0]
      set infix [lindex $line 1]
      set r [lindex $line 2]
      set g [lindex $line 3]
      set b [lindex $line 4]
      foreach id1 $regids {
        # fail if dup region id in LUT (tksurfer.c: read_mgh_colorlut)
        if { "$regid" == "$id1" } {
          confirmalert "Make MGH Annot: duplicate region idnum found:\
                    \n\n    $regid\
                    \n\nSecond occurrence was for region name:\
                    \n\n    $infix\
                    \n\n...quitting"
          return
        }
        foreach ind [array names col $id1,*] {  ;# array non-exist -> ret empty
          if [string match *,r $ind] { set r1 $col($ind) }
          if [string match *,g $ind] { set g1 $col($ind) }
          if [string match *,b $ind] { set b1 $col($ind) }
        }
        # fail if dup colors in LUT (tksurfer.c: read_mgh_colorlut)
        if { $r == $r1 && $g == $g1 && $b == $b1 } {
          confirmalert "Make MGH Annot: duplicate region color found:\
                    \n\n    $r1  $g1  $b1\
                    \n\nSecond occurrence was for region name:\
                    \n\n    $infix"
          return
        }
      }
      # save legal entries
      lappend regids $regid
      set col($regid,r) $r
      set col($regid,g) $g
      set col($regid,b) $b
      # chk label files corresponding to each LUT regin exist (write_mgh_annot)
      if {$infix != "Unknown" && $infix != "???" &&
         ![file exists $env(SUBJECTS_DIR)/$subject/label/$hemi-$infix.label]} {
        set missingnames "$missingnames\n    $hemi-$infix.label"
      }
    }
  }
  # list all missing files (tksurfer.c:write_mgh_annot ignores missing files)
  if {"$missingnames" != ""} {
    if ![okreplace "" "Make MGH Annot: following label files (req'd by LUT):\
                   \n    $missingnames\
                 \n\nnot found in label dir:\
                 \n\n    $env(SUBJECTS_DIR)/$subject/label" \
                     "Make Annot Without Those Files"] {
      return
    }
  }

  if [testreplace $anlabel write_mgh_annot] {
    confirmalert "Labels matching structures in:\
              \n\n    $lulabel\
              \n\nassembled into MGH annotation file:\
              \n\n    $anlabel\
              \n\nAnnotation displayed/rotated after OK\
                \n(current val,val2 swapped/saved to valbak,val2bak)\
                \n"
    swap_valval2_valbakval2bak    ;# save current overlay before clear
    logcmd "swap_valval2_valbakval2bak"
    clear_values
    logcmd "clear_values"
    ### override def MGH annot alpha=0=invisible with "tran" entry setting
    #set_annot_alpha $labelalpha
    #logcmd "set_annot_alpha $labelalpha"
    ### force opaque ignoring "tran" entry
    #set_annot_alpha 255
    #logcmd "set_annot_alpha 255"
    ### read_mgh_annot now forces opaque
    set labelflag 1
    logcmd "set labelflag 1"
    set overlayflag 1
    logcmd "set overlayflag 1"
    set i 0
    set step 5
    redraw
    while {$i < 360} {
      rotate_brain_y $step
      incr i $step
      redraw
    }
    redrawbutton

    # TODO: should have a way of undoing the havoc done here to color scale!
    if ![okreplace "" "Show overlap saved in .pval field? (OK to skip)" \
         "Skip" none "Show Overlap" ] {
      ### for testing: also show overlap
      confirmalert "Next: display per-vtx hitcount accumulated in .pval field:\
                \n\n    (1) swap_pval_val\
                  \n    (2) reset colscale/parms, flags\
                \n\nTo save, pick name, use \"W\" on \"val:\" line\
                \n\nHit count displayed/rotated on OK\
                  \n(2 hits on borders)"
      set pvalborddotflag 0
      logcmd "set pvalborddotflag 0"
      swap_pval_val
      logcmd "swap_pval_val"
      set overlayflag 1
      logcmd "set overlayflag 1"
      set statmaskampflag 0
      logcmd "set statmaskampflag 0"
      secondsquashents
      logcmd "secondsquashents"
      set colscale 6
      logcmd "set colscale 6"
      set fthresh 0.0
      logcmd "set fthresh 0.0"
      set fmid 0.0
      logcmd "set fmid 0.0"
      set fslope 0.8
      logcmd "set fslope 0.8"
      set labelflag 0
      logcmd "set labelflag 0"
      set complexvalflag 0
      logcmd "set complexvalflag 0"
      set revphaseflag 0
      logcmd "set revphaseflag 0"
      set invphaseflag 0
      logcmd "set invphaseflag 0"
      set truncphaseflag 0
      logcmd "set truncphaseflag 0"
      set i 0
      set step 5
      redraw
      while {$i <= 360} {
        rotate_brain_y $step
        incr i $step
        redraw
      }
    } else {
      swap_valval2_valbakval2bak    ;# restore overlay
    }
    redrawbutton
  }
}

proc gettseries { type } {  ;# "T": subj label/annot -> sess raw/uniq files
  global isession scandir hemi label labelabbrev regdat rawdata
  global brainregioncnt meshr meshg meshb anlabel anlabelabbrev
  global nativerealloadedflag nativeimagloadedflag pcntsigpk2pk complexvalflag

  if [divider [.files.label.cbx subwidget entry get]] { return }
  if {$type != "label" && $type != "rgb" && $type != "all" && $type != "amp"} {
    confirmalert "gettseries: bad type: $type"
    return
  }
  if ![file exists $regdat] {
    confirmalert "Write Label Timecourses:  regdat:\n\n   $regdat\n\nnot found"
    return
  }
  if ![file exists $rawdata] {
   confirmalert "Write Label Timecourses:  rawdata:\n\n   $rawdata\n\nnot found"
    return
  }
  if [searchlimitsBAD] { return }
  if [uniqsampBAD] { return }

  if {$type == "label"} {
    setfile label [.files.label.cbx subwidget entry get]
    if [string match *.annot $label] {
      confirmalert "Write Label Timecourses:  suffix is \".annot\":\
                    \n\nTo extract raw timecourse(s) from MGH annotation:\
                    \n\n    (1) load an annotation with \"D\" button\
                      \n    (2) click region to pick color (near \"MESH\")\
                      \n    (3) middle-click-\"T\"\
                      \n           => out file has brain region infix\
                    \n\nor:\
                    \n\n    (1) shift-middle-click-\"T\"\
                      \n           => get timecourses all brain regions (big!)"
      return
    }
    if ![string match *.label $label] {
      confirmalert "Write Label Timecourses:  label:\
                    \n\n   $label\n\nsuffix is not \".label\""
      return
    }
    if ![file exists $label] {
      confirmalert "Write Label Timecourses:  label:\n\n   $label\n\nnot found"
      return
    } 
    # cp infix/outfile str proc from tksurfer.c write_label_timecourses_stats
    set infix [file rootname [file tail $label]]
    if { [string match rh-* $infix] || [string match lh-* $infix] || \
         [string match rh.* $infix] || [string match lh.* $infix] } {
      set infix [string range $infix 3 end]
    }
    set file1 $isession/$scandir/$hemi.$infix.raw
    set file2 $isession/$scandir/$hemi.$infix.xyz
    set file3 $isession/$scandir/$hemi.$infix.avg
    if [testreplace $file1 write_label_timecourses_stats 0] {;#0=t,1=stat,2=t+s
      confirmalert " raw timecourses, uniq indices, avg timecourse for:\n\n\
                     $label\n\nwritten to:\n\n$file1\n\n$file2\n\n$file3"
    }
  }

  if {$type == "rgb"} {
    setfile anlabel [.files.label.cbx subwidget entry get]
    if {!$brainregioncnt} {
      confirmalert "Write Annot Timecourses: no MGH .annot loaded"
      return
    }
    if {$meshr == 120 && $meshg == 120 && $meshb == 255} {
      if ![okreplace "" \
           "Write Annot Timecourses:\
             \n\n    rgb = ($meshr, $meshg, $meshb)\
             \n\nis still set to default\
             \n\nTo load color, Cancel, click region, try again\
             \n(N.B. default color probably won't match any region)" \
           "Use Default Annotation Color"] {
        confirmalert "Previous annotation extracts (if any) not touched"
        return
      }
    }
    # region name not exported to tcl, just give general pattern
    set file1 $isession/$scandir/$hemi.region_<name>.raw
    set file2 $isession/$scandir/$hemi.region_<name>.xyz
    set file3 $isession/$scandir/$hemi.region_<name>.avg
    if ![okreplace "" \
         "Write Annot Timecourses, uniq indices, avg timecourse for color:\
           \n\n    rgb = ($meshr, $meshg, $meshb)\
           \n\nfrom annotatation file:\
           \n\n    $anlabel\
           \n\nto files like these?\
           \n\n    $file1\n    $file2\n    $file3" \
         "Dump Timecourses"] {
      confirmalert "Previous annotation extracts (if any) not touched"
      return
    } else {write_annotcol_timecourses_stats $meshr $meshg $meshb 0};#0t,1s,2st
  }

  if {$type == "all"} {
    setfile anlabel [.files.label.cbx subwidget entry get]
    if {!$brainregioncnt} {
      confirmalert "Write Annot Timecourses: no MGH .annot loaded"
      return
    }  
    set file1 $isession/$scandir/$hemi.region_<name>.raw
    set file2 $isession/$scandir/$hemi.region_<name>.xyz
    set file3 $isession/$scandir/$hemi.region_<name>.avg
    if ![okreplace "" \
         "Write Annot Timecourses and uniq indices for all\
           \ncolors/regions in annotation file:\
           \n\n    $anlabel\
           \n\nto file like these?\
           \n\n    $file1\n    $file2\n    $file3" \
         "Dump Timecourses"] {
      confirmalert "Previous annotation extracts (if any) not touched"
      return
    } else { write_annotcols_timecourses_stats 0 } ;#0=t,1=s,2=t+s
  }

  if {$type == "amp"} {
    setfile label [.files.label.cbx subwidget entry get]
    if [string match *.annot $label] {
      confirmalert "Calc Response Amp from Fourier:\
                    \n\ndoesn't yet work with MGH annotation"
      return
    }
    if ![string match *.label $label] {
      confirmalert "Calc Response Amp from Fourier:  label:\
                    \n\n   $label\n\nsuffix is not \".label\""
      return
    }
    if ![file exists $label] {
      confirmalert \
        "Calc Response Amp from Fourier:  label:\n\n   $label\n\nnot found"
      return
    } 
    if {!$complexvalflag} {
      confirmalert "Calc Response Amp from Fourier:\n\nrequires complex data"
      return
    }
    if {!$nativerealloadedflag || !$nativeimagloadedflag} { 
      confirmalert "Calc Response Amp from Fourier:\
                    \n\n    ==>  no complex 3D stats loaded  <==\
                    \n\n(1) HOWTO interactive:\
                    \n\n    click \"val:\" to get \"val3d:\" label\
                      \n    select _x or _y BRIK in \"val3d:\" dropdown\
                      \n    click \"R\" button (auto-reads complex)\
                    \n\n(2) HOWTO tksurfer cmdline options:\
                    \n\n    -real3d <stem>+orig_x.BRIK\
                      \n    -imag3d <stem>+orig_y.BRIK\
                    \n\n(3) HOWTO tcl script:\
                    \n\n    set statpatt <stem>+orig_x.BRIK\
                      \n    read_native_stat 0\
                      \n    set statpatt <stem>+orig_y.BRIK\
                      \n    read_native_stat 1"
      return
    }
    confirmalert "Calc Response Amp from Fourier:\
              \n\nN.B.: amp only valid for 3D raw fourier (_x,_y) files!"
    # cp infix/outfile str proc from tksurfer.c write_label_timecourses_stats
    set infix [file rootname [file tail $label]]
    if { [string match rh-* $infix] || [string match lh-* $infix] || \
         [string match rh.* $infix] || [string match lh.* $infix] } {
      set infix [string range $infix 3 end]
    }
    set file1 $isession/$scandir/$hemi.$infix.raw
    set file2 $isession/$scandir/$hemi.$infix.xyz
    set file3 $isession/$scandir/$hemi.$infix.avg
    if [testreplace $file1 write_label_timecourses_stats 4] { ;# amp from FFT
      confirmalert " raw timecourses, uniq indices, avg timecourse for:\n\n\
                     $label\n\nwritten to:\n\n$file1\n\n$file2\n\n$file3"
    }
    confirmalert \
      "Avg peak-to-peak stimfreq amp from FFT: [format "%2.2f" $pcntsigpk2pk]%"
  }
}

proc getstat { type } {
  global isession scandir hemi label labelabbrev regdat rawdata complexvalflag
  global nativerealloadedflag nativeimagloadedflag nativemaskloadedflag
  global brainregioncnt meshr meshg meshb anlabel anlabelabbrev

  if [divider [.files.label.cbx subwidget entry get]] { return }
  if {$type != "label" && $type != "rgb" && $type != "all"} {
    confirmalert "getstat: bad type: $type"
    return
  }
  if [divider

  if ![file exists $regdat] {
    confirmalert "Write Label Stats:  regdat:\n\n   $regdat\n\nnot found"
    return
  }
  if {!$nativerealloadedflag} { 
    confirmalert "Write Label Stats:\
                  \n\n    no 3D vol stats loaded\
                  \n\n\n(1) click \"val:\" to get \"val3d:\" label\
                  \n(2) use the \"R\" button on \"val3d:\" line\
                  \n\nor opt:  -real3d\
                  \nor tcl:   set statpatt <brik/bfloat>; read_native_stat 0"
    return
  }
  if {$complexvalflag && !$nativeimagloadedflag} {
    confirmalert "Write Label Stats:\
                  \n\n    no 3D vol stats (imag. comp.) loaded\
                  \n\n\n(1) click \"val:\" to get \"val3d:\" label\
                  \n(2) use the \"R\" button on \"val3d:\" line\
                  \n\nor opt:  -imag3d\
                  \nor tcl:   set statpatt <brik/bfloat>; read_native_stat 1"
    return

  }
  if [searchlimitsBAD] { return }
  if [uniqsampBAD] { return }

  if {$type == "label"} {
    setfile label [.files.label.cbx subwidget entry get]
    if [string match *.annot $label] {
      confirmalert "Write Label Stats:  suffix is \".annot\":\
                    \n\nTo extract raw stats-only from MGH annotation:\
                    \n\n    (1) load an annotation with \"D\" button\
                      \n    (2) click region to pick color (near \"MESH\")\
                      \n    (3) ctrl-middle-click-\"S\"\
                      \n           => out file has brain region infix\
                    \n\nor:\
                    \n\n    (1) shift-ctrl-middle-click-\"S\"\
                      \n           => get stats-only all brain regions"
      return
    }


    if ![file exists $label] {
      confirmalert "Write Label Stats:  label:\n\n   $label\n\nnot found"
      return
    } 
    # copy infix/outfile str proc from tksurfer.c write_label_timecourses_stats
    set infix [file rootname [file tail $label]]
    if { [string match rh-* $infix] || [string match lh-* $infix] || \
         [string match rh.* $infix] || [string match lh.* $infix] } {
      set infix [string range $infix 3 end]
    }
    set file1 $isession/$scandir/$hemi.$infix.stat
    set file2 $isession/$scandir/$hemi.$infix.xyz
    if [testreplace $file1 write_label_timecourses_stats 1] { ;#0=t,1=s,2=t+s
      confirmalert " stat and uniq indices for:\n\n\
                     $label\n\nwritten to:\n\n   $file1\n\n   $file2"
    }
  }

  if {$type == "rgb"} {
    setfile anlabel [.files.label.cbx subwidget entry get]
    if {!$brainregioncnt} {
      confirmalert "Write Annot Stats: no MGH .annot loaded"
      return
    }
    if {$meshr == 120 && $meshg == 120 && $meshb == 255} {
      if ![okreplace "" \
           "Write Annot Stats:\
             \n\n    rgb = ($meshr, $meshg, $meshb)\
             \n\nis still set to default\
             \n\nTo load color, Cancel, click region, try again\
             \n(N.B. default color probably won't match any region)" \
           "Use Default Annotation Color"] {
        confirmalert "Previous annotation extracts (if any) not touched"
        return
      }
    }
    # region name not exported to tcl, just give general pattern
    set file1 $isession/$scandir/$hemi.region_<name>.stat
    set file2 $isession/$scandir/$hemi.region_<name>.xyz
    if ![okreplace "" \
         "Write Annot Stats-only, uniq indices for color:\
           \n\n    rgb = ($meshr, $meshg, $meshb)\
           \n\nfrom annotatation file:\
           \n\n    $anlabel\
           \n\nto files like these?\
           \n\n    $file1\n    $file2" \
         "Dump Stats"] {
      confirmalert "Previous annotation extracts (if any) not touched"
      return
    } else {write_annotcol_timecourses_stats $meshr $meshg $meshb 1};#0t,1s,2st
  }

  if {$type == "all"} {
    setfile anlabel [.files.label.cbx subwidget entry get]
    if {!$brainregioncnt} {
      confirmalert "Write Annot Stats: no MGH .annot loaded"
      return
    }
    set file1 $isession/$scandir/$hemi.region_<name>.stat
    set file2 $isession/$scandir/$hemi.region_<name>.xyz
    if ![okreplace "" \
         "Write Annot Stats-only, uniq indices for all\
           \ncolors/regions in annotation file:\
           \n\n    $anlabel\
           \n\nto file like these?\
           \n\n    $file1\n    $file2" \
         "Dump Stats"] {
      confirmalert "Previous annotation extracts (if any) not touched"
      return
    } else { write_annotcols_timecourses_stats 1 } ;#0=t,1=s,2=t+s
  }
}

proc getstattseries { type } {  ;# "S" button (same as "T" but incl stats)
  global isession scandir hemi labelabbrev label regdat rawdata complexvalflag
  global nativerealloadedflag nativeimagloadedflag nativemaskloadedflag
  global brainregioncnt meshr meshg meshb anlabel anlabelabbrev

  if [divider [.files.label.cbx subwidget entry get]] { return }
  if {$type != "label" && $type != "rgb" && $type != "all"} {
    confirmalert "getstattseries: bad type: $type"
    return
  }
  if ![file exists $regdat] {
    confirmalert \
      "Write Label Stats+Timecourses:  regdat:\n\n   $regdat\n\nnot found"
    return
  }
  if {!$nativerealloadedflag} { 
    confirmalert "Write Label/Annot Stats+Timecourses:\
                  \n\n    no 3D vol stats loaded\
                  \n\n\n(1) click \"val:\" to get \"val3d:\" label\
                  \n(2) use the \"R\" button on \"val3d:\" line\
                  \n\nor opt:  -real3d\
                  \nor tcl:   set statpatt <brik/bfloat>; read_native_stat 0"
    return
  }
  if {$complexvalflag && !$nativeimagloadedflag} {
    confirmalert "Write Label/Annot Stats+Timecourses:\
                  \n\n    no 3D vol stats (imag. comp.) loaded\
                  \n\n\n(1) click \"val:\" to get \"val3d:\" label\
                  \n(2) use the \"R\" button on \"val3d:\" line\
                  \n\nor opt:  -imag3d\
                  \nor tcl:   set statpatt <brik/bfloat>; read_native_stat 1"
    return

  }
  if ![file exists $rawdata] {
    confirmalert \
      "Write Label Stats+Timecourses:  rawdata:\n\n   $rawdata\n\nnot found"
    return
  }
  if [searchlimitsBAD] { return }
  if [uniqsampBAD] { return }

  if {$type == "label"} {
    setfile label [.files.label.cbx subwidget entry get]
    if [string match *.annot $label] {
      confirmalert "Write Label Stats+Timecourses:  suffix is \".annot\":\
                    \n\nTo extract raw timecourse(s) from MGH annotation:\
                    \n\n    (1) load an annotation with \"D\" button\
                      \n    (2) click region to pick color (near \"MESH\")\
                      \n    (3) middle-click-\"S\"\
                      \n           => out file has brain region infix\
                    \n\nor:\
                    \n\n    (1) shift-middle-click-\"S\"\
                      \n           => get stat+time all brain regions (big!)"
      return
    }
    if ![string match *.label $label] {
      confirmalert "Write Label Stats+Timecourses:  label:\
                    \n\n   $label\n\nsuffix is not \".label\""
      return
    }
    if ![file exists $label] {
      confirmalert \
        "Write Label Stats+Timecourses:  label:\n\n   $label\n\nnot found"
      return
    } 
    # copy infix/outfile str proc from tksurfer.c write_label_timecourses_stats
    set infix [file rootname [file tail $label]]
    if { [string match rh-* $infix] || [string match lh-* $infix] || \
         [string match rh.* $infix] || [string match lh.* $infix] } {
      set infix [string range $infix 3 end]
    }
    set file1 $isession/$scandir/$hemi.$infix.stat,raw
    set file2 $isession/$scandir/$hemi.$infix.xyz
    set file3 $isession/$scandir/$hemi.$infix.avg
    if [testreplace $file1 write_label_timecourses_stats 2] { ;#0=t,1=s,2=both
      confirmalert " stat+rawtimecourses, uniq indices, avg timecourse for:\n\n\
      confirmalert " stat + raw timecourses and uniq indices for:\n\n\
                     $label\n\nwritten to:\n\n$file1\n\n$file2\n\n$file3"
    }
  }

  if {$type == "rgb"} {
    setfile anlabel [.files.label.cbx subwidget entry get]
    if {!$brainregioncnt} {
      confirmalert "Write Annot Stats+Timecourses: no MGH .annot loaded"
      return
    } 
    if {$meshr == 120 && $meshg == 120 && $meshb == 255} {
      if ![okreplace "" \
           "Write Annot Stats+Timecourses:\
             \n\n    rgb = ($meshr, $meshg, $meshb)\
             \n\nis still set to default\
             \n\nTo load color, Cancel, click region, try again\
             \n(N.B. default color probably won't match any region)" \
           "Use Default Annotation Color"] {
        confirmalert "Previous annotation extracts (if any) not touched"
        return
      }
    }
    # region name not exported to tcl, just give general pattern
    set file1 $isession/$scandir/$hemi.region_<name>.stat,raw
    set file2 $isession/$scandir/$hemi.region_<name>.xyz
    set file3 $isession/$scandir/$hemi.region_<name>.avg
    if ![okreplace "" \
          "Write Annot Stats+Timecourses, uniq indices, avg tcourse for color:\
           \n\n    rgb = ($meshr, $meshg, $meshb)\
           \n\nfrom annotatation file:\
           \n\n    $anlabel\
           \n\nto files like these?\
           \n\n    $file1\n    $file2\n    $file3" \
         "Dump Stats+Timecourses"] {
      confirmalert "Previous annotation extracts (if any) not touched"
      return
    } else {write_annotcol_timecourses_stats $meshr $meshg $meshb 2};#0t,1s,2st
  }

  if {$type == "all"} {
    setfile anlabel [.files.label.cbx subwidget entry get]
    if {!$brainregioncnt} {
      confirmalert "Write Annot Stats+Timecourses: no MGH .annot loaded"
      return
    } 
    set file1 $isession/$scandir/$hemi.region_<name>.stat,raw
    set file2 $isession/$scandir/$hemi.region_<name>.xyz
    set file3 $isession/$scandir/$hemi.region_<name>.avg
    if ![okreplace "" \
         "Write Annot Stats+Timecourses, uniq indices, avg timecourse for all\
           \ncolors/regions in annotation file:\
           \n\n    $anlabel\
           \n\nto file like these?\
           \n\n    $file1\n    $file2\n    $file3" \
         "Dump Stats+Timecourses"] {
      confirmalert "Previous annotation extracts (if any) not touched"
      return
    } else { write_annotcols_timecourses_stats 2 } ;#0=t,1=s,2=t+s
  }
}

proc corrctrls { type } {  ;# left/mid-clk X button on "label:" line wrapper
  global fillneartype num,sqmm,mm cmptype val xcorr_outstem
  global xcorrcovarflag searchlightuniqflag numafteruniqflag r2zscoreflag
  global corrctrlswin

  if {$type != "label" && $type != "rgb"} {
    confirmalert "corrctrls: bad type: $type"
    return
  }
  if [winfo exists $corrctrlswin] { raise $corrctrlswin; return }
  set title "SEARCHLIGHT CORRELATION"
  if {$type == "label"} {
    set title "$title\n(over current \"label:\")"
  }
  if {$type == "rgb"} {
    set title "$title\n(over MGH annot region\npicked by MESH r,g,b)" 
  }
  set title "$title\
             \n\nFill nearest (fillneartype):\
               \n 0:  num vertices\
               \n 1:  area (mm^2)\
               \n2:  radius (mm)\
             \n\nCompare type (cmptype):\
               \n0:  Real,Real (Corr)\
               \n1:  Amp,Real (Corr)\
               \n2:  Real,Amp (Corr)\
               \n3:  Amp,Amp (Corr)\
               \n  4:  Ang,Ang (CircCorr)"
  set variablelist "whitespace \
                    xcorr_outstem fillneartype num,sqmm,mm cmptype \
                    whitespace \
                    r2zscoreflag \
                    xcorrcovarflag \
                    searchlightuniqflag \
                    numafteruniqflag \
                    whitespace"
  set corrctrlswin [controls $title $variablelist "READY" "do_corr $type" 11]
  bind $corrctrlswin <ButtonRelease-3> { helpwin label_corr }
}

proc do_corr { type } {
  global num,sqmm,mm fillneartype cmptype label labelabbrev brainregioncnt
  global valloadedflag val2loadedflag valbakloadedflag val2bakloadedflag
  global meshr meshg meshb labelflag fillnearname critname cmpname
  global complexvalflag colscale fthresh fmid fslope searchlightvtxcnt
  global revphaseflag invphaseflag truncphaseflag statmaskampflag
  global xcorrcovarflag searchlightuniqflag numafteruniqflag r2zscoreflag
  global val valabbrev xcorr_outstem hemi uniqvoxcntloadedflag corrctrlswin
  global anlabel anlabelabbrev pvalborddotflag

  if {$type != "label" && $type != "rgb"} {
    confirmalert "do_corr: bad type: $type"
    if [winfo exists $corrctrlswin] { destroy $corrctrlswin }
    set corrctrlswin ""
    return
  }

  ### check popup parms
  if {$fillneartype < 0 || $fillneartype > 2} {
    confirmalert \
            "bad fillneartype:  $fillneartype\n(valid \$fillneartype's: 0-2)\
                  \n\n    0 = n nearest vertices\
                    \n    1 = nearest vertices until area reached\
                    \n    2 = nearest until radius reached"
    return
  }
  if {$cmptype < 0 || $cmptype > 4} {
    confirmalert "bad correlation cmptype:  $cmptype\n(valid \$cmptype's: 0-4)\
                  \n\n    0 = real/real\
                    \n    1 = complex-amp/real\
                    \n    2 = real/complex-amp\
                    \n    3 = complex-amp/complex-amp\
                    \n    4 = complex-phase/complex=phase"
    return
  }
  if {$cmptype == 0} {  ;# real/real
    if {!$valloadedflag || !$valbakloadedflag} {
      confirmalert "Searchlight Correlation:\
                    \n(\$cmptype=$cmptype: real/real)\
                    \n\nfirst load 2 data sets:\n\n    val\n    valbak"
      return
    }
  }
  if {$cmptype == 1} {  ;# amp/real
    if {!$valloadedflag || !$val2loadedflag || !$valbakloadedflag} {
      confirmalert "Searchlight Correlation:\
                    \n(\$cmptype=$cmptype: complexamp/real)\
                    \n\nfirst load 2 data sets:\n\n    val,val2\n    valbak"
      return
    }
  }
  if {$cmptype == 2} {  ;# real/amp
    if {!$valloadedflag || !$valbakloadedflag || !$val2bakloadedflag} {
      confirmalert "Searchlight Correlation:\
                    \n(\$cmptype=$cmptype: real/complexamp):\
                    \n\nfirst load 2 data sets:\n\n    val\n    valbak,val2bak"
      return
    }
  }
  if {$cmptype == 3} {  ;# complex/complex, amp
    if {!$valloadedflag || !$valbakloadedflag || \
        !$valbakloadedflag || !$val2bakloadedflag} {
      confirmalert "Searchlight Correlation:\
                    \n(\$cmptype=$cmptype: complex/complex, amplitude):\
              \n\nfirst load 2 data sets:\n\n    val,val2\n    valbak,val2bak"
      return
    }
  }
  if {$cmptype == 4} {  ;# complex/complex, phase
    if {!$valloadedflag || !$valbakloadedflag || \
        !$valbakloadedflag || !$val2bakloadedflag} {
      confirmalert "Searchlight Correlation:\
                    \n(\$cmptype=$cmptype: complex/complex, phase):\
              \n\nfirst load 2 data sets:\n\n    val,val2\n    valbak,val2bak"
      return
    }
  }
  if {$searchlightuniqflag && !$uniqvoxcntloadedflag} {
    confirmalert "Searchlight Correlation:\
              \n\n    searchlightuniqflag requires first identifying\
                \n    \'representative\' unique voxel vertices\
              \n\nFirst run read_uniq_vertices:\
              \n\n    (1) select $hemi-UniqSampVtxs.label from dropdown\
                \n    (2) ctrl-left-click \"R\" on \"label:\" line\
              \n\nOr manually re-run find_uniq_vertices:\
              \n\n    (1) click \"val:\" to get \"val3d:\"\
                \n    (2) select 3D stats BRIK from dropdown\
                \n    (3) click  \"R\"\
                \n    (4) click  \"PA\"\
                \n    (5) click \"UQ\""
    return
  }
  if {$xcorrcovarflag && $r2zscoreflag} {
    confirmalert "Searchlight Correlation:\
              \n\n    Convert r -> z-score incompatible w/covariance output\
              \n\nUntick one of following, and try again:\
              \n\n    r2zscoreflag\
                \n    xcorrcovarflag"
    return
  }

  ### ask output file overwrite before maybe long run
  if {$r2zscoreflag} { set infix "_z" } else { set infix "_s" }
  set xcorr_outfile [file dirname $val]/${xcorr_outstem}${infix}-$hemi.w
  set writeflag 1
  if [file exists $xcorr_outfile] {
    if ![okreplace "" \
           "Write XCorr: outfile exists:\
        \n\n    $xcorr_outfile\
        \n\nOK to overwrite when xcorr calc finishes?\
        \n\n(if Cancel, can still write manually at end)" "Overwrite"] {
      set writeflag 0
    }
  }

  ### report (N.B.: xcorrcovarflag + r2zscoreflag blocked above)
  if {$xcorrcovarflag} { set rtype covariance } else { set rtype correlation }
  if {$cmptype == 4}   { set kind circular    } else { set kind linear       }
  if {$r2zscoreflag}   { set units z-score    } else { set units r           }
  set resulttype "$kind $rtype -- $units"

  ### do for label
  if {$type == "label"} {
    setfile label [.files.label.cbx subwidget entry get]
    if [string match *.annot $label] {
      confirmalert "Searchlight Correlation:  suffix is \".annot\":\
                    \n\nTo use MGH annotation region:\
                    \n\n    (1) load an annotation with \"D\" button\
                      \n    (2) click region to pick color (near \"MESH\")"
      return
    }
    if ![string match *.label $label] {
      confirmalert "Searchlight Correlation:  label:\
                    \n\n   $label\n\nsuffix is not \".label\""
      return
    }
    if ![file exists $label] {
      confirmalert "Searchlight Correlation:  label:\n\n   $label\n\nnot found"
      return
    }
    if ![okreplace "" \
         "Searchlight Correlation for vertices in label:\
           \n\n    $label\
           \n\nusing parameters:\
           \n\n    fillneartype = $fillneartype  ($fillnearname($fillneartype))\
             \n    criterion = ${num,sqmm,mm}  ($critname($fillneartype))\
             \n    cmptype = $cmptype  ($cmpname($cmptype))\
           \n\nResult ($resulttype) to .stat field\
             \nPos power of 10 p-val of correlation to .pval field" \
         "Searchlight Correlation"] {
      return
    } else {
      set pvalborddotflag 0
      logcmd "set pvalborddotflag 0"
      read_label_to_annot_using_col $meshr $meshg $meshb
      logcmd "read_label_to_annot_using_col $meshr $meshg $meshb"
      set labelflag 1
      logcmd "set labelflag 1"
      redrawbutton
      corr_over_label $fillneartype ${num,sqmm,mm} $cmptype
      logcmd "corr_over_label $fillneartype ${num,sqmm,mm} $cmptype"
      confirmalert "Searchlight Correlation for label:\
                    \n\n    $label\
                      \n    avg searchlight vtx cnt = $searchlightvtxcnt\
                    \n\nDone.  Click OK to see result:\
                    \n\n    1. swap corr (.stat) to surf (make visible)\
                      \n    2. reset colcale reset to BR (real-valued)\
                      \n    3. set: fthresh=0.0, fmid=0.6, fslope=2.0)\
                    \n\n    N.B.: stat/val swap means log will report\
                      \n    stat as \'val\' when clicking on a vertex"
    }
  }

  ### do for MGH annot rgb
  if {$type == "rgb"} {
    setfile anlabel [.files.label.cbx subwidget entry get]
    if {!$brainregioncnt} {
      confirmalert "Searchlight Correlation Using Annotation:\
                    \n\nno MGH .annot loaded"
      return
    }
    if {$meshr == 120 && $meshg == 120 && $meshb == 255} {
      if ![okreplace "" \
           "Searchlight Correlation Using Annotation:\
             \n\n    rgb = ($meshr, $meshg, $meshb)\
             \n\nis still set to default\
             \n\nTo load color, Cancel, click region, try again\
             \n(N.B. default color probably won't match any region)" \
           "Use Default Annotation Color"] {
        return
      }
    }
    if ![okreplace "" \
         "Searchlight Correlation for vertices with color:\
           \n\n    rgb = ($meshr, $meshg, $meshb)\
           \n\nusing parameters:\
           \n\n    fillneartype = $fillneartype  ($fillnearname($fillneartype))\
             \n    criterion = ${num,sqmm,mm}  ($critname($fillneartype))\
             \n    cmptype = $cmptype  ($cmpname($cmptype))\
           \n\nResult ($resulttype) to .stat field\
             \nPos power of 10 p-val of correlation to .pval field" \
         "Searchight Correlation"] {
      return
    } else {
      set pvalborddotflag 0
      logcmd "set pvalborddotflag 0"
      corr_over_annotcol \
        $fillneartype ${num,sqmm,mm} $cmptype $meshr $meshg $meshb
      logcmd "corr_over_label \
        $fillneartype ${num,sqmm,mm} $cmptype $meshr $meshg $meshb"
      confirmalert "Searchlight Correlation for annot col:\
                    \n\n    rgb = ($meshg, $meshg, $meshb)\
                      \n    searchlightvtxcnt=$searchlightvtxcnt\
                    \n\nDone.  Click OK to see result:\
                    \n\n    1. swap $resulttype (.stat) to surf (make visible)\
                      \n    2. reset colcale reset to BR (real-valued)\
                      \n    3. set: fthresh=0.0, fmid=0.6, fslope=2.0\
                    \n\n    N.B.: stat/val swap means log will report\
                      \n    stat as \'val\' when clicking on a vertex"
    }
  }

  ### show final corr (swap, clear label, fix colscale, fix parms, redraw)
  clear_annot
  logcmd "clear_annot"
  swap_stat_val
  logcmd "swap_stat_val"
  set complexvalflag 0
  logcmd "set complexvalflag 0"
  set revphaseflag 0
  logcmd "set revphaseflag 0"
  set invphaseflag 0
  logcmd "set invphaseflag 0"
  set truncphaseflag 0
  logcmd "set truncphaseflag 0"
  set colscale 6
  logcmd "set colscale 6"
  set fthresh 0.0
  logcmd "set fthresh 0.0"
  set fmid 0.6
  logcmd "set fmid 0.6"
  set fslope 2.0
  logcmd "set fslope 2.0"
  set statmaskampflag 0
  logcmd "set statmaskampflag 0"
  secondsquashents
  logcmd "secondsquashents"
  redrawbutton

  ### autowrite xcorr to _s (permission above)
  setfile val $xcorr_outfile  ;# always setup "val:" entry for manual write
  if {$writeflag} { write_binary_values }

  ## leave window up for redo
  #if [winfo exists $corrctrlswin] { destroy $corrctrlswin }
  #set corrctrlswin ""
}

proc sampclustctrls { } {  ;# popup from left-click bold "label:" label
  global sampclustctrlswin

  if [winfo exists $sampclustctrlswin] {
    raise $sampclustctrlswin
    return $sampclustctrlswin
  }
  set sampclustctrlswin \
      [controls "NormSamp (paint/label)\nand ClusterFilter Controls" { \
    normdsampsearchflag \
    normdfracflag \
    whitespace \
    normdsampuniqvoxflag \
    normdsampuniqvtxflag \
    normdsampallflag \
    whitespace \
    samevtxthickflag \
    bokflag \
    wmgmext \
    normdmax \
    normdsamp \
    whitespace \
    normdfracmax \
    normdfracsamp \
    whitespace \
    normddstep \
    normdop \
    whitespace \
    preclustfthr \
    clustarea \
    whitespace \
    sulfrac \
    gyrfrac \
  } none none]
  # tickboxes help (TODO: fix controls to embed check var)
  bind $sampclustctrlswin.ck0 <ButtonRelease-3> { helpwin nsamp_search }
  bind $sampclustctrlswin.ck1 <ButtonRelease-3> { helpwin nsamp_dfrac }
  bind $sampclustctrlswin.ck2 <ButtonRelease-3> { helpwin nsamp_uniqvox }
  bind $sampclustctrlswin.ck3 <ButtonRelease-3> { helpwin nsamp_uniqvtx }
  bind $sampclustctrlswin.ck4 <ButtonRelease-3> { helpwin nsamp_all }
  bind $sampclustctrlswin.ck5 <ButtonRelease-3> { helpwin nsamp_samevtx }
  bind $sampclustctrlswin.ck6 <ButtonRelease-3> { helpwin nsamp_bok }
  # entry labels help
  bind $sampclustctrlswin.wmgmext.la <ButtonRelease-3> { helpwin nsamp_wmgmext }
  bind $sampclustctrlswin.normdsamp.la <ButtonRelease-3> { helpwin nsamp_min }
  bind $sampclustctrlswin.normdmax.la <ButtonRelease-3> { helpwin nsamp_max }
  bind \
   $sampclustctrlswin.normdfracsamp.la <ButtonRelease-3> {helpwin nsamp_fracmin}
  bind \
   $sampclustctrlswin.normdfracmax.la <ButtonRelease-3> {helpwin nsamp_fracmax}
  bind $sampclustctrlswin.normddstep.la <ButtonRelease-3> { helpwin nsamp_step }
  bind $sampclustctrlswin.normdop.la <ButtonRelease-3> { helpwin nsamp_op }
  bind $sampclustctrlswin.preclustfthr.la <ButtonRelease-3> { helpwin nsamp_pre}
  bind $sampclustctrlswin.clustarea.la <ButtonRelease-3> { helpwin nsamp_area }
  bind $sampclustctrlswin.sulfrac.la <ButtonRelease-3> { helpwin nsamp_sul }
  bind $sampclustctrlswin.gyrfrac.la <ButtonRelease-3> { helpwin nsamp_gyr }
  # entries themselves help
  bind $sampclustctrlswin.wmgmext.e <ButtonRelease-3> { helpwin nsamp_wmgmext }
  bind $sampclustctrlswin.normdsamp.e <ButtonRelease-3> { helpwin nsamp_min }
  bind $sampclustctrlswin.normdmax.e <ButtonRelease-3> { helpwin nsamp_max }
  bind \
    $sampclustctrlswin.normdfracsamp.e <ButtonRelease-3> {helpwin nsamp_fracmin}
  bind \
    $sampclustctrlswin.normdfracmax.e <ButtonRelease-3> {helpwin nsamp_fracmax}
  bind $sampclustctrlswin.normddstep.e <ButtonRelease-3> { helpwin nsamp_step }
  bind $sampclustctrlswin.normdop.e <ButtonRelease-3> { helpwin nsamp_op }
  bind $sampclustctrlswin.preclustfthr.e <ButtonRelease-3> { helpwin nsamp_pre }
  bind $sampclustctrlswin.clustarea.e <ButtonRelease-3> { helpwin nsamp_area }
  bind $sampclustctrlswin.sulfrac.e <ButtonRelease-3> { helpwin nsamp_sul }
  bind $sampclustctrlswin.gyrfrac.e <ButtonRelease-3> { helpwin nsamp_gyr }
  # for repositioning popup
  return $sampclustctrlswin
}

# begin "fs:" line GR (gradient) no-arg button procs
############################################################################
proc fsGR_2d_curv { } {
  comp_disp_grad curv
}

proc fsGR_2d_val { } {
  comp_disp_grad val 
}

proc fsGR_2d_phase { } {
  comp_disp_grad phase
}

proc fsGR_surf_curv { } {
  comp_disp_grad curv3d
}

proc fsGR_surf_val { } {
  comp_disp_grad val3d
}

proc fsGR_surf_phase { } {
  comp_disp_grad phase3d
}

# next 6 skip hotkey combos
proc fsGR_2d_avgcurv { } {
  comp_disp_grad avgcurv
}

proc fsGR_2d_avgval { } {
  comp_disp_grad avgval
}

proc fsGR_2d_avgphase { } {
  comp_disp_grad avgphase
}

proc fsGR_surf_avgcurv { } {
  comp_disp_grad avgcurv3d
}

proc fsGR_surf_avgval { } {
  comp_disp_grad avgval3d
}

proc fsGR_surf_avgphase { } {
  comp_disp_grad avgphase3d
}

proc fsGR_findrev { } {
  findgradrevctrls
}

#laplacian
proc fsGR_laplace_curv { } {
  comp_disp_laplace curv
}

proc fsGR_laplace_val { } {
  comp_disp_laplace val
}

proc fsGR_laplace_phase { } {
  comp_disp_laplace phase 
}

############################################################################
# end "fs:" line no-arg button procs

proc comp_disp_grad { type } {
  global flag2d gradvecbakflag gradvecbak3dflag valbaks_cart2polarflag
  global arrowscale valloadedflag val2loadedflag annotloadedflag
  global reggradvecbakflag reggradvecbak3dflag sdoutlierfact

  puts "tksurfer.tcl: comp_disp_grad $type"
  # bad arg
  if {$type != "curv"      && $type != "val"      && $type != "phase" &&
      $type != "curv3d"    && $type != "val3d"    && $type != "phase3d" &&
      $type != "avgcurv"   && $type != "avgval"   && $type != "avgphase" &&
      $type != "avgcurv3d" && $type != "avgval3d" && $type != "avgphase3d"} {
    confirmalert "Compute gradient: bad type:\
              \n\n  $type\
              \n\nvalid: curv,val,phase,curv3d,val3d,phase3d\
                \n       avgcurv,avgval,avgphase,avgcurv3d,avgval3d,avgphase3d"
    return
  }
  # wrong surf types
  if {$type == "curv" || $type == "val" || $type == "phase"} {
    if {!$flag2d} { 
      confirmalert "Compute 2D gradient: first load a flat patch\
                \n\n(or compute gradients on 3D folded surf instead)"
      return
    }
  }
  if {$type == "avgcurv" || $type == "avgval" || $type == "avgphase"} { 
    if {!$flag2d} { 
      confirmalert "Compute 2D region-average gradients: first load flat patch\
               \n\n(or compute region-avg gradients on 3D folded surf instead)"
      return
    }
  }
  if {$type == "curv3d" || $type == "val3d" || $type == "phase3d"} {
    if {$flag2d} {
      confirmalert "Compute 3D gradient: first load 3D surface\
               \n\n(or compute gradients on 2D flat surf instead)"
      return
    }
  }
  if {$type == "avgcurv3d" || $type == "avgval3d" || $type == "avgphase3d"} {
    if {$flag2d} {
      confirmalert "Compute 3D region-average gradients: first load 3D surface\
               \n\n(or compute region-avg gradients on 2D flat surf instead)"
      return
    }
  }
  # forgot to load data (curv always loaded)
  if {$type == "val" || $type == "val3d" ||
      $type == "avgval" ||  $type == "avgval3d"} {
    if {!$valloadedflag} {
      confirmalert "Compute gradient of real: first load the .val field\
                \n\n(e.g., with \"R\" on the \"val:\" line - real data)"
      return
    }
  }
  if {$type == "phase" || $type == "phase3d" ||
      $type == "avgphase" || $type == "avgphase3d"} {
    if {!$valloadedflag || !$val2loadedflag} {
      confirmalert "Compute (avg) gradient phase: first load .val,.val2 fields\
                \n\n(e.g., with \"R\" on the \"val:\" line - complex data)"
      return
    }
  }
  # don't check $valbaks_cart2polarflag - compute_angles_vals_to_baks run below
  # don't test $valbaks_grad2oriflag - compute_angles_vals_to_baks overwrites
  # forgot to load annotation
  if {$type == "avgcurv" || $type == "avgval" || $type == "avgphase" ||
      $type == "avgcurv3d" || $type == "avgval3d" || $type == "avgphase3d"} {
    if {!$annotloadedflag} {
      confirmalert "Compute (avg) gradients: first load annotation\
                \n\n(e.g., with \"D\" on the \"label:\" line)"
      return
    }
  }

  # don't trunc large curv gradients (N.B.: set before b/c used by compute grad)
  if {$type == "curv" || $type == "curv3d"} {  ;# avgcurv OK
    set sdoutlierfact 10.0
    logcmd "set sdoutlierfact 10.0"
  }

  # go: flat
  if {$type == "curv" || $type == "avgcurv"} {
    compute_gradient 0
    logcmd "compute_gradient 0"
    if {$type == "avgcurv"} {
      compute_brainregion_avggrads
      logcmd "compute_brainregion_avggrads"
    }
  }
  if {$type == "val" || $type == "avgval"} {
    compute_gradient 1
    logcmd "compute_gradient 1"
    if {$type == "avgval"} {
      compute_brainregion_avggrads
      logcmd "compute_brainregion_avggrads"
    }
  }
  if {$type == "phase" || $type == "avgphase"} {
    compute_angles_vals_to_baks
    logcmd "compute_angles_vals_to_baks"
    compute_gradient 2
    logcmd "compute_gradient 2"
    if {$type == "avgphase"} {
      compute_brainregion_avggrads
      logcmd "compute_brainregion_avggrads"
    }
  }
  # go: 3d
  if {$type == "curv3d" || $type == "avgcurv3d"} {
    compute_surfgrad 0
    logcmd "compute_surfgrad 0"
    if {$type == "avgcurv3d"} {
      compute_brainregion_avggrads
      logcmd "compute_brainregion_avggrads"
    }
  }
  if {$type == "val3d" || $type == "avgval3d"} {
    compute_surfgrad 1
    logcmd "compute_surfgrad 1"
    if {$type == "avgval3d"} {
      compute_brainregion_avggrads
      logcmd "compute_brainregion_avggrads"
    }
  }
  if {$type == "phase3d" || $type == "avgphase3d"} {
    compute_angles_vals_to_baks
    logcmd "compute_angles_vals_to_baks"
    compute_surfgrad 2
    logcmd "compute_surfgrad 2"
    if {$type == "avgphase3d"} {
      compute_brainregion_avggrads
      logcmd "compute_brainregion_avggrads"
    }
  }

  # displags: all off (leave top-of-stack gradvacflag alone)
  set gradvecbakflag 0
  logcmd "set gradvecbakflag 0"
  set gradvecbak3dflag 0
  logcmd "set gradvecbak3dflag 0"
  set reggradvecbakflag 0
  logcmd "set reggradvecbakflag 0"
  set reggradvecbak3dflag 0
  logcmd "set reggradvecbak3dflag 0"
  # dispflags: (N.B.: reggradvecbak{3d}flag override gradvecbak{3d}flag)
  if {$type == "curv" || $type == "val" || $type == "phase"} {
    set gradvecbakflag 1
    logcmd "set gradvecbakflag 1"
  }
  if {$type == "curv3d" || $type == "val3d" || $type == "phase3d"} {
    set gradvecbak3dflag 1
    logcmd "set gradvecbak3dflag 1"
  }
  if {$type == "avgcurv" || $type == "avgval" || $type == "avgphase"} {
    set reggradvecbakflag 1
    logcmd "set reggradvecbakflag 1"
  }
  if {$type == "avgcurv3d" || $type == "avgval3d" || $type == "avgphase3d"} {
    set reggradvecbak3dflag 1
    logcmd "set reggradvecbak3dflag 1"
  }
  if {$arrowscale < 2.0} {
    set arrowscale 2.0
    logcmd "set arrowscale 2.0"
  }
  #TODO arrows defaults for much less numerous brainregion grad arrs

  redrawbutton
}

#laplacian
proc comp_disp_laplace { type } {
  global valloadedflag val2loadedflag
  global overlayflag complexvalflag colscale fslope fmid fthresh truncphaseflag

  puts "tksurfer.tcl: comp_disp_laplace $type"
  # bad arg
  if {$type != "curv" && $type != "val" && $type != "phase"} {
    confirmalert "Compute gradient: bad type:\
              \n\n  $type\
              \n\nvalid: curv,val,phase"
    return
  }
  # forgot to load data (curv always loaded)
  if {$type == "val"} {
    if {!$valloadedflag} {
      confirmalert "Compute laplacian of real: first load the .val field\
                \n\n(e.g., with \"R\" on the \"val:\" line - real data)"
      return
    }
  }
  if {$type == "phase"} {
    if {!$valloadedflag || !$val2loadedflag} {
      confirmalert "Compute laplacian of phase: first load .val/.val2 fields:\
                \n\n(e.g., with \"R\" on the \"val:\" line - complex data)"
      return
    }
  }
  # don't check $valbaks_cart2polarflag - compute_angles_vals_to_baks run below
  # don't test $valbaks_grad2oriflag - compute_angles_vals_to_baks overwrites

  # go
  if {$type == "curv"} {
    compute_laplacian 0
    logcmd "compute_laplacian 0"
  }
  if {$type == "val"} {
    compute_laplacian 1
    logcmd "compute_laplacian 1"
  }
  if {$type == "phase"} {
    compute_angles_vals_to_baks
    logcmd "compute_angles_vals_to_baks"
    compute_laplacian 2
    logcmd "compute_laplacian 2"
  }

  # display
  set valbakdotbordflag 0  ;# TODO: maybe pos/neg colored dots
  if {!$valbakdotbordflag} {
    if ![okreplace "" \
               "Calculate Laplacian:\
            \n\nReady to swap .valbak into view and reset colscale as follows:\
            \n\n  swap_valval2_valbakval2bak\
              \n  set overlayflag 1        (current: $overlayflag)\
              \n  set truncphaseflag 0   (current: $truncphaseflag)\
              \n  set complexvalflag 0  (current: $complexvalflag)\
              \n  set colscale 11           (current: $colscale)\
              \n  set fslope 2.0              (current: $fslope)\
              \n  set fmid 0.5 (curv: 0.002)  (current: $fmid)\
              \n  set fthresh 0.0            (current: $fthresh)\
            \n\nOK to display .valbak output? (cancel: output left in .valbak)"\
       "Swap .pval Into View, Reset ColScale"] {return }
    swap_valval2_valbakval2bak
    logcmd "swap_valval2_valbakval2bak"
    set overlayflag 1
    logcmd "set overlayflag 1"
    set truncphaseflag 0
    logcmd "set truncphaseflag 0"
    set complexvalflag 0
    logcmd "set complexvalflag 0"
    set colscale 11
    logcmd "set colscale 11"
    set fslope 2.0
    logcmd "set fslope 2.0"
    if {$type == "curv"} {
      set fmid 0.002
      logcmd "set fmid 0.002"
    } else {
      set fmid 0.5
      logcmd "set fmid 0.5"
    }
    set fthresh 0.0
    logcmd "set fthresh 0.0"
  }
  redrawbutton
}

proc comp_disp_fs { } {    ;# N.B. (asks to) write fs files in local dir
  global flag2d fs fsabbrev fm fmabbrev hemi scandir
  global valloadedflag val2loadedflag valbakloadedflag val2bakloadedflag
  global fsdata2gradsflag gradvecflag gradvecbakflag
  global angoffrevarrflag arrownormflag arrowscale

  if { !$valloadedflag && !$val2loadedflag && \
       !$valbakloadedflag && !$val2bakloadedflag && \
       !$flag2d } { ;# nothing done: full message
    confirmalert "Compute fieldsign:\
              \n\nFirst do:\
              \n\n  (1) load flat patch for fieldsign computation\
                \n  (2) load polar (use \"R\" on \"val:\" line)\
                \n  (3) Shift-Middle-S/V (swap_valval2_valbakval2bak)\
                \n  (4) load eccen (use \"R\" on \"val:\" line)\
                \n  (5) come back here and click \"F\""
    return
  }
  if { !$flag2d } {
    confirmalert "Compute fieldsign:\
              \n\n    2D patch for fieldsign computation\
              \n\nnot loaded"
    return
  }
  if { !$valloadedflag || !$val2loadedflag } {
    confirmalert "Compute fieldsign:\n\n    val/val2\n\nnot loaded"
    return
  }
  if { !$valbakloadedflag || !$val2bakloadedflag } {
    confirmalert "Compute fieldsign:\n\n    valbak/val2bak\n\nnot loaded"
    return
  }
  if ![okreplace "" \
        "OK to use current scandir for fieldsign computation?\
     \n\n    curr scandir:  $scandir\
     \n\n\(will only attempt to write: $hemi.fs, $hemi.fm)" "Use"] {
    confirmalert "Compute fieldsign:    ...quitting"
    return
  }

  ## conv r/i to phase/amp, compute fieldsign, maybe conv angles->gradients
  compute_angles     ;# r,i -> phase,amp for both val,val2 and valbak,val2bak
  logcmd "compute_angles"
  if [okreplace "" "OK to show gradients?" "Show Ecc/Pol Gradients"] {
    set fsdata2gradsflag 1
    logcmd "set fsdata2gradsflag 1"
  } else {
    set fsdata2gradsflag 0
    logcmd "set fsdata2gradsflag 0"
  }
  compute_fieldsign
  logcmd "compute_fieldsign"

  ## write fs in curr dir (fs "W" butt def writes to "fs", can't return)
  setfile fs */$scandir/$hemi.fs
  setfile fm [string range $fs 0 [expr [string length $fs] - 4]].fm
  if ![testreplace $fm write_fsmask_curvfmt] { return }
  if ![testreplace $fs write_fieldsign_curvfmt] { return }

  ## fs display (use fieldsign "R" button)
  .files.lf.fieldsign.br invoke

  ## gradients display
  if {$fsdata2gradsflag} {
    set angoffrevarrflag 0
    logcmd "set angoffrevarrflag 0"
    set gradvecflag 1
    logcmd "set gradvecflag 1"
    set gradvecbakflag 1
    logcmd "set gradvecbakflag 1"
    set arrownormflag 1
    logcmd "set arrownormflag 1"
    set arrowscale 0.5
    logcmd "set arrowscale 0.5"
  }
  redrawbutton
  set fsdata2gradsflag 0
  logcmd "set fsdata2gradsflag 0"
}

proc fdrctrls { } {  ;# popup from mid-click "val:" line CS button
  global fdrctrlswin

  if [winfo exists $fdrctrlswin] { raise $fdrctrlswin; return }
  set title "CALC pVAL CORRECTION\
           \nFOR REQUESTED FDR\
           \n(false discovery rate)\
         \n\nCorrected p-val returned\
           \nin pop-up (also, csurf log)\
         \n\nEnter smoothing steps\
           \nand type (redo: reload)\
         \n\nEnter desired FDR\
           \nas p-val (e.g., 0.05)\
         \n\nEnter noise degs freedom\
           \n(e.g., 245 = timepts - 11)\
         \n\nUniq: use only vtxs nearest\
           \navg of set sampling a voxel"
  set variablelist "whitespace \
                    whitespace \
                    smoothsteps \
                    val,weight \
                    desired_FDR \
                    noisedf \
                    whitespace \
                    uniqsampvtxflag \
                    arbitrFDRcovarflag \
                    whitespace"
  set fdrctrlswin [controls $title $variablelist "READY" do_fdr 7]
  bind $fdrctrlswin <ButtonRelease-3> { helpwin val_clust }
}

proc do_fdr { } {
  global fdrctrlswin desired_FDR uniqsampvtxflag
  global val,weight pval_FDR noisedf statloadedflag
  global hemi scandir label labelabbrev stat smoothsteps pvalborddotflag

  ## parms
  if {${val,weight} != "val" && ${val,weight} != "weight"} {
    confirmalert "False Discovery Rate (FDR) pVal Calculation:\
      \n\n    bad smoothtype:  ${val,weight}\n\n(OK: \"val\" or \"weight\")"
    return
  }
  if {$desired_FDR >= 1.0 || $desired_FDR <= 0.0} {
    confirmalert "False Discovery Rate (FDR) pVal Calculation:\
              \n\nbad desired FDR p-val:\n\n    $desired_FDR\
              \n\n(OK: between 0 and 1)"
    return
  }
  if {$noisedf <= 0 || $noisedf > 2048} {
    confirmalert "False Discovery Rate (FDR) pVal Calculation:\
              \n\nbad noise degrees of freedom:    $noisedf\
              \n\n(OK: e.g., 245)"
    return
  }

  ## infiles
  if {!$statloadedflag} {
    confirmalert "False Discovery Rate (FDR) pVal Calculation:\
       \n\n    .stat not loaded\
       \n\nload F-stats to surf with \"val:\" line \"R\",\ then \"S/V\""
    return
  }
  ### xxxxxxx -- omit check _f in filename
  ## N.B.: $stat will still be tksurfer def "scan1-somestat-$hemi.w" unless
  ##       stat mask read (and eccen-views.tcl,etc updates $stat on S/V)
  #if ![string match *_f-$hemi.w $stat] {
  #  confirmalert "False Discovery Rate (FDR) pVal Calculation:\n\nStat file:\
  #            \n\n    [file tail $stat]\
  #            \n\ndoesn't match F-stats pattern: <stem>_f-$hemi.w\
  #            \n\n. . . using anyway"
  #}
  if {$uniqsampvtxflag} {
    setfile label */$scandir/$hemi-UniqSampVtxs.label
    if ![file exists $label] {
      confirmalert "False Discovery Rate (FDR) pVal Calculation:\
                \n\n    uniq vtx label file:   [file tail $label]\
                \n\nnot found in scandir:\
                \n\n    $scandir\
                \n\nRe-run PAINT w/Setup Funct panel \"UniqVtx\" ON\
                  \n(or make w/middle-click UQ on \"val3d:\" line)"
      return
    }
  }

  ## run
  if {$smoothsteps > 0} {
    smooth $smoothsteps ${val,weight}  ;# does complex + stat
    redrawbutton
  }
  clear_uniqvoxdata  ;# else stale used if there from prev run
  if {$uniqsampvtxflag} {
    read_uniqsamp_vertices
    logcmd "read_uniqsamp_vertices"
  }
  # log popup values
  logcmd "set noisedf $noisedf"
  # go
  set pvalborddotflag 0
  logcmd "set pvalborddotflag 0"
  pval_from_fourier_fstat
  logcmd "pval_from_fourier_fstat"
  find_FDR_from_pvals $desired_FDR
  logcmd "find_FDR_from_pvals $desired_FDR"
  ## report
  confirmalert "False Discovery Rate (FDR) correction for F-stats:\
            \n\n    for desired FDR = $desired_FDR\
            \n\n    use p-value = [format "%1.6f" $pval_FDR]"
  if [winfo exists $fdrctrlswin] { destroy $fdrctrlswin }
  set fdrctrlswin ""
}

proc do_getvmsuff { action } {
  global vmsuffctrlswin viewmatrixsuff viewmatrix

  set saveviewmatrix $viewmatrix
  set viewmatrix ${viewmatrix}${viewmatrixsuff}
  logcmd "set viewmatrix ${viewmatrix}${viewmatrixsuff}"
  if {"$action" == "write"} { .xform.translate.bot.la.top.ri.bu  invoke }
  if {"$action" == "read"}  { .xform.translate.bot.la.top.ri.bu2 invoke }
  set viewmatrix $saveviewmatrix
  logcmd "set viewmatrix $saveviewmatrix"
  if [winfo exists $vmsuffctrlswin] { destroy $vmsuffctrlswin }
  set histctrlswin ""
}

proc histctrls { } {  ;# popup from mid-click "h" (help,histogram) button
  global histctrlswin histtype histbins histsmoothsteps complexvalflag

  if [winfo exists $histctrlswin] { raise $histctrlswin; return }
  if {$complexvalflag} { set histtype 3 } else { set histtype 0 }
  set title "SURFACE DATA\
           \nHISTOGRAM\
           \n(reqs gnuplot)\
         \n\nEnter hist type: 0-6\
           \n(can adj bins/smooth):\
         \n\n    0: curv (.curv)\
           \n1: val (.val)\
           \n     2: complex amp\
           \n    3: complex ang\
           \n           4: ang, amp>fthresh\
           \n             5: ang, stat>\sfthresh\
           \n  6: stat (.stat)"
  set variablelist "whitespace \
                    histtype \
                    histbins \
                    histsmoothsteps \
                    whitespace"
  set histrlswin [controls $title $variablelist "READY" do_hist 7]
}

proc do_hist { } {
  global histctrlswin histtype histbins histsmoothsteps
  global curvloadedflag valloadedflag val2loadedflag statloadedflag

  if { ![file exists /usr/local/gnuplot] &&
       ![file exists /opt/local/bin/gnuplot] } {
    confirmalert "Histogram:\n\n    gnuplot not found\
              \n\nLooked for:\
              \n\n    /usr/local/gnuplot\
                \n    /opt/local/bin/gnuplot"
    return
  }
  if {$histtype < 0 || $histtype > 6} {
    confirmalert "Histogram:\
      \n\n    bad histtype:  $histtype\n\n(OK:0-6)"
    return
  }
  if {$histtype == 0 && !$curvloadedflag} {
    confirmalert "Histogram:\
              \n\n    no data in .curv field\
              \n\nload data using \"R\" on \"curv:\" line"
    return
  }
  if {$histtype == 1 && !$valloadedflag} {
    confirmalert "Histogram:\
              \n\n    no data in .val field\
              \n\nload data using \"R\" on \"val:\" or \"label:\" line"
    return
  }
  if {$histtype == 2 || $histtype == 3 || $histtype == 4 || $histtype == 5} {
    if {!$valloadedflag || !$val2loadedflag} {
      confirmalert "Histogram:\
                \n\n    no complex data (.val plus .val2 field)\
                \n\nload data using \"R\" on \"val:\" or \"label:\" line"
      return
    }
  }
  if {$histtype == 5 || $histtype == 6} {
    if {!$statloadedflag} {
      confirmalert "Histogram:\
                \n\n    no data in .stat field\
                \n\nload data using:\
                \n\n    (1) \"R\" on \"val:\" or \"label:\" line\
                  \n    (2) \"S/V\" (swap .stat and .val)"
      return
    }
  }

  print_hist $histtype $histbins $histsmoothsteps
  logcmd "print_hist $histtype $histbins $histsmoothsteps"

  if [winfo exists $histctrlswin] { destroy $histctrlswin }
  set histctrlswin ""
}

proc spotopctrls { } {  ;# popup from mid-click SMOOTH button
  global spotopctrlswin fillneartype num,sqmm,mm optype
  global searchlightuniqflag numafteruniqflag

  if [winfo exists $spotopctrlswin] { raise $spotopctrlswin; return }
  set title "SEARCHLIGHT OPERATION\
               \nN.B.: 9 min/hemi (4core i7, 8thr)\
             \n\nFill nearest (fillneartype):\
               \n 0:  num vertices\
               \n 1:  area (mm^2)\
               \n2:  radius (mm)\
               \n       3:  neigh order (1-6)\
             \n\nSearchight operation (optype):\
               \n0:  average val in ROIs\
               \n 1:  count intIDs in ROIs\
               \n   2:  variance (subtr cent)\
               \n    3:  no-overlap IDs (fill=3)\
               \n   4:  simple sum               \
             \n\nOutput:  to .stat field"
  set variablelist "whitespace \
                    fillneartype \
                    num,sqmm,mm \
                    optype \
                    whitespace \
                    searchlightuniqflag \
                    numafteruniqflag \
                    whitespace"
  set spotopctrlswin [controls $title $variablelist "READY" "do_spotop" 11]
}

proc do_spotop { } {
  global spotopctrlswin fillneartype num,sqmm,mm optype valloadedflag

  if {!$valloadedflag} {
    confirmalert "Searchlight Operation:\
              \n\n    no data in .val field\
              \n\nload data using \"R\" on \"val:\" or \"label:\" line"
    return
  }
  if {$fillneartype < 0 || $fillneartype > 3} {
    confirmalert \
            "bad fillneartype:  $fillneartype\n(valid \$fillneartype's: 0-3)\
                  \n\n    0 = n nearest vertices\
                    \n    1 = nearest vertices until area reached\
                    \n    2 = nearest until radius reached\
                    \n    3 = neighbor order (1-6)"
    return
  }
  if {$optype < 0 || $optype > 4} {
    confirmalert "bad searchlight optype:  $optype\n(valid \$optype's: 0-4)\
                  \n\n    0 = average val in ROIs\
                    \n    1 = count intIDs in ROIs\
                    \n    2 = variance (subtr cent vtx)\
                    \n    3 = non-overlapping paint intID's\
                    \n    4 = sum in ROIs"
    return
  }
  if {$optype == 3 || $fillneartype != 3} {
    confirmalert "optype=3 (paint non-overlapping intIDs)\
              \n\n    requires\
              \n\n fillneartype=3 (neighbor order)"
    return
  }

  searchlightop_val2stat $fillneartype ${num,sqmm,mm} $optype  ;# 10 min
  logcmd "searchlightop_val2stat $fillneartype ${num,sqmm,mm} $optype"
  if {$fillneartype == 3} {
    logcmd "# equivalent: neighop_val2stat ${num,sqmm,mm} $optype"
  }

  if {$optype == 0} { set optypetext "average .val in ROIs" }
  if {$optype == 1} { set optypetext "count intIDs in ROIs" }
  if {$optype == 2} { set optypetext "variance in ROIs (after subtract cent)" }
  if {$optype == 3} { set optypetext "painted non-overlapping intIDs" }
  if {$optype == 4} { set optypetext "sum .val in ROI's" }
  confirmalert "Searchlight Operation (optype=$optype) done:\
            \n\n    $optypetext\
            \n\nResult put into (invisible) .stat field\
            \n\nTo view: do \"S/V\", then adjust colscale"

  if [winfo exists $spotopctrlswin] { destroy $spotopctrlswin }
}

proc display_ctab { } {  ;# LUT auto-generated by read_mgh_annot
  global isession labelabbrev

  # regions popup: cp str handle ctab loc: read_mgh_annot/read_gifti_to_annot
  after 500 {  ;# after slower redraw raise
    set ctabpref [string range [file rootname [file tail $labelabbrev]] 3 end]
    helpwin $isession/scripts/$ctabpref.ctab 50 22  ;# no-op missing
  }
}

proc do_nonoverlap2stat { } {
  global neighord

  neighop_val2stat $neighord 3
  logcmd "neighop_val2stat $neighord 3"
  confirmalert "To see result:\
            \n\n  (1) convert .stat to randcol annot:\
            \n\n       R-clk \"label:\" line \"W\" to get buttons popup\
              \n       use \"Write StatIDs to RandCol MGH Annot\" button\
            \n\n  (2) display the resulting annot:\
            \n\n       use \"label:\" line \"R\""
}

proc nonoverlap2statctrls { } {  ;# 2nd popup added to SMOOTH button
  global nonoverlap2statctrlswin neighord ffontb

  if [winfo exists $nonoverlap2statctrlswin] {
    raise $nonoverlap2statctrlswin
    return
  }
  set title "NON-OVERLAPPING PAINTBALLS\
         \n\ntcl funct: neighop_val2stat <neighord> 3\
           \nneighbor order controls paintball size\
           \noutput (seq. int regions) to .stat field\
         \n\nMAKE STAT IDNUMS writes .stat field\
           \nGROW STAT IDNUMS fills gaps in .stat\
         \n\nTo see/use result:                                    \
         \n(1) convert .stat to randcol annot:           \
           \n  R-clk \"label:\" line \"W\" for buttons\
           \n        \"Write StatIDs to RandCol MGH Annot\"\
           \n(2) display resulting annot:                      \
           \nselect output, \"label:\" line \"R\"    \
         \n\nneighord=1:     7 vertices   \
           \nneighord=2:   19 vertices   \
           \nneighord=3:   37 vertices   \
           \nneighord=4:   61 vertices   \
           \nneighord=5:   91 vertices   \
           \nneighord=6: 127 vertices    "
  set variablelist "whitespace \
                    neighord \
                    whitespace"
  set nonoverlap2statctrlswin \
    [controls $title $variablelist "MAKE STAT IDNUMS" \
     "do_nonoverlap2stat"]
  bind $nonoverlap2statctrlswin <ButtonRelease-3> { helpwin smooth}
  bind $nonoverlap2statctrlswin.neighord.e <Return> { do_nonoverlap2stat }
  # hack in another button (sorry)
  update idletasks
  button $nonoverlap2statctrlswin.bu2 -text "GROW STAT IDNUMS" -font $ffontb \
    -pady 2 -padx 5
  $nonoverlap2statctrlswin.bu2 config -command {
    grow_stat_idnums
    logcmd "grow_stat_idnums"
    confirmalert "spaces between .stat idnum regions filled"
  }
  pack $nonoverlap2statctrlswin.bu2 -side top
  # end hack
}

proc annotmaskctrls { } {  ;# popup from shift-R-click "label:" line D butt
  global annotmaskctrlswin annotloadedflag valloadedflag hemi overlayflag
  global labelabbrev visible_idnums_list vtxcolflag
  global unmasked_to_label_flag 
  global unmasked_to_labels_flag

  if {!$annotloadedflag} {
    confirmalert "Mask Using Annot or Display Annot Subset:\
              \n\n    no annotation loaded\
              \n\n(1) select *.annot from \"label:\" dropdown\
                \n(2) use \"D\" button to read it"
    return
  }

  # regions popup
  display_ctab
  update idletasks
  after 500

  if [winfo exists $annotmaskctrlswin] { raise $annotmaskctrlswin; return }

  if {$vtxcolflag} {  ;# vtxcol loaded: show subset vtxcol paint
    set title "DISPLAY SUBSET VTXCOL \"PAINT\" BY ANNOT IDNUM{S}\
           \n\nEnter space-separated list of VISIBLE idnums\
             \n(or \"all\", to re-show all)\
           \n\nAdjust gray curv contrast with \$cvfact (def=1.3),\
             \nat upper-right, just to left of \"intp\" checkbox\
           \n\nTo find idnums of vtxcol regions to show, use either:\
              \n      (1) idnum list in popup HELP window    \
              \n      (2) double-middle-click region, including\
              \ncurrently masked regions\
            \n\n(to mask overlay data, turn off vtxcolflag,\
              \nload overlay/val data, and re-open panel)\
            \n\n(to display subset colored annotation regions,\
              \nturn off vtxcolflag, and re-open panel)"
    set variablelist "whitespace \
                      visible_idnums_list \
                      whitespace"
    set annotmaskctrlswin \
      [controls $title $variablelist "READY" do_annotsubset 40]
  } elseif {!$valloadedflag || !$overlayflag} { ;#no overlay: show subset annots
    set title "DISPLAY SUBSET OF ANNOT IDNUM(S)\
             \n(if .val,\[.val2\] loaded, see only data for idnums)\
           \n\nEnter space-separated list of VISIBLE idnums\
             \n(or \"all\", to re-show all)\
           \n\nControl annot transparency with upper-left\
             \n\"tran\" entry (default: 255=opaque)\
           \n\nAdjust gray curv contrast with \$cvfact (def=1.3),\
             \nat upper-right, just to left of \"intp\" checkbox\
           \n\nTo find idnums of regions to show, use either:\
              \n      (1) idnum list in popup HELP window    \
              \n      (2) double-middle-click region, including\
              \ncurrently masked regions\
            \n\n(to mask overlay data, load overlay/val\
              \ndata, and re-open panel)\
            \n\n(to mask vtxcol \"paint\", load vtxcol\
              \n*.cols file, and re-open panel)"
    set variablelist "whitespace \
                      visible_idnums_list \
                      whitespace"
    set annotmaskctrlswin \
      [controls $title $variablelist "READY" do_annotsubset 40]
  } else {              ;# overlay loaded: mask overlay data with subset
    set title "MASK OVERLAY USING ANNOT IDNUM(S)\
             \n(optional extract overlay data to labels)\
           \n\nEnter space-separated list of UNMASKED idnums\
             \n(or \"all\", to re-show all overlay data)\
           \n\nTo find idnums of regions to show, use either:\
              \n  (1) idnum list in popup HELP window\
              \n  (2) double-middle-click region           \
            \n\nIf optional extract all unmasked overlay data to one label,\
             \n\"labelabbrev\" (output label) must end in:  $hemi-<infix>.label\
            \n\nIf optional extract unmasked overlay data to individual labels,\
             \n\"labelabbrev\" (output labels stem) must end in:  $hemi-<infix>\
           \n\n(to display subset colored annotation regions,\
             \nuntick \"ovlay\", and re-open panel)\
           \n\n(to mask vtxcol \"paint\", load vtxcol\
             \n*.cols file, and re-open panel)"
    set variablelist "whitespace \
                      visible_idnums_list \
                      whitespace \
                      unmasked_to_label_flag \
                      unmasked_to_labels_flag \
                      labelabbrev \
                      whitespace"
    set annotmaskctrlswin \
      [controls $title $variablelist "READY" do_annotmask 40]

    # modify current labelabbrev to respect write_val_idnum_vertices req's
    set labelabbrev [file dirname $labelabbrev]/$hemi-[string range [file rootname [file tail $labelabbrev]] 3 end]

    # internal hack: form switch from two flags
    $annotmaskctrlswin.ck0 config -command {
      if {$unmasked_to_label_flag} {
        set unmasked_to_labels_flag 0
        $annotmaskctrlswin.labelabbrev.la config -state normal
        $annotmaskctrlswin.labelabbrev.e config -state normal
      } else {
        $annotmaskctrlswin.labelabbrev.la config -state disabled
        $annotmaskctrlswin.labelabbrev.e config -state disabled
      }
    }

    # internal hack: enable/disable labelabbrev on toggle
    #   unmasked_to_labels_flag
    $annotmaskctrlswin.ck1 config -command {
      if {$unmasked_to_labels_flag} {
        set unmasked_to_label_flag 0
        $annotmaskctrlswin.labelabbrev.la config -state normal
        $annotmaskctrlswin.labelabbrev.e config -state normal
      } else {
        $annotmaskctrlswin.labelabbrev.la config -state disabled
        $annotmaskctrlswin.labelabbrev.e config -state disabled
      }
    }
    if {!$unmasked_to_labels_flag} {  ;# init
      $annotmaskctrlswin.labelabbrev.la config -state disabled
      $annotmaskctrlswin.labelabbrev.e config -state disabled
    }
    bind $annotmaskctrlswin <ButtonRelease-3> { helpwin label_read }
  }
}

proc do_annotsubset { } {
  global annotmaskctrlswin visible_idnums_list
  global labelflag overlayflag labelalpha annotmaskflag vtxcolflag

  if {"$visible_idnums_list" == "0"} {
    confirmalert "Display Subset Annot:\
      \n\n    0: no visible regions requested\
      \n\nEnter space-separated list of integer idnums (or \"all\")"
    return
  }

  # go/redraw
  if {"$visible_idnums_list" == "all"} {
    set_idnums_visibility 1
    logcmd "set_idnums_visibility 1"
  } else {
    foreach num $visible_idnums_list {
      if ![string is int "$num"] {
        confirmalert "Mask Annot:\n\nbad idnum: $num"
        return
      }
    }
    set annotmaskflag 1  ;# force slow annot2brainregionindex() search
    logcmd "set annotmaskflag $annotmaskflag"
    if {$vtxcolflag} { set labelflag 0 } else { set labelflag 1 }
    logcmd "set labelflag $labelflag"
    set overlayflag 1
    logcmd "set overlayflag $overlayflag"
    set labelalpha 255   ;# def keep annots saturated
    logcmd "set labelalpha $labelalpha"
    set_annot_alpha $labelalpha  ;# update interface
    logcmd "set_annot_alpha $labelalpha"

    set_idnums_visibility 0  ;# start by masking everything
    logcmd "set_idnums_visibility 0"
    foreach num $visible_idnums_list {
      set_idnum_visibility $num 1
      logcmd "set_idnum_visibility $num 1"
    }
  }
  redrawbutton
}

proc do_annotmask { } {
  global annotmaskctrlswin visible_idnums_list
  global unmasked_to_label_flag
  global unmasked_to_labels_flag
  global annotmaskflag labelflag hemi label labelabbrev 
  global normdsampsearchflag transform_loaded
  global complexvalflag usecurrcoordsflag usetalcoordsflag

  if {"$visible_idnums_list" == "0"} {
    confirmalert "Mask Using Annot:\
      \n\n    0: no visible regions requested\
      \n\nEnter space-separated list of integer idnums (or \"all\")\
      \n\n. . . quitting"
    return
  }
  if {$unmasked_to_label_flag} {
    set currabbrev [.files.label.cbx subwidget entry get]
    if ![string match ${hemi}* [file tail $currabbrev]] {
      confirmalert "Write one label for visible MGH annotation regions:\
                \n\nPrefix for output label:\
                \n\n    [file tail $currabbrev]\
                \n\ndoesn't match current hemi:\n\n    $hemi
                \n\n. . . quitting"
      return
    }
    if ![string match *.label [file tail $currabbrev]] {
      confirmalert "Write one label for visible MGH annotation regions:\
                \n\nSuffix for output label:\
                \n\n    [file tail $currabbrev]\
                \n\nnot .label\
                \n\n. . . quitting"
      return
    }
  }
  if {$unmasked_to_labels_flag} {
    set currabbrev [.files.label.cbx subwidget entry get]
    if ![string match ${hemi}* [file tail $currabbrev]] {
      confirmalert "Write labels for visible MGH annotation regions:\
                \n\nPrefix for output labels:\
                \n\n    [file tail $currabbrev]\
                \n\ndoesn't match current hemi:\n\n    $hemi\
                \n\n. . . quitting"
      return
    }
    if { [string length [file tail $currabbrev]] < 4 } {
      confirmalert "Write labels for visible MGH annotation regions:\
                \n\nPrefix for output labels:\
                \n\n    [file tail $currabbrev]\
                \n\nlacks infix of at least 1 char.  Should look like:\
                \n\n    $hemi-<infix>\
                \n\n. . . quitting"
      return
    }
    if { [string range [file tail $currabbrev] 2 2] != "-" } {
      confirmalert "Write labels for visible MGH annotation regions:\
                \n\nPrefix for output labels:\
                \n\n    [file tail $currabbrev]\
                \n\nmust have '-' (dash) as third character, like this:\
                \n\n    $hemi-<infix>\
                \n\n. . . quitting"
      return
    }
    if [string match *.label $currabbrev] {
      confirmalert "Write labels for visible MGH annotation regions:\
                \n\nOmit \".label\" from prefix for output labels:\
                \n\n    [file tail $currabbrev]\
                \n\nIt will be auto-appended after region name\
                \n\n. . . quitting"
      return
    }
  }

  # go/redraw
  if {"$visible_idnums_list" == "all"} {
    set_idnums_visibility 1
    logcmd "set_idnums_visibility 1"
  } else {
    foreach num $visible_idnums_list {
      if ![string is int "$num"] {
        confirmalert "Mask Annot:\n\nbad idnum: $num"
        return
      }
    }
    set annotmaskflag 1
    logcmd "set annotmaskflag $annotmaskflag"
    set labelflag 0
    logcmd "set labelflag $labelflag"
    set_idnums_visibility 0  ;# start by masking everything
    logcmd "set_idnums_visibility 0"
    foreach num $visible_idnums_list {
      set_idnum_visibility $num 1
      logcmd "set_idnum_visibility $num 1"
    }
  }
  redrawbutton

  # make targ/coords/normsearch popup messages for next 2 (optional)
  if {$unmasked_to_label_flag ||
      $unmasked_to_labels_flag} {
    if {$complexvalflag} {set targ ".val/.val2"} else {set targ ".val"}
    if {$usecurrcoordsflag} {
      set coords "N.B.: x,y,z coords in file: from CURRENT surface"
    } elseif {$usetalcoordsflag && $transform_loaded} {
      set coords "N.B.: x,y,z coords in file: .orig conv -> MNI Talairach"
    } else {
      set coords "N.B.: x,y,z coords in file: from .orig surface"
    }
    if {$normdsampsearchflag && !$usecurrcoordsflag} {
      set normsearch "N.B.: x,y,z coords INCLUDE move along normal\
                    \n            (left-click \"label:\" label for curr parms)\
                    \n            (for no move, untick normdsampsearchflag)"
    } else {
      set normsearch "N.B.: x,y,z coords NOT modified by move along normal"
    }
  }

  # optional write all unmasked to one label
  if {$unmasked_to_label_flag} {
    if [okreplace "" "Write $targ for currently visible regions\
                    \nto one label file?\
                  \n\n$coords\
                    \n$normsearch\
                  \n\n(next checks overwrite)" \
                    "Write One Label"] {
      uplevel #0 "setfile label $labelabbrev"  ;# expand current abbrev
      if { [file exists $label] } {
        if ![okreplace $label \
              "label file:\n\n    $label\n\nalready exists.  Overwrite?" \
              "Overwrite"] {
          confirmalert "Mask Annot: label not altered"
        } else {
          write_val_unmasked_vertices
          confirmalert "All visible data written to label:\n\n    $label"
        }
      } else {
        write_val_unmasked_vertices
        confirmalert "All visible data written to label:\n\n    $label"
      }
    }
  }

  # optional write labels
  if {$unmasked_to_labels_flag} {
    if [okreplace "" "Write $targ for currently visible regions\
                    \nto separate label files (with area-name infixes)?\
                  \n\n$coords\
                    \n$normsearch\
                  \n\n(doesn't check overwrite)" \
                  "Write [llength $visible_idnums_list] Labels"] {
      foreach num $visible_idnums_list {
        uplevel #0 "setfile label $labelabbrev"  ;# expand current
        write_val_idnum_vertices $num
      }
      confirmalert "[llength  $visible_idnums_list] label files written to dir:\
                \n\n    [file dirname $label]\
                \n\nwith names formatted as follows:\
                \n\n    [file tail $label]_<some-region1>.label\
                  \n    [file tail $label]_<some-region2>.label\
                  \n    . . ."
    } else {
      confirmalert "Mask Annot: no label files written"
    }
  }

  ## leave window up for redo
  #if [winfo exists $annotmaskctrlswin] { destroy $annotmaskctrlswin }
  #set annotmaskctrlswin ""
}

# begin "val:" line R (read) no-arg button procs
############################################################################
proc valR_read { } {
  global val valabbrev overlayflag

  setfile val [.files.val.cbx subwidget entry get]
  read_real_or_complex_binary_values
  fix_nonzero_vals  ;# for sparse smooth (OK to do even if read fails)
  logcmd "fix_nonzero_vals"
  set overlayflag 1
  logcmd "set overlayflag 1"
  redrawbutton
}

proc valR_read_demean_varnorm { } {
  global val overlayflag

  confirmalert "read data to .val\nsubtract mean\ndivide by stdev"
  setfile val [.files.val.cbx subwidget entry get]
  read_real_or_complex_binary_values
  fix_nonzero_vals  ;# for sparse smooth (OK to do even if read fails)
  logcmd "fix_nonzero_vals"
  set overlayflag 1
  logcmd "set overlayflag 1"
  demean_varnorm_val
  logcmd "demean_varnorm_val"
  redrawbutton
}

proc valR_read_cmplxamp_1 { } {
  global val valabbrev complexvalflag overlayflag

  if {!$complexvalflag} {
    confirmalert "meanamp2one_valval2: overlay data not complex"
    return
  }
  confirmalert "read data to .val/.val2\nscale avg complex amp to 1.0"
  setfile val [.files.val.cbx subwidget entry get]
  read_real_or_complex_binary_values
  fix_nonzero_vals  ;# for sparse smooth (OK to do even if read fails)
  logcmd "fix_nonzero_vals"
  set overlayflag 1
  logcmd "set overlayflag 1"
  meanamp2one_valval2
  logcmd "meanamp2one_valval2"
  redrawbutton
}

proc valR_3frame_mgh_to_vec { } {
  global val valabbrev dipolesflag hemi genstrret_1k

  setfile val [.files.val.cbx subwidget entry get]
  if ![string match *.mgh $val] {
    confirmalert "read_mgh_dipoles:\n\nrequires 3-frame *.mgh file"
    return
  }
  if {$hemi == "lh" && [string match *.rh.* $val] } {
    confirmalert "Selected valfile name:\
              \n\n    $val\
              \n\ncontains an \"*.rh.*\" (but current hemi is: lh)\
              \n\nPerhaps file belongs to other hemisphere?"
  }
  if {$hemi == "rh" && [string match *.lh.* $val] } {
    confirmalert "Selected valfile name:\
              \n\n    $val\
              \n\ncontains an \"*.lh.*\" (but current hemi is: rh)\
              \n\nPerhaps file belongs to other hemisphere?"
  }
  read_mgh_header
  set nframes 0
  foreach line [split $genstrret_1k "\n"] {
    if { [lindex $line 0] == "nframes" } { set nframes [lindex $line 2] }
  }
  if {$nframes != 3} {
    confirmalert "Found $nframes frames in dipole/vector file:\
              \n\n    $val\
              \n\nFile must have nframes=3 to be read as dipoles/vectors"
    return
  } else {
    read_mgh_dipoles
    logcmd "read_mgh_dipoles"
    set dipolesflag 1
    logcmd "set dipolesflag 1"
    redrawbutton
  }
}

# begin "val:" line S/V (swap stat val) no-arg button procs
############################################################################
proc valSV_swap_stat_val { } {
  if ![okreplace "" \
         "Do swap_stat_val:\
      \n\nFor stack at each vertex,\
        \nswap top member (.val)\
        \nand .stat:\
      \n\n    ----------------------------------------\
        \n    val\t\t(visible)\
        \n    val2\t\t(visible if complex)\
        \n    ----------------------------------------\
        \n    stat\t\t(invisible)\
        \n    ----------------------------------------\
        \n    valbak\t\t(invisible)\
        \n    val2bak\t(invisible)\
        \n    ----------------------------------------" \
        "Swap Stat / Val"] { return }
  swap_stat_val
  logcmd "swap_stat_val"
  swap_settings
  redrawbutton
}

proc valSV_swap_val_val2 { } {
  if ![okreplace "" \
         "Do swap_val_val2:\
      \n\nFor stack at each vertex,\
        \nswap top two members (.val, .val2):\
      \n\n    ----------------------------------------\
        \n    val\t\t(visible)\
        \n    val2\t\t(visible if complex)\
        \n    ----------------------------------------\
        \n    stat\t\t(invisible)\
        \n    ----------------------------------------\
        \n    valbak\t\t(invisible)\
        \n    val2bak\t(invisible)\
        \n    ----------------------------------------" \
        "Swap Val / Val2"] { return }
  swap_settings
  swap_val_val2
  logcmd "swap_val_val2"
  redrawbutton
}

proc valSV_complex_stack { } {
  if ![okreplace "" \
         "Do swap_valval2_valbakval2bak:\
      \n\nFor stack at each vertex,\
        \nswap top pair (.val, .val2) with\
        \nbottom pair (.valbak, .val2bak):\
      \n\n    ----------------------------------------\
        \n    val\t\t(visible)\
        \n    val2\t\t(visible if complex)\
        \n    ----------------------------------------\
        \n    stat\t\t(invisible)\
        \n    ----------------------------------------\
        \n    valbak\t\t(invisible)\
        \n    val2bak\t(invisible)\
        \n    ----------------------------------------" \
        "Swap Val,Val2 / ValBak,Val2Bak"] { return }
  swap_settings
  swap_valval2_valbakval2bak
  logcmd "swap_valval2_valbakval2bak"
  redrawbutton
}

proc valSV_swap_pval_val { } {
  if ![okreplace "" \
         "Do swap_pval_val:\
      \n\nFor stack at each vertex,\
        \nswap top member (.val)\
        \nand .pval:\
      \n\n    ----------------------------------------\
        \n    val\t\t(visible)\
        \n    val2\t\t(visible if complex)\
        \n    ----------------------------------------\
        \n    stat\t\t(invisible)\
        \n    pval\t\t(invisible)\
        \n    ----------------------------------------\
        \n    valbak\t\t(invisible)\
        \n    val2bak\t(invisible)\
        \n    ----------------------------------------" \
        "Swap PVal / Val"] { return }
  swap_settings
  swap_pval_val
  logcmd "swap_pval_val"
  redrawbutton
}

proc valSV_curv_curvbak { } {
  if ![okreplace "" \
       "Do swap_curv_curvbak:\
    \n\nFor stack at each vertex,\
      \nswap .curv and .curvbak" \
       "Swap Curv / CurvBak"] { return }
  #swap_settings  ;# curv settings?
  swap_curv_curvbak
  logcmd "swap_curv_curvbak"
  redrawbutton
}

proc valSV_curv_val { } {
  if ![okreplace "" \
         "Do swap_curv_val:\
      \n\nFor stack at each vertex,\
        \nswap top member (.val) and .curv" \
         "Swap Curv / Val"] { return }
  if {$complexvalflag} {
    confirmalert "N.B.: real-valued curv swapped with\
                \nreal part of complex num (val,val2)"
  }
  #swap_settings  ;# curv settings?
  swap_curv_val
  logcmd "swap_curv_val"
  redrawbutton
}

proc valSV_origarea_val { } {
  if ![okreplace "" \
         "Do swap_origarea_val:\
      \n\nFor stack at each vertex,\
        \nswap top member (.val) and .origarea\
      \n\n(at startup, origarea loaded w/area file)" \
         "Swap OrigArea / Val"] { return }
  if {$complexvalflag} {
    confirmalert "N.B.: real-valued origarea swapped with\
                \nreal part of complex num (val,val2)"
  }
  #swap_settings  ;# curv settings?
  swap_origarea_val
  logcmd "swap_origarea_val"
  redrawbutton
}

proc valSV_idnum_val { } {
  global annotloadedflag complexvalflag

  if {!$annotloadedflag} {
    confirmalert "No annotation loaded\
              \n\nfirst load annotation with \"D\" on \"label:\" line"
    return
  }
  if ![okreplace "" \
         "Do copy_idnum_val:\
      \n\nFor stack at each vertex,\
        \nfind idnum of curr annotation\
        \ncopy it to real (.val) field\
     \n\n(overwrites loaded .val, if any)" \
         "Copy IDnum to Val"] { return }
  if {$complexvalflag} {
    confirmalert "Integer IDnums written to .val field:\
              \n\nN.B.: complex-valued data overwritten:\
              \n\n  real (.val)  -> idnum\
                \n  imag (.val2) -> 0.0"
    set complexvalflag 0
    logcmd "set complexvalflag 0"
  } else {
    confirmalert "Integer IDnums written to .val field:\
              \n\n  real (.val)  -> idnum"
  }
  copy_idnum_val
  logcmd "copy_idnum_val"
  redrawbutton
  confirmalert "Can save as labelfile or wfile with:\
            \n\n  (1) \"W\" on \"label:\" line (ASCII)\
              \n  (2) \"W\" on \"val:\" line (binary)\
            \n\nCan display with:\
            \n\n  (1) use mkrandlut to make val2rgb.lut in scriptsdir\
              \n  (2) set colscale 12 (\"lt\" on \"Col:\" popup)\
              \n  (3) read val2rgb.lut with \"R\" on \"lut:\" line"
}

# begin "val:" line CS (cluster/FDR) no-arg button procs
############################################################################
proc valCS_run_surfclust { } {
  global statloadedflag

  if {!$statloadedflag} {
    confirmalert "Cluster: stat not loaded: use S/V (swap_stat_val)"
    return
  }
  run_surfclust
  logcmd "run_surfclust"
  redrawbutton
}

proc valCS_FDR_ctrls { } {
  fdrctrls
}

# begin "val:" line CLR no-arg button procs
############################################################################
proc valCLR_clear_valval2 { } {
  if ![okreplace "" "Clear vertex data values (.val,.val2 fields)" \
                 "Clear .val,.val2 fields"] { return }
  clear_values
  logcmd "clear_values"
  redrawbutton
}

proc valCLR_clear_stats { } {
  if ![okreplace "" "Clear vertex stat values (.stat field)" \
                 "Clear .stat field"] { return }
  clear_stats
  logcmd "clear_stats"
  redrawbutton
}

proc valCLR_clear_all { } {
  if ![okreplace "" \
                   "Clear all vertex data:\
                \n\n    visible values (.val, .val2)\
                  \n    statistics (.stat, .pval)\
                  \n    uniq paint calc (.uniqvoxnum, .uniqvoxcnt)\
                  \n    value stack bottom (.valbak, .valbak2)\
                 \n\nN.B.: leaves transparent, vertexcolor labels\
                   \n(use \"label:\" line CLR to clear those)" \
                 "Clear all Vertex Data"] { return }
  clear_values
  logcmd "clear_values"
  clear_valbaks
  logcmd "clear_valbaks"
  clear_stats
  logcmd "clear_stats"
  clear_pvals
  logcmd "clear_pvals"
  clear_uniqvoxdata
  logcmd "clear_uniqvoxdata"
  redrawbutton
}

# begin "val:" line W no-arg button procs
############################################################################
proc valW_write { } {
  global val valabbrev allverticesflag val2newcurvflag

  setfile val [.files.val.cbx subwidget entry get]
  if {$allverticesflag} {
    set wflagmsg1 "save all vertices  (\$allverticesflag=$allverticesflag)"
  } else {
    set wflagmsg1 "save only nonzero  (\$allverticesflag=$allverticesflag)"
  }
  if {$val2newcurvflag} {
    set wflagmsg2 "new curv format  (\$val2newcurvflag=$val2newcurvflag)"
  } else {
    set wflagmsg2 "orig wfile format  (\$val2newcurvflag=$val2newcurvflag)"
  }
  if ![okreplace "" \
                 "Write currently displayed vertex values to:\
              \n\n    $val\
              \n\nVertex list output format:\
              \n\n    $wflagmsg1\
                \n    $wflagmsg2\
              \n\nTo change output format, Cancel, mid-clk \"val:\"\
                \nfor parms popup, adjust parms, try again" \
                 "Write Vertex List File"] { return }
  testreplace $val write_real_or_complex_binary_values
}

proc valW_FT2percent { } {
  writedftampctrls 
}

proc valW_mgh1D { } {
  global val valabbrev complexvalflag

  if {$complexvalflag} {
    confirmalert "Write MGH Values:  can't write complex-valued data\
              \n\n    (1)  untick \"cpx\"\
                \n    (2)  verify/display real data\
                \n    (3)  try again"
    return
  }
  if ![okreplace "" \
                 "Alternate write currently displayed vertex values as:\
              \n\n    1-D, *.mgh format, float file\
              \n\n(vertex list as pseudo-volume)" \
                 "Write 1D MGH File"] { return }
  setfile val [.files.val.cbx subwidget entry get]
  if ![string match *.mgh $val] {
    if ![okreplace "" "Write MGH file without *.mgh suffix?\
                   \n\nN.B.: won't be recognized on re-read" "OK"] { return }
  }
  testreplace $val write_mgh_values
}

proc valW_vtkvals { } {
  global val valabbrev complexvalflag

  if {$complexvalflag} {
    confirmalert "Write VTK Values:  can't write complex-valued data\
                 \n\n    (1)  untick \"cpx\"\
                   \n    (2)  verify/display real data\
                   \n    (3)  try again"
    return
  }
  if ![okreplace "" \
                 "Alternate write currently displayed vertex values as:\
              \n\n    1-column, ASCII *.vtk format, POINT_DATA file\
              \n\n(surface geometry not included)" \
                 "Write VTK 1D Data File"] { return }
  setfile val [.files.val.cbx subwidget entry get]
  if ![string match *.vtk $val] {
    if ![okreplace "" "Write MGH file without *.vtk suffix?\
                   \n\nN.B.: won't be recognized on re-read" "OK"] { return }
  }
  testreplace $val write_vtk_values
}

proc valW_vtksurfvals { } {
  global val valabbrev complexvalflag

  if {$complexvalflag} {
    confirmalert "Write VTK Surf+Values:  can't write complex-valued data\
                 \n\n    (1)  untick \"cpx\"\
                   \n    (2)  verify/display real data\
                   \n    (3)  try again"
    return
  }
  if ![okreplace "" \
                 "Alternate write currently displayed vertex values as:\
              \n\n    ASCII *.vtk surf plus 1-column of POINT_DATA values\
              \n\n(surface geometry is included)" \
                 "Write VTK Surf+Data File"] { return }
  setfile val [.files.val.cbx subwidget entry get]
  testreplace $val write_vtk_surface_plus_values  ;# funct autoappends .vtk
}

proc  valW_sphimcurv { } {
  global surfext

  if {$surfext != "sphere.reg" && $surfext != "sphere"} {
    confirmalert "Reverse paint only works from sphere{.reg} surface"
    return
  }
  confirmalert "Alternate write: \"reverse paint\" CURV:\
            \n\nSample current surf .curv field to 3D vol\
              \nto make morph curvim target (no file)\
            \n\nfor REG (sphere_morph) on F3 interface"
  surf2sphim 0
  logcmd "surf2sphim 0"
}

proc valW_sphimstat { } {
  global surfext statloadedflag

  if {$surfext != "sphere.reg" && $surfext != "sphere"} {
    confirmalert "Reverse paint only works from sphere{.reg} surface"
    return
  }
  if {!$statloadedflag} {
    confirmalert "Reverse paint stat:\n\n.stat field not loaded (use R, S/V)"
    return
  }
  confirmalert "Alternate write: \"reverse paint\" STAT:\
            \n\nSample current surf .stat field to 3D vol\
              \nto make morph statim target (no file)\
            \n\nfor REG (sphere_morph) on F3 interface"
  surf2sphim 1
  logcmd "surf2sphim 1"
}

proc valW_sphimvalval2 { } {
  global surfext valloadedflag val2loadedflag

  if {$surfext != "sphere.reg" && $surfext != "sphere"} {
    confirmalert "Reverse paint only works from sphere{.reg} surface"
    return
  }
  if {!$valloadedflag} {
    confirmalert "Reverse paint val:\n\n.val field not loaded (use R)"
    return
  }
  if {!$val2loadedflag} {
    confirmalert "Reverse paint val2:\n\n.val2 field not loaded (use R, S/V)"
    return
  }
  confirmalert "Alternate write: \"reverse paint\" VAL,VAL2:\
            \n\nSample current surf .val,.val2 fields to 3D vol\
              \nto make morph realim/imagim target (no file)\
            \n\nfor REG (sphere_morph) on F3 interface"
  surf2sphim 2
  logcmd "surf2sphim 2"
  surf2sphim 3
  logcmd "surf2sphim 3"
}

proc valW_sphimvalval2baks { } {
  global surfext valbakloadedflag val2bakloadedflag

  if {$surfext != "sphere.reg" && $surfext != "sphere"} {
    confirmalert "Reverse paint only works from sphere{.reg} surface"
    return
  }
  if {!$valbakloadedflag} {
    confirmalert "Reverse paint val:\n\n.valbak field not loaded (use R)"
    return
  }
  if {!$val2bakloadedflag} {
    confirmalert "Reverse paint val2:\n\n.val2bak field not loaded (use R, S/V)"
    return
  }
  confirmalert "Alternate write: \"reverse paint\" VALBAK,VAL2BAK:\
            \n\nSample current surf .valbak,.val2bak fields to 3D vol\
              \nto make morph realim2/imagim2 target (no file)\
            \n\nfor REG (sphere_morph) on F3 interface"
  surf2sphim 4
  logcmd "surf2sphim 4"
  surf2sphim 5
  logcmd "surf2sphim 5"
}

proc valW_sphimctrls { } {
  sphimctrls
}
############################################################################
# end "val:" line no-arg button procs

proc getdijk2 {  } {
  global env subject hemi isession scandir overlayflag smoothsteps
  global label labelabbrev labeldir labelflag nmarked labelalpha

  if {$nmarked < 2} {
    confirmalert "first select at least two vertices (last 2 used)"
    return
  }
  set curv0arg ""
  if ![file exists $env(SUBJECTS_DIR)/$subject/surf/$hemi.smoothwm.H.crv] {
    confirmalert "$hemi.smoothwm.H.curv not found:\n\nusing $hemi.curv"
    update idletasks  ;# else panel hangs
    set curv0arg "--curv0 curv"
  }
  set subjectscripts $env(SUBJECTS_DIR)/$subject/scripts
  if ![file exists $subjectscripts] {
    confirmalert "subjects scripts directory not found:\
                  \n\n    $subjectscripts\
                  \n\nCreate it and try again"
    return
  }
  if ![info exists env(FSURF_DIR)] {  ;# in case user tcl script tries to run
    confirmalert "env var (MGH freesurfer install dir):\
              \n\n    FSURF_DIR\
              \n\nnot defined => can't run mris_pmake\
                \nDefine FSURF_DIR and restart tksurfer"
    return
  }
  if ![file exists $env(FSURF_DIR)/bin/mris_pmake] {
    confirmalert "Geodesic-finding binary:\
              \n\n    $env(FSURF_DIR)/bin/mris_pmake\
              \n\nnot found in MGH freesurfer\
                \nN.B.: requires freesurfer release 5.3"
    return
  }

  ## setup hemi-spec. names to cp output label to (used below), check overwrite
  set currdir [pwd]   ;# tmp change below to run mris_pmake
  set from $subjectscripts/dijk.label   ;# default output (not in help!)
  # SUBJ vs. FUNCT
  if { [string match */$subject/scripts $currdir] ||
       $scandir == "__noscandir__" || !$overlayflag } {
    set to $env(SUBJECTS_DIR)/$subject/$labeldir/$hemi-dijk.label
    set toabbrev ~/label/$hemi-dijk.label
  } else {
    set to $isession/$scandir/$hemi-dijk.label
    set toabbrev */$scandir/$hemi-dijk.label
  }
  if { [file exists $to] && ![okreplace $to] } { return }

  ## get 2 last vertices
  cd $subjectscripts
  logcmd "cd $subjectscripts" 
  print_selected_list   ;# to subject scripts dir
  logcmd "print_selected_list"
  set vlist $subjectscripts/CurrVtxList.txt
  if ![file exists $vlist] { cd $currdir; return }
  set id [open $vlist r]
  set lines [split [read -nonewline $id] "\n"] ;# nonewline: no last empty elem
  close $id
  set vtx0 [lindex $lines end-1]
  set vtx1 [lindex $lines end]

  ## mris_pmake (see also --mpmProg patchMake, --mpmProg autodijk)
  #https://mail.nmr.mgh.harvard.edu/pipermail/freesurfer/2011-April/017978.html
  #ttps://mail.nmr.mgh.harvard.edu/pipermail/freesurfer/2013-January/027543.html
  if [string match "* *" $env(SUBJECTS_DIR)] {
    puts "tksurfer.tcl: ### current SUBJECTS_DIR has space(s):"
    puts "tksurfer.tcl:  $env(SUBJECTS_DIR)"
    puts "tksurfer.tcl: ### MGH FreeSurfer5.3 mris_pmake will fail w/spaces"
    confirmalert "N.B.: MGH FreeSurfer v5.3 mris_pmake will fail if\
                \nSUBJECTS_DIR path contains spaces:\
              \n\ncurrent SUBJECTS_DIR:\
              \n\n    $env(SUBJECTS_DIR)"
  }
  set cmd "\"$env(FSURF_DIR)/bin/mris_pmake\" \
    --subject $subject \
    --hemi $hemi \
    $curv0arg \
    --mpmOverlay euclidean \
    --mpmProg pathFind \
    --mpmArgs startVertex:${vtx0},endVertex:${vtx1}"
  puts "tksurfer.tcl: $cmd"
  logcmd "$cmd"

  ## run mris_pmake cmd, catch/parse output
  catch { set lines [split [eval exec $cmd] "\n"] } err
  if { "$err" != "" && "$err" != 0 && "$err" != 1 } {
    #confirmalert "mris_pmake:\n\n$err"
    #return
    #puts "tksurfer.tcl: ### $err"  ;# normal return here/stderr, too?
  }
  foreach line $lines {
    puts "tksurfer: mris_pmake: $line"
    if [string match "Total path cost*" $line] { set len [lindex $line 4] }
  }

  ### OLD: just cp output label to std csurf format, update interface entry
  #exec cp -f $from $to
  #logcmd "exec cp -f $from $to"

  ### N.B.: mris_pmake label output file xyz from vox2ras=TkReg (not orig|curr)
  ## HOWTO get curr coords (e.g., inflated or flat) into label-to-sort
  #setfile label $from
  #read_label_to_select
  #global usecurrcoordsflag
  #set usecurrcoordsflagcurr $usecurrcoordsflag
  #set usecurrcoordsflag 1
  #write_val_selected_list_to_label  ;# overwrite w/curr surf xyz
  #set usecurrcoordsflag $usecurrcoordsflagcurr

  ## NEW: sort vertex-ordered output label file into path-ordered label
  sort_label_by_pathorder $from $to $vtx0
  logcmd "sort_label_by_pathorder $from $to $vtx0"

  ## report
  setfile label $toabbrev  ;# updates $label
  puts \
  "tksurfer: least dist along folded mesh (~geodesic): [format "%3.3f" $len] mm"
  puts "tksurfer: Wrote path-ordered label w/single line of vertices to:"
  puts "tksurfer:  $to"
  confirmalert \
    "least dist along folded mesh (~geodesic): [format "%3.3f" $len] mm"
  confirmalert \
    "Wrote path-ordered label w/single line of vertices to:\n\n    $to"

  ## display path label
  read_label_to_annot_using_col 255 255 0
  logcmd "read_label_to_annot_using_col 255 255 0"
  set labelalpha 192
  set_annot_alpha $labelalpha  ;# update interface
  logcmd "set_annot_alpha $labelalpha"
  set labelflag 1
  logcmd "set labelflag 1"
  redrawbutton

  ## if overlay, optionally insert data into label
  if {$overlayflag} {
    if ![okreplace "" "OK to insert overlay data into label?" \
        "Insert Overlay Data"] {
        confirmalert "label file contains no data (zeros)"
        return
    } else {  ;# insert data
      clear_annot                         ;# clear any previous annot
      logcmd "clear_annot"
      read_label_to_annot_using_col 255 255 0  ;# re-read label
      logcmd "read_label_to_annot_using_col 255 255 0"
      labeled_cut_clearvals 0             ;# N.B.: recut elears .val(2) fields
      logcmd "labeled_cut_clearvals 0"
      read_real_or_complex_binary_values  ;# re-read .val(2) (existing $val)
      logcmd "read_real_or_complex_binary_values"
      smooth $smoothsteps val             ;# re-smooth (existing $smoothsteps)
      logcmd "smooth $smoothsteps val"
      write_val_visible_vertices          ;# save new path label (sequential)
      logcmd "write_val_visible_vertices"
      sort_label_by_pathorder $to $to $vtx0  ;# re-sort
      logcmd "sort_label_by_pathorder $to $to $vtx0"
      restore_ripflags 2                  ;# restore surface (=INIT button)
      logcmd "restore_ripflags 2"
      redrawbutton
    }
  }

  ## restore dir
  cd $currdir
  logcmd "cd $currdir"
}

proc sort_label_by_pathorder { infile outfile vtx0 } {  ;# for single vtx path
  puts "tksurfer.tcl: sort label by path-order: infile:\ntksurfer.tcl:  $infile"
  # infile=outfile OK
  set id [open $infile r]
  set lines [split [read $id] "\n"]
  close $id
  # init
  set ord 2  ;# label file line nums, this is first data vtx line
  set vtxcnt [lindex $lines 1]
  set todo $vtxcnt
  set linecnt [expr $vtxcnt + 2]
  for {set i 2} {$i < $linecnt} {incr i} {
    set line [lindex $lines $i]
    set v($i) [lindex $line 0]
    set x($i) [lindex $line 1]
    set y($i) [lindex $line 2]
    set z($i) [lindex $line 3]
    if { $v($i) == $vtx0 } {  ;# start at vtx0
      set x0 $x($i)
      set y0 $y($i)
      set z0 $z($i)
      set order($ord) $i   ;# both indices 0-based label file line nums
      set done($i) 1       ;# rm from search list
      incr todo -1
    } else { set done($i) 0 }
  }
  # find nearest Euclidean, save to order, rm from search list, til done
  while {$todo > 0} {
    set dmin 1000.0
    for {set i 2} {$i < $linecnt} {incr i} {
      if {!$done($i)} {
        set dx [expr $x($i) - $x0]
        set dy [expr $y($i) - $y0]
        set dz [expr $z($i) - $z0]
        set d [expr sqrt( ($dx * $dx) + ($dy * $dy) + ($dz * $dz) )]
        if {$d < $dmin} { set dmin $d; set imin $i }
      }
    }
    incr ord
    set x0 $x($imin)  ;# new start
    set y0 $y($imin)
    set z0 $z($imin)
    set order($ord) $imin
    set done($imin) 1
    incr todo -1
  }
  # write path ordered label
  set id [open $outfile w 0644]
  set i [expr $linecnt - 1]
  set lastline [lindex $lines $order($i)]
  set vtx1 [lindex $lastline 0]
  for {set i 0} {$i < $linecnt} {incr i} {
    if {$i == 0} {
      puts $id "[lindex $lines 0], vtxs in pathorder: $vtx0->$vtx1"
    } elseif {$i == 1} {
      puts $id [lindex $lines 1]
    } else {
      puts $id [lindex $lines $order($i)]
    }
  }
  close $id
  puts \
    "tksurfer.tcl: path-order-sorted label: outfile:\ntksurfer.tcl:  $outfile"
}

#xxxxxxx -- 10 secs for 1 vtx to all others do/display for sanity check
#proc autodijk {  } {
#
#}

proc smoothbutton { } {
  global smoothsteps smoothtype

  smooth $smoothsteps $smoothtype
  redrawbutton
}

proc restore_second {  } {
  global flag2d

  resettransform
  make_lateral_view_second
  if {$flag2d} {
    puts "no flat second surface yet"
    prompt
  }
}

proc arrownormctrls { } {  ;# popup added to right-click on arrownorm tickbox
  global arrownormctrlswin

  if [winfo exists $arrownormctrlswin] { raise $arrownormctrlswin; return }
  set title "ARROWS/NORMALS/POINTS"
  set variablelist "whitespace \
                    arrowscale \
                    arrowline \
                    arrowheadfracauto \
                    arrowheadmin \
                    line_arrowbarbangle \
                    filled_arrowtipangle \
                    filled_arrowbarbangle \
                    whitespace \
                    arrownormflag \
                    filledarrowsflag \
                    centerarrowsflag \
                    angoffrevarrflag \
                    rmgradoutliersflag \
                    whitespace \
                    normalsflag \
                    dipolesflag \
                    edgesflag \
                    pointsflag \
                    bigcursorflag \
                    meshline \
                    pointsize"
  set arrownormctrlswin \
    [controls $title $variablelist "GRAD ARROWS -> COLOR" do_grad2col]

  # hack: fix arrowscale Return somehow bound to arrows->col action butt!
  bind $arrownormctrlswin.arrowscale.e <Return> {
    logcmd "set arrowscale $arrowscale"
    redrawbutton
  }
  # hack: internal ck window name: fix if anything added, rearranged!!
  bind $arrownormctrlswin.ck4 <ButtonRelease-1> {
    if {$flag2d} {
      confirmalert "Re-calculate gradient to see effect of this change:\
               \n\n    rmgradoutliersflag -> $rmgradoutliersflag"
    } else {
      confirmalert "no effect on 3d surf gradient (use fthresh/sfthresh)"
    }
  }
  # move up these ctrls to expose button at bottom
  set g [split [wm geometry $arrownormctrlswin] "+x"]
  wm geometry $arrownormctrlswin +[lindex $g 2]+[expr [lindex $g 3]-150]
  bind $arrownormctrlswin <ButtonRelease-3> { helpwin arrownorm }
}

proc do_grad2col { } {
  global gradvecbakflag gradvecbak3dflag reggradvecbakflag reggradvecbak3dflag
  global valbaks_cart2polarflag
  global complexvalflag overlayflag colscale fthresh fmid fslope

  if {$reggradvecbakflag || $reggradvecbak3dflag} {
    confirmalert "Convert gradient amplitude to real-valued overlay:\
              \n\nFirst untick \$reggradvecbakflag or \$reggradvecbak3dflag\
                  to uncover/verify dense gradient arrow field"
    return
  }
  if {!$gradvecbakflag && !$gradvecbak3dflag} {
    confirmalert "Convert gradient amplitude to real-valued overlay:\
              \n\n    ...no gradient loaded/visible\
              \n\nFirst compute gradient (on flat patch) with \"GR\""
    return
  }
  if {$valbaks_cart2polarflag} {
    confirmalert "Convert gradient to real-valued overlay:\
              \n\nN.B.: Cartesian gradient already converted to polar\
              \n\n    ...first reload a fresh gradient w/GR"
    return
  }

  if ![okreplace "" " OK to display shaded gradient amplitude?\n\n\
       (1)  swap gradient to top of complex stack\n\
       (2)  conv gradient x,y -> ang,amp (goes to stack bot)\n\
       (3)  swap output back to top\n\
       (4)  swap amp and angle (amp -> \'real-value\' position)\n\
       (5)  turn off gradient arrows\n\
       (6)  adjust colorscale" \
       "Show Gradient Amp As Shading"] {
    confirmalert "gradient left in stack bottom"
    return
  } else {
    swap_valval2_valbakval2bak
    logcmd "swap_valval2_valbakval2bak"
    compute_angles_vals_to_baks
    logcmd "compute_angles_vals_to_baks"
    swap_valval2_valbakval2bak
    logcmd "swap_valval2_valbakval2bak"
    swap_val_val2
    logcmd "swap_val_val2"
    set gradvecbakflag 0
    logcmd "set gradvecbakflag 0"
    set gradvecbak3dflag 0
    logcmd "set gradvecbak3dflag 0"
    set complexvalflag 0
    logcmd "set complexvalflag 0"
    set overlayflag 1
    logcmd "set overlayflag 1"
    set colscale 6
    logcmd "set colscale 6"
    set fthresh 0.0
    logcmd "set fthresh 0.0"
    set fmid 0.08
    logcmd "set fmid 0.08"
    set fslope 10.0
    logcmd "set fslope 10.0"
    redrawbutton
  }
}

proc fillbutton { } {
  global nmarked flag2d filled_currarea filled_origarea
  global annotloadedflag labelflag erodingfillflag

  if {$nmarked > 0 && $annotloadedflag} {
    if {$erodingfillflag} {
       set paddingfillmsg \
               "\n\nN.B.: eroding fill is set: so FILL'd regions(s)\
                  \nwill NOT share border vertices with adjoining labels\
                \n\n(if you want this, first untick \"er\")"
    } else {
       set paddingfillmsg \
               "\n\nN.B.: non-eroding fill is set: so FILL'd region(s)\
                  \nwill share border vertices with adjoining labels\
                \n\n(to prevent this, first tick \"er\")"
    }
    if {$labelflag} {  ;# if visible, warn/continue, else block
      if ![okreplace "" \
                  "Currently loaded label/annotation will constrain FILL!\
                \n\nThat may be your intent (FILL up to a label)\
                \n\nNote, however, if your seed is *inside* a label/annot,\
                  \nFILL will only select the seed vertex.\
                \n\nYou can clear all labels/annots with:\
                \n\n    CLR on \"label:\" line\
                \n\nand try FILL again \
                   $paddingfillmsg" \
                "FILL Anyway"] { return }
    } else {
      confirmalert "Hidden label/annotation will constrain FILL!!\
                \n\nDo one of the following:\
                \n\n    (1) Display label(s) (tick left of \"label:\")\
                  \n           *or*\
                  \n    (2) Clear label(s) (CLR on \"label:\" line)\
                \n\nand try FILL again"
      return
    }
  }

  if {$nmarked < 1} {
    confirmalert "FILL (floodfill_marked_patch 0):\
              \n\nFirst select one or more vertices\
              \n\n(next panel: previous sum)"
  }
  floodfill_marked_patch 0
  logcmd "floodfill_marked_patch 0"
  update idletasks
  if {$flag2d} {
    confirmalert "Filled Surface Area:\n\
   \n  curr surf:  [format "%3.1f" $filled_currarea] mm^2  (est. undef'd bord)\
   \n  orig surf:  [format "%3.1f" $filled_origarea] mm^2  (from area file)"
  } else {
    confirmalert "Filled Surface Area:\n\
   \n  curr surf:  [format "%3.1f" $filled_currarea] mm^2\
   \n  orig surf:  [format "%3.1f" $filled_origarea] mm^2  (from area file)"
  }
  #after 100
  redrawbutton
}

proc roibutton { } {
  global nmarked erodingfillflag complexvalflag statmaskampflag truncphaseflag
  global filled_currarea filled_origarea flag2d fthresh sfthresh
  global dilatingfillflag ffont ffontb truncphasemin truncphasemax overlayflag
  global statANDhypotflag statANDrealflag labelflag annotloadedflag

  if {$nmarked < 1} {
    confirmalert "ROI fill (floodfill_marked_patch <1-5>):\
              \n\nfirst select one or more vertices"
    return
  }
  if {!$overlayflag} {
    confirmalert "ROI fill: no overlay data visible\
              \n\nFirst load some, or display loaded by ticking \"ovlay\""
    return
  }
  if {$complexvalflag && $statANDhypotflag && $statANDrealflag} { ;# silent fix
    set statANDrealflag 0
    logcmd "set statANDrealflag 0"
  }

  # warn annot constrains fill
  if {$annotloadedflag} {
    if {$labelflag} {  ;# if visible, warn/continue, else block
      if ![okreplace "" \
                  "Currently loaded label/annotation will constrain ROI!\
                \n\nThat may be your intent (ROI up to a label/annot)\
                \n\nNote, however, if your seed is *inside* a label/annot,\
                  \nROI will only select the seed vertex.\
                \n\nYou can clear all labels/annots with:\
                \n\n    CLR on \"label:\" line\
                \n\nand try ROI again" \
                "Fill ROI Anyway"] { return }
    } else {
      confirmalert "Hidden label/annotation will constrain ROI!\
                \n\nDo one of the following:\
                \n\n    (1) Display label(s) (tick left of \"label:\")\
                  \n           *or*\
                  \n    (2) Clear label(s) (CLR on \"label:\" line)\
                \n\nand try ROI again"
      return
    }
  }

  # force choose: use just mask or mask AND real amp
  if {$statmaskampflag && !$complexvalflag} {
    set resp [okreplace "" \
                "StatMask loaded over Real-Valued data:\
             \n\nChoose one:\
             \n\n    ROI respects only stat thresh\
               \n    ROI respects stat thresh AND real amp thresh" \
                "RealAmp AND Stat" "Just Stat"]
    if {$resp == 0} { return }
    if {$resp == 1} { set statANDrealflag 1 }  ;# right button
    if {$resp == 2} { set statANDrealflag 0 }  ;# middle button
    logcmd "set statANDrealflag $statANDrealflag"
  }
  # force choose: use just mask or mask AND cmplxamp
  if {$statmaskampflag && $complexvalflag} {
    set resp [okreplace "" \
                "StatMask loaded over Complex-Valued data:\
             \n\nChoose one:\
             \n\n    ROI respects only stat thresh\
               \n    ROI respects stat thresh AND complex amp thresh" \
                "CmplxAmp AND Stat" "Just Stat"]
    if {$resp == 0} { return }
    if {$resp == 1} { set statANDhypotflag 1 }  ;# right button
    if {$resp == 2} { set statANDhypotflag 0 }  ;# middle button
    logcmd "set statANDhypotflag $statANDhypotflag"
  }


  # wait til after all returns
  set savedilatingfillflag $dilatingfillflag
  set saveerodingfillflag $erodingfillflag
  set dilatingfillflag 0
  logcmd "set dilatingfillflag 0"
  set erodingfillflag 1
  logcmd "set erodingfillflag 1"
  .shrink.cut.ck config -text er -font $ffont
  update idletasks


### wordy, but doesn't tell which used, final okreplace message enough
#  confirmalert "Fill ROI: precendence of operations:\
#          \n\n    (0) if statANDhypot ON: STAT>\$sfthresh && HYPOT>\$fthresh\
#            \n    (1) if statANDreal ON: STAT>\$sfthresh && HYPOT>\$fthresh\
#            \n    (2) if mask on, use:            STAT > \$sfthresh\
#            \n    (3) if truncphase, use:      COMPLEX PHASE within limits\
#            \n    (4) if complex data, use:   COMPLEX AMP > \$fthresh\
#            \n    (5) if real data, use:           REAL AMP > \$fthresh\
#          \n\nN.B.: first wins, other criteria ignored"

  if {$statANDhypotflag} {
    if ![okreplace "" \
          "Fill ROI: use STAT AND COMPLEX AMP (statANDhypot ON):\
       \n\nfill connected vertices w/stat>$sfthresh && hypot>$fthresh" \
          "OK" none none "PROCEED"] { return }
    floodfill_marked_patch 5     ;# stat AND hypot (overrides just stat)
    logcmd "floodfill_marked_patch 5"
  } elseif {$statANDrealflag} {
    if ![okreplace "" \
          "Fill ROI: use STAT AND REAL AMP (statANDreal ON):\
       \n\nfill connected vertices w/stat>$sfthresh && realamp>$fthresh" \
          "OK" none none "PROCEED"] { return }
    floodfill_marked_patch 6     ;# stat AND real (overrides just stat)
    logcmd "floodfill_marked_patch 6"
  } elseif {$statmaskampflag} {
    if ![okreplace "" \
          "Fill ROI: use STAT (statmask ON -> fthresh ignored):\
       \n\nfill connected vertices w/stat > $sfthresh" \
          "OK" none none "PROCEED"] { return }
    floodfill_marked_patch 1     ;# to stat = sfthresh (overrides complex)
    logcmd "floodfill_marked_patch 1"
  } elseif {$truncphaseflag} {
    if ![okreplace "" \
          "Fill ROI: use CMPLX PHASE (cmplx w/statmask OFF, truncphase ON):\
       \n\nfill connected vertices w/phase in trunc limits\
            ($truncphasemin - $truncphasemax)" \
          "OK" none none "PROCEED"] { return }
    floodfill_marked_patch 4     ;# within truncphase
    logcmd "floodfill_marked_patch 4"
  } elseif {$complexvalflag} {
    if ![okreplace "" \
          "Fill ROI: use COMPLEX AMP (cmplx w/statmask ON, truncphase OFF):\
       \n\nfill connected vertices w/amp > $fthresh" \
          "OK" none none "PROCEED"] { return }
    floodfill_marked_patch 3     ;# to complexamp = fthresh
    logcmd "floodfill_marked_patch 3"
  } else { ;# real

    if ![okreplace "" \
          "Fill ROI: use REAL AMP (statmask OFF, truncphase OFF):\
       \n\nfill connected vertices w/val > $fthresh" \
          "OK" none none "PROCEED"] { return }
    floodfill_marked_patch 2     ;# to val = fthresh
    logcmd "floodfill_marked_patch 2"
  }
  set erodingfillflag $saveerodingfillflag
  logcmd "set erodingfillflag $saveerodingfillflag"
  set dilatingfillflag $savedilatingfillflag
  logcmd "set dilatingfillflag $savedilatingfillflag"
  if {!$erodingfillflag && $dilatingfillflag} {
    .shrink.cut.ck config -text dl -font $ffontb
  }
  confirmalert "Filled Surface Area:\n\
    \n  curr surf:  [format "%3.1f" $filled_currarea] mm^2\
    \n  orig surf:  [format "%3.1f" $filled_origarea] mm^2  (from area file)"
  redrawbutton
}

proc nearestbuttons { filltype criterion } {
  global nmarked filled_currarea filled_origarea fillneartype
  global searchlightuniqflag numafteruniqflag pointsflag

  set fillneartype $filltype
  logcmd "set fillneartype $filltype"
  if {$nmarked < 1} {
    set msg ""
    if {$filltype == 0} {set msg "$criterion vertices"}
    if {$filltype == 1} {set msg "vertices\nup to area of $criterion mm^2"}
    if {$filltype == 2} {set msg "vertices\nup to radius of $criterion mm"}
    if {$msg != ""} {confirmalert "first select vertex to pick nearest $msg"}
    return
  }
  if {$filltype == 2 && $criterion > 200} {
    confirmalert "radius above 200 mm probably includes entire surface"
  }
  fill_nearest_vertices $filltype $criterion
  logcmd "fill_nearest_vertices $filltype $criterion"
  if {$searchlightuniqflag} {
    if {$filltype == 0 && $numafteruniqflag} {
      confirmalert "N.B.: turned \$pointsflag ON to view sparse/uniq label\
                  \n(middle-click MESH to toggle pointsflag)\
                \n\nN.B.: sparse/uniq label with $criterion vertices made by\
                  \nexpanding label area beyond standard/dense\
                  \n${criterion}-count label"
    } else {
      confirmalert "N.B.: turned \$pointsflag ON to view sparse/uniq label\
                  \n(middle-click MESH to toggle pointsflag)\
                \n\nN.B.: sparse/uniq label made by removing non-uniq vtxs\
                  \nfrom standard/dense $criterion-count label"
    }
    set pointsflag 1
    logcmd "set poinstflag 1"
  } else {
    confirmalert "Filled Surface Area:\n\
      \n  curr surf:  [format "%3.1f" $filled_currarea] mm^2\
      \n  orig surf:  [format "%3.1f" $filled_origarea] mm^2  (from area file)"
  }
  redrawbutton
}

proc fixdecname { name1 name2 op } {
  global dec decabbrev dip_spacing hemi

  # trace execs in context of invoking code (global here so no uplevel setfile)
  setfile dec $decabbrev                                ;# read curr
  if {$dip_spacing > 0.999} {
    set dectail [format "%s-%d.dec" $hemi $dip_spacing] ;# fix tail one way
  } else {
    set dectail [format "%s-%3.2f.dec" $hemi $dip_spacing] ;# fix tail other way
  }  
  set dec [file dirname $dec]/$dectail                 ;# mod abs name
  setfile dec $dec                                     ;# update abbrev
}

#proc fixcolscale { varName index op } { }  ;# old trace syntax example
proc fixcolscale { name1 name2 op } {
  global colscale complexvalflag overlayflag fieldsignflag
  global minstatcolscale maxstatcolscale colscalebarflag
  global truncphasemin truncphasemax fmid fthresh
  global valloadedflag val2loadedflag zerosymmfadeflag

  set origfieldsignflag $fieldsignflag    ;# for log at end
  set origcomplexvalflag $complexvalflag  ;# for log at end
  set fieldsignflag 0
  # trace not trig at startup, so these won't override csurf panel settings
  if {$colscale == 0}  {set complexvalflag 1}  ;# w1: eccen/polar wheel (cplx)
  if {$colscale == 1}  {                       ;# ht: heat (both!)
    set truncphasemin 0.5  ;# emulate orig hard-coded trunc angle>0.5
    set truncphasemax 0.999
    set complexvalflag 1
  }
  if {$colscale == 2}  {set complexvalflag 1}  ;# ##; cyan/blue (both!)
  if {$colscale == 3}  {set complexvalflag 1}  ;# ##: blue/green/red (both!)
  if {$colscale == 4}  {set complexvalflag 1}  ;# bi: red/green two cond (cplx)
  if {$colscale == 5}  {set complexvalflag 1}  ;# ##: gray (both!)
  if {$colscale == 6}  {set complexvalflag 0}  ;# BR: blu/wht, red/wht (real)
  if {$colscale == 7}  {set complexvalflag 0}  ;# ##: grn/red, ~0:mag/cyan(real)
  if {$colscale == 8}  {set complexvalflag 1}  ;# w2: RYGB wheel (cplx)
  if {$colscale == 9}  {                       ;# fs: EXTRA_SIGNED (R/G real)
    set complexvalflag 0  
    set fieldsignflag 1  ;# fs: special: overrides colscale, data: .fs not .val
  }
  if {$colscale == 10} {set complexvalflag 0}  ;# ##: B/G/R (real)
  if {$colscale == 11} {set complexvalflag 0}  ;# BRy: blu/cyan, red/yel (real)
  if {$colscale == 12} {set complexvalflag 0}  ;# lt: real color LUT
  if {$colscale == 13} {set complexvalflag 1}  ;# lta: complex amp color LUT
  if {$colscale == 14} {                       ;# ltw: complex pha color LUT
    set complexvalflag 1
    set zerosymmfadeflag 0
    logcmd "set zerosymmfadeflag 0"
    set botedgelutflag 1   ;# TODO: rm when code generalized
    logcmd "set botedgelutflag 1"
  }
  if {$colscale == 15} {                       ;# jet: real MATLAB jet-like
    if {$valloadedflag && $val2loadedflag} {
      set complexvalflag 1
      set truncphasemin $fthresh
      logcmd "set truncphasemin $fthresh"
      set truncphasemax [expr $fmid * 4]
      logcmd "set truncphasemax [expr $fmid * 4]"
      set zerosymmfadeflag 0
      logcmd "set zerosymmfadeflag 0"
      confirmalert \
        "N.B.: viewing complex data amplitude with signed real colscale"
    } else {
      set complexvalflag 0
      set fthresh 0.0   ;# begin neg/pos vis
      logcmd "set fthresh 0.0"
      set fmid 0.0
      logcmd "set fmid 0.0"
      set truncphasemin -5.0
      logcmd "set truncphasemin -5.0"
      set truncphasemax 5.0
      logcmd "set truncphasemax 5.0"
      set zerosymmfadeflag 1
      logcmd "set zerosymmfadeflag 1"
    }
  } 
  if {$colscale == 16} {set complexvalflag 1}  ;# w3: mag-bl-cya-gr-yel-rd mirr
  if {$colscale == 17} {                       ;# vd: Caret "videen-style"
    set zerosymmfadeflag 0
    logcmd "set zerosymmfadeflag 0"
    if {$valloadedflag && $val2loadedflag} {
      set complexvalflag 1
      set fthresh 0.0
      logcmd "set fthresh 0.0"
      set truncphasemin $fthresh
      logcmd "set truncphasemin $fthresh"
      set truncphasemax [expr $fmid * 4]
      logcmd "set truncphasemax [expr $fmid * 4]"
      confirmalert "N.B.: viewing complex data amplitude with real colscale"
    } else {
      set complexvalflag 0
      set fthresh -1.0    ;# begin 0-1
      logcmd "set fthresh -1.0"
      set truncphasemin 0.0
      logcmd "set truncphasemin 0.0"
      set truncphasemax 1.0
      logcmd "set truncphasemax 1.0"
    }
  }
  if {$colscale == 18} {set complexvalflag 1}  ;# w4: fred tono

  # force re-autoscale if change color scale
  set minstatcolscale 0.0
  set maxstatcolscale 0.0
  logcmd "set colscale $colscale"
  if {!$colscalebarflag} {  ;# only update butt if scalebar off
    if {$complexvalflag && $overlayflag} {
      .draw.mesh.rect.arect.bu config -text "disk" -width 4
    } else {
      .draw.mesh.rect.arect.bu config -text "bar" -width 4
    }
  }
  # just report changed
  if {$origcomplexvalflag != $complexvalflag} {
    logcmd "set complexvalflag $complexvalflag"
  }
  if {$origfieldsignflag != $fieldsignflag} {
    logcmd "set fieldsignflag $fieldsignflag"
  }
}

proc checkrealcolscale { } {
  global colscale

  if { $colscale != 6  && $colscale != 11 && $colscale != 12 && 
       $colscale != 15 && $colscale != 17 } {  ;# only reset not-real
    set colscale 11  ;# BRy
    logcmd "set colscale 11"
  }
}

proc checkfthreshfmidBRy { } {
  global colscale fthresh fmid
  if {$colscale == 11 && $fthresh > $fmid} {
    confirmalert "ColorScale BRy:  fthresh should not exceed fmid\
                \n  (currently:  fthresh=$fthresh, fmid=$fmid)\n\
                \nBRy colscale is unique in that fthresh and fmid\
                \nrefer to different ranges of data:\n\
                \n  fthresh:  lower (abs) data val red (blue) cutoff\
                \n  fmid:  higher data val for shift to yellow (cyan)"
  }
}

#proc var2log { name1 name2 op } {
#  global $varName
#  logcmd "set $varName [set $varName]"
#}

proc reloadarea { } {
  global hemi areaflag area areaabbrev insurf insurfabbrev

  logcmd "set areaflag $areaflag"
  if {$areaflag} {
    if ![okreplace "" \
       "new areaflag = 1\
       \n\nOK to recalc and load origara\
       \nfor entire surface?\
       \n\nN.B.: medial cut may have non-zero area" \
       "Calc/Re-Load OrigArea"] {
      confirmalert "origarea not touched"
      return
    }
    set currinsurf $insurf
    setfile insurf ~/surf/$hemi.white
    if ![file exists $insurf] {
      confirmalert "surf:\n\n    $insurf\n\nnot found"
      return
    }
    read_binary_surface
    logcmd "read_binary_surface"
    redrawbutton
    set currarea $area
    setfile area $hemi.area.tmp
    write_binary_areas
    logcmd "write_binary_areas"
    read_binary_areas
    logcmd "read_binary_areas"
    exec rm $area
    logcmd "exec rm $area"
    setfile insurf $currinsurf
    read_binary_surface
    setfile area $hemi.area   ;# set back to def
    redrawbutton
  } else {  ;# restore def init
    if ![okreplace "" \
       "new areaflag = 0\
        \n\nOK to restore default origarea\
        \nfor entire surface?\
        \n\nN.B.: medial cut may have zero area" \
       "Re-Load OrigArea"] {
      confirmalert "origarea not touched"
      return
    }
    setfile area ~/surf/$hemi.area
    read_binary_areas
    logcmd "read_binary_areas"
    redrawbutton
  }
}

proc startstopshrink { steps cycles {normareaflag 0} } {
  global runshrinkflag

  if {!$runshrinkflag} {
    set runshrinkflag 1
    if {$normareaflag} {confirmalert "normalize area each cycle (for inflate)"}
    runshrink $steps $cycles $normareaflag
  } else {
    set runshrinkflag 0
  }
}

proc runshrink { steps cycles normareaflag } {
  global chkselfintflag runshrinkflag
  global runbgcol runactbgcol bgcol actbgcol

  set allowintr 1
  .shrink.head.aSHRINK.bu config -text SH:0000 \
    -background $runbgcol -activebackground $runactbgcol
  for {set cyc 0} {$cyc < $cycles} {incr cyc} {
    shrink $steps
    logcmd "shrink $steps"
    if {$allowintr} {
      update           ;# allow startstopshrink to run simul
    } else {
      update idletasks ;# just purple the button, update reps
    }
    set currcyc [expr $cyc+1]
    set currstep [expr $currcyc*$steps]
    set total [expr $cycles*$steps]
    puts "tksurfer.tcl: cycle $currcyc: ($currstep of $total steps)"
    .shrink.head.aSHRINK.bu config -text SH:[format "%04d" $currstep]
    if {$normareaflag} { normalize_area; logcmd "normalize_area" }
    redrawbutton
    if {!$runshrinkflag && $allowintr} { break }
  }
  if {$chkselfintflag} { write_self_images; logcmd "write_self_images" }
  .shrink.head.aSHRINK.bu config -text "SHRINK" \
     -background $bgcol -activebackground $actbgcol
  set runshrinkflag 0
}

proc startstopmorph { steps cycles } {
  global runmorphflag surfext wcrv wsta wcpx
  global curvimloadedflag statimloadedflag realimloadedflag imagimloadedflag

  if {$surfext != "sphere.reg" && $surfext != "sphere"} {
    confirmalert "REG (sphere_morph) only works with sphere{.reg} surface"
    return
  }
  if {$wcrv != 0.0 && !$curvimloadedflag} {
    confirmalert "REG (sphere_morph): curv im not loaded\
              \n\nUse \"val:\" line, Shift-Middle-\"W\" (surf2sphim 0)"
    return
  }
  if {$wsta != 0.0 && !$statimloadedflag} {
    confirmalert "REG (sphere_morph): stat im not loaded\
              \n\nUse \"val:\" line, Shift-Right-\"W\" (surf2sphim 1)"
    return
  }
  if {$wcpx != 0.0} {
    if {!$realimloadedflag} {
      confirmalert "REG (sphere_morph): real im not loaded\
          \n\nUse \"val:\" line Shift-Left-\"W\" (surf2sphim 2, surf2sphim 3)"
      return
    }
    if {!$imagimloadedflag} {
      confirmalert "REG (sphere_morph): real im not loaded\
          \n\nUse \"val:\" line, Shift-left-\"W\" (surf2sphim 2, surf2sphim 3)"
      return
    }
  }
  if {!$runmorphflag} {
    set runmorphflag 1
    runmorph $steps $cycles
  } else {
    set runmorphflag 0
  }
}

proc runmorph { steps cycles } {
  global chkselfintflag runmorphflag
  global runbgcol runactbgcol bgcol actbgcol

  set allowintr 1
  .shrink.head.aREG.bu config -text 0000 \
    -background $runbgcol -activebackground $runactbgcol
  for {set cyc 0} {$cyc < $cycles} {incr cyc} {
    sphere_morph $steps
    logcmd "sphere_morph $steps"
    if {$allowintr} {
      update           ;# allow startstopmorph to run simul
    } else {
      update idletasks ;# just purple the button, update reps
    }
    set currcyc [expr $cyc+1]
    set currstep [expr $currcyc*$steps]
    set total [expr $cycles*$steps]
    puts "tksurfer.tcl: cycle $currcyc: ($currstep of $total steps)"
    .shrink.head.aREG.bu config -text [format "%04d" $currstep]
    redrawbutton
    if {!$runmorphflag && $allowintr} { break }
  }
  .shrink.head.aREG.bu config -text "REG" \
     -background $bgcol -activebackground $actbgcol
  set runmorphflag 0
}

proc chkcleargradamp { } {
  global MRIflag chkgradampflag

  if {$MRIflag && $chkgradampflag} {
    if ![okreplace "" \
       "OK to recalculate/rewrite stale gradient amplitude?" \
       "Re-Calculate/Write Gradient Amplitude"] {
      confirmalert "Gradient amplitude buffer/images not touched"
      return
    } else { calc_gradamp; logcmd "calc_gradamp" }
  }
}

proc chkclearself { } {
  global MRIflag chkselfintflag selfintersectloaded

  if {$MRIflag && $chkselfintflag && $selfintersectloaded} {
    if ![okreplace "" \
       " OK to clear stale self-intersect buffer?\n\n\
         (to save it, Cancel, and do \"self: W\")" \
         "Clear Self-Intersect Buffer"] {
      confirmalert "Self-intersect buffer not cleared"
      return
    } else { clear_selfintersect; logcmd "clear_selfintersect" }
  }
}

proc chkwritefillim { } {
  global fillim fillimloaded onemgzfileloaded

  if {!$onemgzfileloaded} {
    confirmalert "No mgz file has yet been loaded:\
              \n\nFirst load example mgz with desired resolution\
                \nusing \"R\" on \"im:\" line to define MGH header values"
    return
  } elseif {!$fillimloaded} {
    confirmalert "Fill images not yet loaded:\
              \n\nFirst click FILL3d to fill surface\
                \n(after adjusting parms to left of button)"
    return
  } else {
    testreplace $fillim write_fill_images
    logcmd "write_fill_images"
  }
}

proc select_val { combo value } {   ;# tixcombo appends entry value
  after 100 "$combo subwidget entry xview moveto 1"
}

proc select_val3d { combo value } {   ;# tixcombo appends entry value
  after 100 "$combo subwidget entry xview moveto 1"
}

proc listcmd_rgb { combo } {
  global isession hemi rgbdir

  set allrgblist [lsort [glob -nocomplain $isession/$rgbdir/*.rgb]]
  set alltiflist [lsort [glob -nocomplain $isession/$rgbdir/*.tiff]]
  set lhrgblist [lsort [glob -nocomplain $isession/$rgbdir/*-lh-*.rgb]]
  set lhtiflist [lsort [glob -nocomplain $isession/$rgbdir/*-lh-*.tiff]]
  set rhrgblist [lsort [glob -nocomplain $isession/$rgbdir/*-rh-*.rgb]]
  set rhtiflist [lsort [glob -nocomplain $isession/$rgbdir/*-rh-*.tiff]]
  if {$hemi == "rh"} {set rlist "$rhrgblist $rhtiflist $lhrgblist $lhtiflist"}
  if {$hemi == "lh"} {set rlist "$lhrgblist $lhtiflist $rhrgblist $rhtiflist"}
  set abbrevlist ""
  foreach rgb $rlist {  ;# vs. setfile (clogs log)
    set abbrevlist "$abbrevlist */$rgbdir/[file tail $rgb]"
  }
  foreach rgb "$allrgblist $alltiflist" {
    set found 0
    foreach rgbdone $rlist {
      if {"$rgbdone" == "$rgb"} { set found 1 }
    }
    if {!$found} {set abbrevlist "$abbrevlist */$rgbdir/[file tail $rgb]"}
  }
  $combo subwidget listbox delete 0 end
  foreach abbrev $abbrevlist { $combo insert end $abbrev }
  #after 100 "$combo subwidget entry xview moveto 1" ;#final sel/trace override
}

proc select_rgb { combo value } {   ;# tixcombo appends entry value
  ##N.B.: works here, but obscures informative *beginning* of rgbname
  #after 100 "$combo subwidget entry xview moveto 1"
}

proc save_rgb_named { name } {   ;# wrap for interface update, used by scripts
  global rgb named_rgbdir rel_rgbname

  if ![checknospaces $name] { return }
  logcmd "save_rgb_named $name"
  set rel_rgbname $name                            ;# cp arg->global for uplevel
  uplevel #0 {setfile rgb $named_rgbdir/$rel_rgbname} ;# echo cfunc; fix abbrev
  save_rgb_named_orig $rel_rgbname                 ;# cfunc
}

proc dontsave_rgb_named { name } {  ;# just interface update
  global rgb named_rgbdir rel_rgbname
  set rel_rgbname $name
  uplevel #0 {setfile rgb $named_rgbdir/$rel_rgbname}
}

proc showrgbs { } {
  global isession hemi rgbdir

  set allrgblist [lsort [glob -nocomplain $isession/$rgbdir/*.rgb]]
  set alltiflist [lsort [glob -nocomplain $isession/$rgbdir/*.tiff]]
  set lhrgblist [lsort [glob -nocomplain $isession/$rgbdir/*-lh*.rgb]]
  set lhtiflist [lsort [glob -nocomplain $isession/$rgbdir/*-lh*.tiff]]
  set rhrgblist [lsort [glob -nocomplain $isession/$rgbdir/*-rh*.rgb]]
  set rhtiflist [lsort [glob -nocomplain $isession/$rgbdir/*-rh*.tiff]]
  set fmtlist "CURRENT SAVED BITMAPS (both hemis)\n\n"
  set fmtlist "$fmtlist \
    3D name format: \[scannum\]-\[scantype\]-\[hemi\]-\[surf\]-\[view\].tiff\n"
  set fmtlist "$fmtlist \
    flat name format: \[scannum\]-\[scantype\]-\[hemi\]-\[patch\].tiff\n"
  set fmtlist "$fmtlist\n  ==> rh <==\n"
  foreach rgb "$rhrgblist $rhtiflist" {set fmtlist "$fmtlist[file tail $rgb]\n"}
  set fmtlist "$fmtlist\n  ==> lh <==\n"
  foreach rgb "$lhrgblist $lhtiflist" {set fmtlist "$fmtlist[file tail $rgb]\n"}
  set fmtlist "$fmtlist\n  ==> other <==\n"
  foreach rgb "$allrgblist $alltiflist" {
    set found 0
    foreach rgbdone "$rhrgblist $rhtiflist $lhrgblist $lhtiflist" {
      if {"$rgbdone" == "$rgb"} { set found 1 }
    }
    if {!$found} {set fmtlist "$fmtlist[file tail $rgb]\n"}
  }

  helpwin "$fmtlist" 57 25 varnotfile
}

proc save_rgb_checkfirst { } { ;# tksurf2000 LINUXexit/IRIXcrash, now promoted
  global env subject isession rgb rgbdir tiffoutflag

  # block attempt to use spaces in name
  if ![checknospaces $rgb] { return }

  # check if trying for rgbdir in SUBJECTS_DIR, ask autocreate
  set testrgbdir  [file tail [file dirname $rgb]]
  set testsub     [file tail [file dirname [file dirname $rgb]]]
  set testsubdir  [file dirname [file dirname [file dirname $rgb]]]
  if { $testrgbdir == $rgbdir && \
       $testsub == $subject && \
       $testsubdir == $env(SUBJECTS_DIR) && \
       ![file exists $env(SUBJECTS_DIR)/$subject/$rgbdir] } {
    if ![okreplace "" "OK to create \"rgb\" directory inside:\n\
                       \n    $env(SUBJECTS_DIR)/$subject\n\n\
                       to save image in?" "Create"] {
      confirmalert "image not saved"
      return
    }
    exec mkdir $env(SUBJECTS_DIR)/$subject/$rgbdir
  }

  # check if trying for rgbdir in FUNCTIONALS_DIR, ask autocreate
  set testrgbdir  [file tail [file dirname $rgb]]
  set testsess    [file tail [file dirname [file dirname [file dirname $rgb]]]]
  set testsessdir \
               [file dirname [file dirname [file dirname [file dirname $rgb]]]]
  if { $testrgbdir == $rgbdir && \
       $testsess == [file tail [file dirname $isession]] && \
       $testsessdir == $env(FUNCTIONALS_DIR) && \
       ![file exists $isession/$rgbdir] } {  ;# session is full abs path
    if ![okreplace "" "OK to create \"rgb\" directory inside:\n\
                       \n    $isession\n\n\
                       to save image in?" "Create"] {
      confirmalert "image not saved"
      return
    }
    exec mkdir $isession/$rgbdir
  }

  # check suffix
  if {$tiffoutflag} {
    if { ![string match *.tiff $rgb] && ![string match *.TIFF $rgb] &&
         ![string match *.tif $rgb] && ![string match *.TIF $rgb] } {
      confirmalert "bad suffix (must be *.tiff or *.tif)"
      return
    }
  } else {
    if { ![string match *.rgb $rgb] && ![string match *.RGB $rgb] &&
       ![string match *.sgi $rgb] && ![string match *.SGI $rgb] } {
      confirmalert "bad suffix (must be *.rgb or *.sgi)"
      return
    }
  }

  # check can write
  if ![canwriteormakefile $rgb] {
    confirmalert "Permissions don't allow write/create $rgb"
    return
  }

  save_rgb  ;# Linux: cfunc, IRIX/Octane: overidden w/scrsave at end
}

proc checkreadlabeldir { } {
  global label

  set fulllabeldir [file dirname $label]
  if ![file exists $fulllabeldir] {
    confirmalert "Label dir:\n\n    $fulllabeldir\n\nDoesn't exist.
                  \n\nIf label path is abbreviated, verify correct use:\
                  \n\n    ~ (tilde) means subject-name dir\
                    \n    * (star) means session-name dir (incl's \"image\")"
    return 0
  }
  return 1
}

proc checkwritelabeldir { } {
  global env subject label labeldir

  # check if trying for non-existent labeldir in SUBJECT_DIR, ask autocreate
  set testlabdir  [file tail [file dirname $label]]
  set testsub     [file tail [file dirname [file dirname $label]]]
  set testsubdir  [file dirname [file dirname [file dirname $label]]]
  if { $testlabdir == $labeldir && \
       $testsub == $subject && \
       $testsubdir == $env(SUBJECTS_DIR) && \
       ![file exists $env(SUBJECTS_DIR)/$subject/$labeldir] } {
    if ![okreplace "" "OK to create \"label\" directory inside:\n\
                       \n    $env(SUBJECTS_DIR)/$subject\n\n\
                       to save label in?" "Create"] {
      confirmalert "label dir not created"
      return 0
    }
    exec mkdir $env(SUBJECTS_DIR)/$subject/$labeldir
  }

  # check labeldir exists (maybe non-standard, maybe autocreate above failed)
  set fulllabeldir [file dirname $label]
  if ![file exists $fulllabeldir] {
    confirmalert "Label dir:\n\n    $fulllabeldir\
                  \n\nDoesn't exist.  Create it, and try again.\
                  \n\nN.B.: if label path is abbreviated, verify correct use:\
                  \n\n    ~ (tilde) means subject-name dir\
                    \n    * (star) means session-name dir (incl's \"image\")"
    return 0
  }

  # final write check
  if ![canwriteormakefile $label] {
    confirmalert "Permissions don't allow write/create $label"
    return 0
  }
  return 1
}

proc checklabelfile { } {  ;# 0=fail/mismatch, 1=real, 2=complex
  global label complexvalflag

  if ![file exists $label] {
    confirmalert "Label file:\n\n    $label\n\nnot found"
    return 0
  }
  set id [open $label r]
  set lines [split [read $id 1000] "\n"]  ;# in case long first comment line
  close $id
  set argcnt [llength [concat [split [lindex $lines 2]]]]
  if {$argcnt != 5 && $argcnt != 6} {
    confirmalert "First data line of label file doesn't have 5 or 6 args:\
              \n\n    [lindex $lines 2]\
              \n\n. . . quitting"
    return 0
  }
  if {$argcnt == 5 && $complexvalflag == 1} {
    confirmalert "Won't read real-valued data file (5 args/line), e.g.:
              \n\n    [lindex $lines 2]\
              \n\nas if it was complex\
              \n\nUntick the \"cpx\" checkbox and try again"
    return 0
  }
  if {$argcnt == 6 && $complexvalflag == 0} {
    confirmalert "Won't read complex-valued data file (6 args/line), e.g.:\
              \n\n    [lindex $lines 2]\
              \n\nas if it was real\
              \n\nTick the \"cpx\" checkbox and try again"
    return 0
  }
  if {$argcnt == 5} { return 1 }
  if {$argcnt == 6} { return 2 }
}

proc checknospaces { name } {
  if [string match "* *" [file tail $name]] {
    confirmalert "Remove space(s) from filename:\
              \n\n    \"[file tail $name]\"\
              \n\n. . . and try again"
    return 0
  }
  ### rare, omit for now since blocks early path spaces (I might fix later)
  #if [string match "* *" [file dirname $name]] {
  #  confirmalert "Remove space(s) from path:\
  #            \n\n    \"[file dirname $name]\"\
  #            \n\n. . . and try again"
  #  return 0
  #}
  return 1
}

proc enabledisablelog { } {
  global tksurferlogflag logid ffont ffontb

  if ![canwriteormakefile tksurfer.log] {
    confirmalert "can't write logfile to [pwd]"
    set tksurferlogflag 0
    set logid -1
    return
  }
  if {$logid != -1} { logclose }
  if {$tksurferlogflag} {
    confirmalert "turned OFF log interface tcl cmds to:\
              \n\n    [pwd]/tksurfer.log"
    set tksurferlogflag 0
  } else {
    confirmalert "turned ON log interface tcl cmds to:\
               \n\n    [pwd]/tksurfer.log"
    logopen tksurfer.log  ;# N.B. always overwrites
    set tksurferlogflag 1
    exec xterm -geometry +50+630 -e tail -f [pwd]/tksurfer.log >& /dev/null &
  }
  if {$tksurferlogflag} {
    [.subhead.script.tcl.cbx subwidget label] config -font $ffontb
  } else {
    [.subhead.script.tcl.cbx subwidget label] config -font $ffont
  }
}

proc findsendto { } {
  global fulltkmedit fulltkregister
  set fulltkmedit ""
  set fulltkregister ""
  if { [exec uname] == "Darwin" || [exec uname] == "Linux" } {
    catch {set fulltkmedit [lrange [exec ps uxww | grep /tkmedit] 10 10]}
    catch {set fulltkregister [lrange [exec ps uxww | grep /tkeegister] 10 10]}
  } else {
    catch {set fulltkmedit [lrange [exec ps -af | grep /tkmedit] 7 7]}
    catch {set fulltkregister [lrange [exec ps -af | grep /tkregister] 7 7]}
  }
}

proc testclose { } {  ;# catch WM_DELETE_WINDOW, supersede simple wrappers func
  global surfeditedflag

  if {$surfeditedflag} {
    if ![okreplace "" \
           "Current surface coords have been edited:\
        \n\nDiscard surface coord edits and quit anyway?\
          \n(or Cancel, save with \"W\"\ on F3-interface \"outsurf:\" line)" \
            "Discard/Quit"] {
      return
    }
  }
  logclose
  destroy .
  exit        ;# takes GLX window with it (TODO: leaves vi/gedit in bg)
}

proc macro { } {  ;# orig long interface to right of GL
  global tksurferinterface inim fs fsabbrev glxwinx glxwiny glxwinw
  global mac_appnap_hack

  wm withdraw .
  pack forget .mright .draw.mesh.cm .shrink.cut.mini
  pack forget .subhead.script.surf
  pack forget .draw.curvswitch.ck0
  pack .subhead.hemisurf -side left
  pack .subhead.hemisurf.home -side top
  pack .subhead.hemisurf.insurf -side top
  pack .subhead.script -after .subhead.hemisurf
  pack .subhead.script.tcl -side top
  pack .subhead.script.aGO -side left
  pack .subhead.script.aEDIT -side left
  pack .subhead.script.aRDENV -side left
  pack .subhead.script.aLS -side left
  pack .subhead.script.sp -after .subhead.script.aLS -side left
  pack .subhead.script.bu -after .subhead.script.sp
  pack .files.outsurf    -before .files.ca -fill x
  if [info exists inim] { pack .files.inim -before .files.ca -fill x }
  pack .files.dipoles    -after .files.patch -fill x
  pack .files.label      -after .files.dipoles
  pack .files.lf         -after .files.label
  if [winfo viewable .files.val]   { pack .files.val -after .files.lf }
  if [winfo viewable .files.val3d] { pack .files.val3d -after .files.lf }
  pack .draw             -after .files
  pack .draw.main.aFlipHemi -after ".draw.main.aGOTO PNT" -side left
  pack .draw.main.aFlipHemi.bu
  pack .draw.curvswitch  -after .draw.main
  pack .draw.valswitch   -after .draw.curvswitch
  pack .draw.twocols     -after .draw.valswitch
  pack .draw.mesh        -after .draw.twocols
  pack .draw.switch2d    -after .draw.mesh
  pack .draw.mesh.sb     -after .draw.mesh.b
  pack .display          -after .xform
  pack .display.ri
  pack .shrink           -after .display
  pack .shrink.smooth    -after .shrink.cut
  pack .shrink.smooth.steps.avo -after .shrink.smooth.steps.acv -side left
  pack .shrink.smooth.steps.avo.ra
  pack .shrink.smooth.steps.acr -after .shrink.smooth.steps.aval -side left
  pack .shrink.smooth.steps.acr.ra
  pack .shrink.smooth.steps.as -after .shrink.smooth.steps.acr -side left
  pack .shrink.smooth.steps.as.ra
  pack .shrink.smooth.steps.agr -after .shrink.smooth.steps.asp -side left
  pack .shrink.smooth.steps.agr.ra
  pack .shrink.head      -after .shrink.smooth
  pack .shrink.main      -after .shrink.head
  #pack .shrink.cut.aFL  ;# rm FL=flatten -- TODO: restore when working
  pack forget .shrink.cut.aAREA.la .shrink.cut.ck
  pack .compute          -after .shrink
  pack .compute2         -after .compute
  pack .draw.mesh.me     -before .draw.mesh.r
  pack .draw.mesh.rect -after .draw.mesh.b
  pack .draw.curvswitch.acurv -side left
  pack .draw.curvswitch.anone.ra .draw.curvswitch.acurv.ra -side left
  # next2: insert space between "sh" radio and "in" tick (F2 OK)
  if ![winfo exists .draw.curvswitch.sp] { frame .draw.curvswitch.sp }
  pack .draw.curvswitch.sp -after .draw.curvswitch.as.ra -padx 2
  # next: rename/dup mess to mv up next row: ck=intp,ra=jet,ra2=ltw,ra3=vd
  #pack .draw.curvswitch.ra2 -after .draw.curvswitch.ck -side left
  pack .draw.curvswitch.ra2 -after .draw.curvswitch.ck3 -side left
  pack .draw.curvswitch.ra -after .draw.curvswitch.ra2 -side left
  pack .draw.curvswitch.ra3 -after .draw.curvswitch.ra -side left
  pack .draw.valswitch.aw2 -after .draw.valswitch.aw1 -side left
  pack .draw.valswitch.aw3 -after .draw.valswitch.aw2 -side left
  pack .draw.valswitch.aw4 -after .draw.valswitch.aw3 -side left
  pack .draw.valswitch.abi -after .draw.valswitch.aw4 -side left
  #pack .draw.valswitch.aGR -after .draw.valswitch.abi -side left
  #pack .draw.valswitch.ajt -after .draw.valswitch.afs -side left
  .draw.curvswitch.anone.la config -text "Col:" -width 3 -padx 0
  pack .draw.curvswitch.acurv .draw.curvswitch.aa .draw.curvswitch.as \
    -after .draw.curvswitch.anone -side left
  pack forget .draw.curvswitch.e0 .draw.curvswitch.e1
  #pack forget .draw.curvswitch.ck2 .draw.curvswitch.ck3
  .draw.curvswitch.anone.ra config -text "no"
  .draw.curvswitch.acurv.ra config -text "cv"
  # next3: slightly darker to distinguish
  .draw.curvswitch.ck config -text "in" -bg #b0b0a0
  .draw.curvswitch.ck2 config -text "bt" -bg #b0b0a0
  .draw.curvswitch.ck3 config -text "sy" -bg #b0b0a0
  {.draw.main.aSEND PNT.bu} config -text "SEND PNT"
  {.draw.main.aGOTO PNT.bu} config -text "GOTO PNT"
  pack .shrink.cut.aROI -before .shrink.cut.aAREA
  pack .shrink.cut.aN .shrink.cut.aA .shrink.cut.aR -after .shrink.cut.aROI
  pack .shrink.cut.aUNDO -after .shrink.cut.aLINE
  .shrink.cut.aAREA.bu config -text "AREA"
  .shrink.cut.aPLANE.bu config -text "PLANE"
  .shrink.cut.aLINE.bu config -text "LINE"
  .shrink.smooth.steps.la config -text "steps:" -width 6
  #.subhead.hemisurf.home.e config -width 20
  #.subhead.hemisurf.insurf.e config -width 20
  #.shrink.smooth.aSMOOTH.bu config -text "Smooth VtxData"
  #wm geometry . +1240+26   ;# tk interface window (was +1275+32)
  wm geometry . +[expr $glxwinx + $glxwinw + 10]+[expr $glxwiny - 22]
  after 500 { wm deiconify . }
  ### tried zillions of diff configs w/o ever getting this to work reliably
  #if {$mac_appnap_hack} {
  #  tkwait visibility .    ;# returns when just window, before widgets drawn
  #  uplevel #0 {
  #    set geom +[winfo rootx .]+[winfo rooty .]
  #    set xtermpid [exec xterm -geom 62x72${geom} -bg $bgcol -e bash --norc &]
  #  }
  #  update  ;# required for delayed conver/uncover to work
  #  after 2000 { exec kill $xtermpid }
  #}
  set tksurferinterface macro
}

proc mini { } {  ;# rearrange for under GL window
  global tksurferinterface inim fs fsabbrev fm fmabbrev
  global glxwinx glxwiny glxwinh bgcol mac_appnap_hack

  wm withdraw .
  set winlist {.subhead.hemisurf .subhead.script .files.outsurf \
               .files.dipoles \
               .draw.main.aFlipHemi \
               .draw.curvswitch .draw.twocols .draw.switch2d \
               .draw.mesh.sb .display.ri .draw.valswitch.aw2 \
               .draw.valswitch.aw3 .draw.valswitch.aw4 .draw.valswitch.aGR \
               .draw.curvswitch.ra2 .draw.curvswitch.ra .draw.curvswitch.ra3 \
               .draw.curvswitch.anone.ra \
               .draw.curvswitch.acurv \
               .draw.curvswitch.aa .draw.curvswitch.as \
               .shrink.smooth .shrink.head .shrink.main .shrink.cut.aFL \
               .shrink.smooth.steps.avo.ra .shrink.smooth.steps.avo \
               .shrink.smooth.steps.acr.ra .shrink.smooth.steps.acr \
               .shrink.smooth.steps.agr.ra .shrink.smooth.steps.agr \
               .shrink.smooth.steps.as.ra  .shrink.smooth.steps.as \
               .compute .compute2 }  ;# forget avo/acr/agr frame, too -> squish
  foreach win $winlist { pack forget $win }
  if [info exists inim] { pack forget .files.inim }  ;# bak compat
  pack forget .subhead.hemisurf
  pack .subhead.script
  pack .subhead.script.bu -side left
  pack forget .subhead.script.sp
  pack .subhead.script.surf -side left
  pack .subhead.script.tcl -after .subhead.script.surf -side left
  pack .subhead.script.aGO -after .subhead.script.tcl -side left
  pack .subhead.script.aEDIT -after .subhead.script.aGO -side left
  pack forget .subhead.script.aLS
  pack forget .subhead.script.aRDENV
  pack .files.lf  -after .files.label
  if [winfo viewable .files.val]   { pack .files.val -after .files.lf }
  if [winfo viewable .files.val3d] { pack .files.val3d -after .files.lf }
  ## rearrange
  pack .mright -before .subhead -side right
  .draw config -bd 2 -relief groove
  pack .draw -in .mright 
  pack .draw.curvswitch
  pack .draw.valswitch -after .draw.curvswitch
  pack .draw.mesh -after .draw.valswitch
  pack .draw.mesh.me
  pack .draw.mesh.cm
  pack .display -after .draw
  pack .shrink -after .display
  pack .shrink.smooth
  pack .shrink.cut.mini -before .shrink.cut.aAREA -side bottom
  raise .draw
  raise .display
  raise .shrink
  pack .shrink.cut.aROI .shrink.cut.aN .shrink.cut.aA .shrink.cut.aR \
    .shrink.cut.aUNDO .shrink.cut.aINIT .shrink.cut.aALL \
    -in .shrink.cut.mini -side left
  ## squish
  {.draw.main.aSEND PNT.bu} config -text SEND
  {.draw.main.aGOTO PNT.bu} config -text GOTO
  .draw.curvswitch.anone.la config -text "Col:" -width 3
  pack .draw.curvswitch.ck0 .draw.curvswitch.e0 .draw.curvswitch.e1 \
    -after .draw.curvswitch.anone.la -side left
  pack .draw.curvswitch.ck2 .draw.curvswitch.ck3 \
    -after .draw.curvswitch.ck -side left
  pack .shrink.cut.aAREA.la -side left -before .shrink.cut.aAREA.bu
  pack .shrink.cut.ck -side left -after .shrink.cut.aAREA.bu
  .shrink.smooth.steps.la config -text "" -width 0
  #.shrink.smooth.aSMOOTH.bu config -text "SMOOTH"
  ## unsquish
  .draw.curvswitch.ck config -text "intp" -bg $bgcol
  .draw.curvswitch.ck2 config -text "bot" -bg $bgcol
  .draw.curvswitch.ck3 config -text "sym" -bg $bgcol
  #wm geometry . +630+659    ;# tk interface window (was +658+664)
  #tksurfer.c:sprintf(cmd,"wm geometry . +%d+%d", glw.x, glw.y+glw.h+TKGL_YGAP);
  wm geometry . +${glxwinx}+[expr $glxwiny + $glxwinh + 10]  ;# TKGL_YGAP=10
  after 500 { wm deiconify . }

  ### tried zillions of diff configs w/o ever getting this to work reliably
  #if {$mac_appnap_hack} {
  #  tkwait visibility .    ;# returns when just window, before widgets drawn
  #  uplevel #0 {
  #    set geom +[winfo rootx .]+[winfo rooty .]
  #    set xtermpid [exec xterm -geom 105x25${geom} -bg $bgcol -e bash --norc &]
  #  }
  #  update  ;# required for delayed conver/uncover to work
  #  after 2000 { exec kill $xtermpid }
  #}
  set tksurferinterface mini
}

############################################################################
# main window frames, frame hierachy by indentation
############################################################################
wm title . "tksurfer ($subject $hemi $surfext)"
wm protocol . WM_DELETE_WINDOW testclose
wm resizable . 0 0

frame .subhead
pack .subhead -side top
  frame .subhead.hemisurf
  pack .subhead.hemisurf -side left
  frame .subhead.script -borderwidth 2 -relief groove
  pack .subhead.script -side right -fill x -expand true

frame .files
pack .files -side top

frame .draw
pack .draw -side top
  frame .draw.main
  pack .draw.main -side top ;# -fill x
  frame .draw.mainsub
  pack .draw.mainsub -side top -fill x
  frame .draw.curvswitch
  pack .draw.curvswitch -side top -fill x
  frame .draw.valswitch
  pack .draw.valswitch -side top -fill x
  frame .draw.twocols
  pack .draw.twocols -side top -fill x
    frame .draw.twocols.r1
    pack .draw.twocols.r1 -side left -fill x
    frame .draw.twocols.g1
    pack .draw.twocols.g1 -side left -fill x
    frame .draw.twocols.b1
    pack .draw.twocols.b1 -side left -fill x
    frame .draw.twocols.r2
    pack .draw.twocols.r2 -side left -fill x
    frame .draw.twocols.g2
    pack .draw.twocols.g2 -side left -fill x
    frame .draw.twocols.b2
    pack .draw.twocols.b2 -side left -fill x
  frame .draw.mesh
  pack .draw.mesh -side top -fill x
    frame .draw.mesh.me
    pack .draw.mesh.me -side left -fill x
    frame .draw.mesh.r
    pack .draw.mesh.r -side left -fill x
    frame .draw.mesh.g
    pack .draw.mesh.g -side left -fill x
    frame .draw.mesh.b
    pack .draw.mesh.b -side left -fill x
    frame .draw.mesh.sb
    pack .draw.mesh.sb -side left -fill x
    frame .draw.mesh.cm
    pack .draw.mesh.cm -side left -fill x
    frame .draw.mesh.rect
    pack .draw.mesh.rect -side left -fill x
  frame .draw.switch2d
  pack .draw.switch2d -side top -fill x

frame .xform
pack .xform -side top
  # rotate
  frame .xform.rotate -borderwidth 2 -relief groove
  pack .xform.rotate -side left
    frame .xform.rotate.top
    pack .xform.rotate.top -side top
    frame .xform.rotate.bot
    pack .xform.rotate.bot -side top
      frame .xform.rotate.bot.la
      pack .xform.rotate.bot.la -side right -anchor center
  # translate
  frame .xform.translate -borderwidth 2 -relief groove
  pack .xform.translate -side left
    frame .xform.translate.top
    pack .xform.translate.top -side top
    frame .xform.translate.bot
    pack .xform.translate.bot -side top
      frame .xform.translate.bot.la
      pack .xform.translate.bot.la -side right -anchor center
  # scale
  frame .xform.scale -borderwidth 2 -relief groove
  pack .xform.scale -side left -anchor n   ;# -fill both -expand true
    frame .xform.scale.top
    pack .xform.scale.top -side top
    frame .xform.scale.bot
    pack .xform.scale.bot -side top

frame .display ;# -borderwidth 2 -relief groove
pack .display -side top
  frame .display.le
  pack .display.le -side left
  frame .display.mi
  pack .display.mi -side left
  frame .display.ri
  pack .display.ri -side left

frame .shrink -borderwidth 2 -relief groove
pack .shrink
  frame .shrink.cut
  pack .shrink.cut -padx 0
    frame .shrink.cut.mini
    pack .shrink.cut.mini -side bottom
  frame .shrink.smooth ;# -borderwidth 2 -relief groove
  pack .shrink.smooth
  frame .shrink.head
  pack .shrink.head -side top
  frame .shrink.main
  pack .shrink.main -side top
    frame .shrink.main.le
    pack .shrink.main.le -side left
    frame .shrink.main.mi
    pack .shrink.main.mi -side left
    frame .shrink.main.ri
    pack .shrink.main.ri -side left

frame .compute ;# -borderwidth 2 -relief groove
pack .compute -side top
  frame .compute.le0
  pack .compute.le0 -side left
  frame .compute.le
  pack .compute.le -side left
  frame .compute.lm
  pack .compute.lm -side left
  frame .compute.rm
  pack .compute.rm -side left
  frame .compute.ri
  pack .compute.ri -side left

frame .compute2
pack .compute2 -side top

frame .mright -borderwidth 2 -relief groove  ;# for rearrange
pack .mright -side right

### if opened here (tksurfer option), log includes constant startup cmds
set mktcllabbold 0
if { $tksurferlogflag } {
  if ![canwriteormakefile tksurfer.log] {
    confirmalert "can't write tksurfer.log to:\n\n[pwd]"
    set tksurferlogflag 0
  } else {
    if { [pwd] != "$isession/scripts" } {  ;# not from csurf
      confirmalert "N.B.: writing tcl cmd log outside scripts dir in:\n\n[pwd]"
    }
    logopen tksurfer.log
    set mktcllabbold 1
  }
}

############################################################################
# make interface widgets, top left to bottom right
############################################################################
### make orig one-column big/F3 panel, then rearrange into two columns
puts "tksurfer.tcl: making widgets"

### top box/line (plus some F3 only)
set f .subhead

#### home (F3 only)
############################################################################
set f .subhead.hemisurf
edlabval $f "home" $home/$subject n 5 22
$f.home.e config -font $ffontb -state disabled
bind $f.home.e <ButtonRelease-3> { helpwin home }

#### insurf (F3 only, replaced by better combo in F2)
############################################################################
set f .subhead.hemisurf
edlabval $f "insurf" $hemi.$surfext r 5 19  ;# "insurf:" (makes R button)
setfile insurf $insurf
bind $f.insurf.br <ButtonRelease-3> { helpwin insurf_read }
$f.insurf.e config -textvariable insurfabbrev
bind $f.insurf.e <ButtonRelease-3> { helpwin insurf_read }
$f.insurf.br config -text "R" -padx 1
$f.insurf.br config -command {
  setfile insurf [.subhead.hemisurf.insurf.e get]
  if [string match $hemi.* [file tail $insurf]] {
    set surfext [string range [file tail $insurf] 3 end]
  } else { set surfext $surfext }  ;# touch to get callback
  #rereaddrawsurf  ;#don't need: touch surfext does tix select_surfext callback
  wm title . "tksurfer ($subject $hemi $surfext)"
}
bind $f.insurf.e <Return> "$f.insurf.br invoke"

#### surf (cbx -command vs. just select)
############################################################################
set f .subhead.script
## toggle interface size
button $f.bu -text "i" -font $ffontb -pady 0 -padx 1 -command {
  #buttonbar "\" F2 \" \" F3 \"" "mini macro"  ;# overkill for toggle
  if {$tksurferinterface == "mini"} {
    macro
  } elseif {$tksurferinterface == "macro"} {
    mini
  } else { ; }
}
pack $f.bu -side left
bind $f.bu <ButtonRelease-3> { helpwin interface }
label $f.sp -width 1 -bg $bgcol
## surf dropdown
frame $f.surf
pack $f.surf -side top -fill x -padx 2
# N.B.; dropdown only loaded once (vs. 
tixComboBox $f.surf.cbx -label "surf:" -dropdown true -editable true \
  -variable surfext -command "select_surfext $f.surf.cbx" -listwidth 159 \
  -options "label.width 3 entry.width 9 listbox.height 15 listbox.width 18"
### -listwidth alone required 175 (wider) to get constant: keep both
#tixComboBox $f.surf.cbx -label "surf:" -dropdown true -editable true \
#  -variable surfext -command "select_surfext $f.surf.cbx" -listwidth 175 \
#  -options "label.width 3 entry.width 9 listbox.height 15" ;# listbox.width 18
$f.surf.cbx subwidget label config -font $ffont
$f.surf.cbx subwidget entry config -selectforeground black
$f.surf.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
set surflist ""
foreach surf $surflooklist {  ;# match surf's w/suffixes (incl sphere.reg)
  set globsurfs \
    [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/$hemi.$surf*]
  foreach globsurf $globsurfs {  ;# rm dups, irrelevant
    if { ![string match *.nofix $globsurf] && \
         ![string match *.crv $globsurf] && \
         ![string match *.H $globsurf] && \
         ![string match *.K $globsurf] && \
         ![string match *.3d $globsurf] &&
         ![string match *.flat $globsurf] } {
      #$f.surf.cbx insert end [string trimleft [file tail $globsurf] $hemi.]
      set surflist "$surflist [string trimleft [file tail $globsurf] $hemi.]"
    }
  }
}
# add any surf-like GIFTI (N.B.: maybe R,L,RL, incl flat since not a patch!)
if {$hemi == "rh"} {
  set globsurfs \
    [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*.R.*.surf.gii]
}
if {$hemi == "lh"} {
  set globsurfs \
    [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*.L.*.surf.gii]
}
# add all *.obj/*.srf, trim preappend hemi, rm dups (e.g., surftmp there above)
lappend globsurfs [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*.obj]
lappend globsurfs [glob -nocomplain $env(SUBJECTS_DIR)/$subject/$surfdir/*.srf]
foreach globsurf $globsurfs {
  set surflist "$surflist [string trimleft [file tail $globsurf] $hemi.]"
}
set uniqlist {}
foreach surf $surflist {
  if { [lsearch -exact $uniqlist $surf] == -1 } { lappend uniqlist $surf }
}
set surflist $uniqlist
# load entry
set surflist [lsort $surflist]
foreach surf $surflist { $f.surf.cbx insert end $surf }
pack $f.surf.cbx -side left
bind [$f.surf.cbx subwidget entry] <ButtonRelease-3> { helpwin surf }
bind [$f.surf.cbx subwidget label] <ButtonRelease-3> {
  set printheaderflag 1   ;# refresh genstrret_1k (doesn't re-read surf)
  read_binary_surface
  set printheaderflag 0
  confirmalert "Surface header:\n-----------------------\n$genstrret_1k"
}

#### tcl script
############################################################################
set f .subhead.script
frame $f.tcl
pack $f.tcl -side top -fill x -padx 2
## combo
tixComboBox $f.tcl.cbx -label "tcl:" -dropdown true -editable true \
  -variable scriptabbrev -listcmd "listcmd_tcl $f.tcl.cbx" -listwidth 315 \
  -command "select_script $f.tcl.cbx" \
  -options "label.width 2 entry.width 16 listbox.height 18" ;# listbox.width 40
setfile script $script    ;# reset scriptabbrev (to show cmdline or default)
$f.tcl.cbx subwidget label config -font $ffont
$f.tcl.cbx subwidget entry config -selectforeground black
$f.tcl.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
set currabbrev $scriptabbrev
$f.tcl.cbx config -value $currabbrev
pack $f.tcl.cbx -side left
bind [$f.tcl.cbx subwidget entry] <ButtonRelease-3> { helpwin script }
bind [$f.tcl.cbx subwidget label] <ButtonRelease-1> { enabledisablelog }
##TODO: binding to <Return> won't trigger (but <ButtonRelease-2> works?)
#bind [$f.tcl.cbx subwidget entry] <Return> {
#  setfile script [.subhead.script.tcl.cbx subwidget entry get]
#  if ![file exists $script] {
#    confirmalert "Tcl Script file not found:\n\n    $script"
#  }
#}
if {$mktcllabbold} {
  [.subhead.script.tcl.cbx subwidget label] config -font $ffontb
}
bind [$f.tcl.cbx subwidget label] <ButtonRelease-3> { helpwin script_record }
## buttons (warn startup script redo)
buttons $f "GO" { } row 0 1  ;# TODO: put load combo in func, reload if error
#frame $f.aGO  ;# HOWTO emulate copy extra subwin from buttons
#button $f.aGO.bu -text "GO" -font $ffontb -pady 0 -padx 0
#pack $f.aGO $f.aGO.bu
bind .subhead.script.aGO.bu <ButtonRelease-1> {
  if [divider [.subhead.script.tcl.cbx subwidget entry get]] { break }
  .subhead.script.tcl.cbx config -disablecallback true
  setfile script [.subhead.script.tcl.cbx subwidget entry get]
  .subhead.script.tcl.cbx config -disablecallback false
  set doit 1
  # query accidental re-run SURFACE startup script
  if [string match "TmpTclSurf.*" [file tail $script]] {
    if ![okreplace "" "Run Script: current tcl script:\
                   \n\n    [file tail $script]\
                   \n\nis a tksurfer SURFACE startup script\
                   \n\n... re-run anyway (OK)?" "Re-Run Script"] {
      set doit 0
    }
  } else {  ;# check other non-standalone SURFACE-STATS scripts
    foreach patt "fs-views.tcl fs-flat.tcl
        eccen-views.tcl eccen-flat.tcl polar-views.tcl polar-flat.tcl
        real-views.tcl real-flat.tcl twocond-views.tcl twocond-flat.tcl
        borders.tcl fs-make.tcl" {
      if [string match $patt [file tail $script]] {
        if { ![info exists dir] && 
             ![info exists eccendir] && ![info exists polardir] } {
          # block initial run SURFACE-STATS startup script from SURFACE button
          confirmalert "Run Script: current tcl script:\
                    \n\n    [file tail $script]\
                    \n\nis a tksurfer SURFACE-STATS startup script\
                      \n(normally run via comprehensive command line)\
                    \n\nBlocked here because it will fail\
                      \n(unless needed vars commented in for standalone)"
          set doit 0
        } else {
          # query accidental re-run SURFACE-STATS startup script
          if ![okreplace "" "Run Script: current tcl script:\
                         \n\n    [file tail $script]\
                         \n\nis a tksurfer SURFACE-STATS startup script\
                         \n\n... re-run anyway?" "Re-Run Script"] { set doit 0 }
        }
      }
    }
  }
  if {$doit} {
    puts "tksurfer.tcl: run (source) script: $script"
    catch { set userok 0; source $script } err  ;# works w/space
    logcmd "set userok 0; source $script"
    if { "$err" != "" && "$err" != 0 && "$err" != 1 } {
      confirmalert "$script: ###\n\n$err"
    }
    prompt
  }
}
bind .subhead.script.aGO.bu <ButtonRelease-3> { helpwin script_run }
## next no effect (like above)
#bind [$f.tcl.cbx subwidget entry] <Return> "$f.aGO.bu invoke" ;#after make it
buttons $f "EDIT" {
  if [divider [.subhead.script.tcl.cbx subwidget entry get]] { break }
  setfile script [.subhead.script.tcl.cbx subwidget entry get]
  if { [string match $env(SUBJECTS_DIR)/$subject/tmp/*.tcl $script] &&
       ![file exists $env(SUBJECTS_DIR)/$subject/tmp] } {
    if [canwriteormakefile $env(SUBJECTS_DIR)/$subject/tmp] {
      if [catch { exec mkdir $env(SUBJECTS_DIR)/$subject/tmp }] {
        confirmalert "Failed to create tmp subdir in subject: $subject"
      } else {
        confirmalert "Added tmp subdir to subject: $subject"
      }
    } else {
      confirmalert "Permissions don't allow create tmpdir in subject: $subject"
    }
  }
  editfile $script
} row 0 0
bind .subhead.script.aEDIT.bu <ButtonRelease-3> { helpwin script_edit }
## RDENV,LS (big panel only)
buttons $f "RDENV" { source $env(CSURF_DIR)/lib/tcl/readenv.tcl; \
                 setfile script $env(CSURF_DIR)/lib/tcl/readenv.tcl } row 0 0
bind .subhead.script.aRDENV.bu <ButtonRelease-3> { helpwin readenv }
buttons $f LS {
  confirmalert "$env(CSURF_DIR)/lib/tcl:\n[exec ls -1F $env(CSURF_DIR)/lib/tcl]"
  puts "$env(CSURF_DIR)/lib/tcl:\n---------------------------------------"
  puts [exec ls -1F $env(CSURF_DIR)/lib/tcl]
  prompt
} row 0 0
bind .subhead.script.aLS.bu <ButtonRelease-3> { helpwin ls }

#### editable files region (plus some only on F3 interface)
set f .files

#### orig/ellipse coords -- entry never made
setfile origcoords $origcoords
setfile whitecoords $whitecoords
setfile pialcoords $pialcoords
setfile ellcoords $ellcoords

#### outsurf (F3 only)
############################################################################
edlabval $f "outsurf" default w 6 14  ;#was VTK=33 OFF=28 STL=24 GLB=19 OBJ=14
setfile outsurf $outsurf
$f.outsurf.e config -textvariable outsurfabbrev
$f.outsurf.bw config -command {
  setfile outsurf [.files.outsurf.e get]
  testreplace $outsurf write_binary_surface   ;# does log
}
bind $f.outsurf.e <ButtonRelease-3> { helpwin outsurf }
bind $f.outsurf.bw <ButtonRelease-3> { helpwin outsurf_write }
$f.outsurf.bw config -text "W" -padx 2
# write ASC (was W-ASCII)
button $f.outsurf.bw2 -text "ASC" -font $ffontb -pady 0 -padx 0 -command {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.asc $outsurf] { setfile outsurf $outsurf.asc }
  testreplace $outsurf write_ascii_surface
}
## auto-append next here (before funct does) so test_replace can warn overwrite
# write VTK
button $f.outsurf.bw3 -text "VTK" -font $ffontb -pady 0 -padx 0 -command {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.vtk $outsurf] { setfile outsurf $outsurf.vtk }
  testreplace $outsurf write_vtk_surface
}
# write OFF (no colors)
button $f.outsurf.bw4 -text "OFF" -font $ffontb -pady 0 -padx 0 -command {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.off $outsurf] { setfile outsurf $outsurf.off }
  testreplace $outsurf write_off_surface 0
}
# alt: write OFF (face colors)
bind $f.outsurf.bw4 <ButtonRelease-2> {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.off $outsurf] { setfile outsurf $outsurf.off }
  testreplace $outsurf write_off_surface 1
}
# alt: write OFF (vertex colors)
bind $f.outsurf.bw4 <Shift-ButtonRelease-2> {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.off $outsurf] { setfile outsurf $outsurf.off }
  testreplace $outsurf write_off_surface 2
}
# write STL
button $f.outsurf.bw5 -text "STL" -font $ffontb -pady 0 -padx 0 -command {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.stl $outsurf] { setfile outsurf $outsurf.stl }
  testreplace $outsurf write_stl_surface
}
# write GLB (glTF)
button $f.outsurf.bw6 -text "GLB" -font $ffontb -pady 0 -padx 0 -command {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.glb $outsurf] { setfile outsurf $outsurf.glb }
  testreplace $outsurf write_glb_surface
}
# write OBJ (Wavefront/Alias, no colors)
button $f.outsurf.bw7 -text "OBJ" -font $ffontb -pady 0 -padx 0 -command {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.obj $outsurf] { setfile outsurf $outsurf.obj }
  testreplace $outsurf write_obj_surface 0
}
# alt: write OBJ (Wavefront/Alias, vertex colors)
bind $f.outsurf.bw7 <ButtonRelease-2> {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.obj $outsurf] { setfile outsurf $outsurf.obj }
  testreplace $outsurf write_obj_surface 1
}
# no binding yet for just add normals: write_obj_surface 2
# alt: write OBJ (Wavefront/Alias, vertex colors and normals)
bind $f.outsurf.bw7 <Shift-ButtonRelease-2> {
  setfile outsurf [.files.outsurf.e get]
  if ![string match *.obj $outsurf] { setfile outsurf $outsurf.obj }
  testreplace $outsurf write_obj_surface 3
}
pack $f.outsurf.bw2 $f.outsurf.bw3 $f.outsurf.bw4 $f.outsurf.bw5 \
  $f.outsurf.bw6 $f.outsurf.bw7 -side left
pack $f.outsurf.bw -before $f.outsurf.bw2 -side left
bind $f.outsurf.bw2 <ButtonRelease-3> { helpwin outsurfasc_write }
bind $f.outsurf.bw3 <ButtonRelease-3> { helpwin outsurfvtk_write }
bind $f.outsurf.bw4 <ButtonRelease-3> { helpwin outsurfoff_write }
bind $f.outsurf.bw5 <ButtonRelease-3> { helpwin outsurfstl_write }
bind $f.outsurf.bw6 <ButtonRelease-3> { helpwin outsurfglb_write }
bind $f.outsurf.bw7 <ButtonRelease-3> { helpwin outsurfobj_write }

#### inim's (F3 only)
############################################################################
if [info exists inim] {
  edlabval $f "inim"       default   r  5 35
  setfile inim $inim
  $f.inim.e config -textvariable inimabbrev
  $f.inim.br config -command {
    setfile inim [.files.inim.e get]
    read_images
    logcmd "read_images"
    set MRIflag 1
    logcmd "set MRIflag 1"
    chkcleargradamp
    logcmd "chkcleargradamp"
  }
  bind $f.inim.e <Return> "$f.inim.br invoke"
  bind $f.inim.e <ButtonRelease-3> { helpwin read_im }
  bind $f.inim.br <ButtonRelease-3> { helpwin read_im }
  ## direct_paint im only
  button $f.inim.br2 -text "P" -font $ffontb -pady 0 -padx 0 -command {
    if {!$MRIloaded} {
      confirmalert "Direct Paint (to .val): no \"im:\" data loaded"
    } else {
      direct_paint
      logcmd "direct_paint"
      set overlayflag 1
      logcmd "set overlayflag 1"
      checkrealcolscale
      redrawbutton
    }
  }
  pack $f.inim.br2 -side left
  bind $f.inim.br2 <ButtonRelease-3> { helpwin direct_paint }
}
# overload "im:" label with write sphim popup
$f.inim.la config -font $ffontb  ;# $ffontb -> clickable label
bind $f.inim.la <ButtonRelease-1> { sphimctrls }
bind $f.inim.la <ButtonRelease-3> { helpwin read_im_label }
## inim2,3 plus buttons, packed into inim frame (big only)
if [info exists inim2] {
  $f.inim.la config -width 3 -text "im:"
  $f.inim.e config -width 10
  $f.inim.br config -text "R" -padx 0
  edlabval $f.inim "inim2" default r 3 10 row
  edlabval $f.inim "inim3" default r 3 8 row
  setfile inim2 $inim2
  setfile inim3 $inim3
  $f.inim.inim2.e config -textvariable inim2abbrev
  $f.inim.inim3.e config -textvariable inim3abbrev
  $f.inim.inim2.la config -text "im2:"
  $f.inim.inim3.la config -text "im3:"
  $f.inim.inim2.br config -text "R" -padx 1 -command { 
    setfile inim2 [.files.inim.inim2.e get]
    read_images2
    logcmd "read_images2"
    set MRI2flag 1
    logcmd "set MRI2flag 1"
  }
  $f.inim.inim3.br config -text "R" -padx 1 -command { 
    setfile inim3 [.files.inim.inim3.e get]
    read_images3
    logcmd "read_images3"
    set MRI3flag 1
    logcmd "set MRI3flag 1"
  }
  bind $f.inim.inim2.e <Return> "$f.inim.inim2.br invoke"
  bind $f.inim.inim3.e <Return> "$f.inim.inim3.br invoke"
  bind $f.inim.inim2.e <ButtonRelease-3> { helpwin read_im2 }
  bind $f.inim.inim3.e <ButtonRelease-3> { helpwin read_im3 }
  bind $f.inim.inim2.br <ButtonRelease-3> { helpwin read_im2 }
  bind $f.inim.inim3.br <ButtonRelease-3> { helpwin read_im3 }
}

#=============================
#### alpha + curv + area frame
#=============================
set f .files
frame $f.ca
pack $f.ca -side top -fill x -padx 1

#### curv (add area)
############################################################################
set f .files.ca
frame $f.curv
pack $f.curv -side left
## labelalpha
label $f.curv.la2 -text "tran" -font $ffont -pady 0
pack $f.curv.la2 -side left
entry $f.curv.e2 -textvariable labelalpha -font $ffont -width 3 \
  -selectbackground $selbgcol -selectforeground black  ;# linux
pack $f.curv.e2 -side left -padx 0
bind $f.curv.e2 <Return> {
  set_annot_alpha $labelalpha
  logcmd "set_annot_alpha $labelalpha"
  redrawbutton
}
bind $f.curv.e2 <ButtonRelease-3> { helpwin labelalpha }
## combo
setfile curv $curv   ;# create curvabbrev (N.B.: file may not exist)
tixComboBox $f.curv.cbx -label " curv:" -dropdown true -editable true \
  -variable curvabbrev -listcmd "listcmd_curv $f.curv.cbx" \
  -command "select_curv $f.curv.cbx" -listwidth 453 \
  -options "label.width 4 entry.width 7 listbox.height 12" ;# listbox.width 17
$f.curv.cbx subwidget label config -font $ffont
$f.curv.cbx subwidget entry config -selectforeground black
$f.curv.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
set currabbrev $curvabbrev
$f.curv.cbx config -disablecallback true  ;# blk select_curv load before GL
$f.curv.cbx config -value $currabbrev
$f.curv.cbx config -disablecallback false
pack $f.curv.cbx -side left -padx 2
$f.curv.cbx subwidget entry xview moveto 1
bind [$f.curv.cbx subwidget entry] <ButtonRelease-3> { helpwin curv }
## buttons
button $f.curv.br -text "R" -font $ffontb -pady 0 -padx 0 -command {
  select_curv .files.ca.curv.cbx [.files.ca.curv.cbx subwidget entry get]
}
button $f.curv.bw -text "W" -font $ffontb -pady 0 -padx 0 -command {
  setfile curv [.files.ca.curv.cbx subwidget entry get]
  testreplace $curv write_binary_curv
}
pack $f.curv.br $f.curv.bw -side left
bind $f.curv.br <ButtonRelease-3> { helpwin curv_read }
bind $f.curv.bw <ButtonRelease-3> { helpwin curv_write }

#### area (added to curv line)
###############################
set f .files.ca
frame $f.area
pack $f.area -side left -padx 0
## combo
set area2flag 0  ;# intern: toggle area label
setfile area $area  ;# create areaabbrev (N.B.: file may not exist)
tixComboBox $f.area.cbx -label " area:" -dropdown true -editable true \
  -variable areaabbrev -listcmd "listcmd_area $f.area.cbx" \
  -command "select_area $f.area.cbx" -listwidth 153 \
  -options "label.width 4 entry.width 7 listbox.height 8 listbox.width 17"
$f.area.cbx subwidget label config -font $ffont
$f.area.cbx subwidget entry config -selectforeground black
$f.area.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
set currabbrev $areaabbrev
$f.area.cbx config -disablecallback true  ;# blk select_area load before GL
$f.area.cbx config -value $currabbrev
$f.area.cbx config -disablecallback false
pack $f.area.cbx -side left -padx 1
$f.area.cbx subwidget entry xview moveto 1
bind [$f.area.cbx subwidget entry] <ButtonRelease-3> { helpwin area }
bind [$f.area.cbx subwidget label] <ButtonRelease-3> { helpwin area_lab }
## buttons (R, W, D-overloaded)
button $f.area.br -text "R" -font $ffontb -pady 0 -padx 0 -command {
  select_area .files.ca.area.cbx [.files.ca.area.cbx subwidget entry get]
}
button $f.area.bw -text "W" -font $ffontb -pady 0 -padx 0 -command {
  setfile area [.files.ca.area.cbx subwidget entry get]
  chkareaoverwrite
  testreplace $area write_binary_areas
}
button $f.area.bd -text "D" -font $ffontb -pady 0 -padx 0
bind $f.area.bd <ButtonRelease-1>       { calcdisp_curr2orig_logarat }
bind $f.area.bd <ButtonRelease-2>       { calcdisp_curr2orig_arat }
bind $f.area.bd <Shift-ButtonRelease-2> { calcdisp_arat }
pack $f.area.br $f.area.bw $f.area.bd -side left
# help
bind $f.area.br <ButtonRelease-3> { helpwin area_read }
bind $f.area.bw <ButtonRelease-3> { helpwin area_write }
bind $f.area.bd <ButtonRelease-3> {  ;# help + buttonbar
  helpwin area_disp
  buttonbar \
    "\"Display Curr-to-Orig Log Area Ratio (left-click-D)\" \
     \"Display Curr-to-Orig Area Ratio (all pos) (mid-clk-D)\" \
     \"Disp Area-to-AreaPial Area Ratio (shift-mid-clk-D)\"" \
    "calcdisp_curr2orig_logarat calcdisp_curr2orig_arat calcdisp_arat" \
    ver "AREA RATIO Button" area_disp
}
## clicking bold "area" or "area2" labels swaps read_binary_{area,area2}
$f.area.cbx subwidget label config -font $ffontb
bind [$f.area.cbx subwidget label] <ButtonRelease-1> {
  if {$area2flag} {  ;# intern (not exported from C)
    set area2flag 0; .files.ca.area.cbx subwidget label config -text "area:"
  } else {
    set area2flag 1; .files.ca.area.cbx subwidget label config -text "area2"
  }
}

#### patch (incl patch operations)
############################################################################
set f .files
frame $f.patch
pack $f.patch -side top -fill x -padx 2
## label coords-type (orig/Talairach/current) Select (a little out of place)
tixSelect $f.patch.s1 -allowzero true -radio true -orientation horizontal
foreach but "ta cu" {
  $f.patch.s1 add $but -text $but -font $hfont \
    -width 2 -bg $bgcol -padx 0 -pady 0 \
    -highlightback $hilbgcol -highlightcolor $hilcol -activeback $actbgcol
}
$f.patch.s1 config -variable c2lab -command select_coordstype
$f.patch.s1 subwidget label config -padx 0
pack $f.patch.s1 -side left -padx 0
bind [$f.patch.s1 subwidget cu] <ButtonRelease-3> {
  helpwin usecurr
  report_curr_labelcoords
}
bind [$f.patch.s1 subwidget ta] <ButtonRelease-3> {
  helpwin usecurr
  report_curr_labelcoords
}
## patch combo
#TODO: -validatecmd <proc> called w/new -value before value changed
setfile patch $patch  ;# create patchabbrev (N.B.: file may not exist)
tixComboBox $f.patch.cbx -label " patch: " -dropdown true -editable true \
  -variable patchabbrev -listcmd "listcmd_patch $f.patch.cbx" \
  -command "select_patch $f.patch.cbx" -listwidth 243 \
  -options "label.width 5 entry.width 22 listbox.height 15" ;# listbox.width 30
$f.patch.cbx subwidget label config -font $ffont
$f.patch.cbx subwidget entry config -selectforeground black
$f.patch.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
set currabbrev $patchabbrev  ;# file may not exist
$f.patch.cbx config -disablecallback true  ;# blk select_patch load before GL
$f.patch.cbx config -value $currabbrev
$f.patch.cbx config -disablecallback false
pack $f.patch.cbx -side left -padx 2
bind [$f.patch.cbx subwidget entry] <ButtonRelease-3> { helpwin patch }
## buttons
button $f.patch.br -text "R" -font $ffontb -pady 0 -padx 2 -command {
  set shiftkeypressed 0  ;# fix stuck (not sure how happens)
  select_patch .files.patch.cbx [.files.patch.cbx subwidget entry get]
}
button $f.patch.bw -text "W" -font $ffontb -pady 0 -padx 2 -command {
  set shiftkeypressed 0  ;# fix stuck
  setfile patch [.files.patch.cbx subwidget entry get]
  testreplace $patch write_binary_patch
  #N.B.: can leave csurf dropdown stale
}
button $f.patch.bm -text "M" -font $ffontb -pady 0 -padx 2 -command {
  setfile patch [.files.patch.cbx subwidget entry get]
  read_binary_patch_to_mask
  logcmd "read_binary_patch_to_mask"
  redrawbutton
}
button $f.patch.bc -text "C" -font $ffontb -pady 0 -padx 2 -command {
  setfile patch [.files.patch.cbx subwidget entry get]
  read_binary_patch_to_cut
  logcmd "read_binary_patch_to_cut"
  redrawbutton
}
pack $f.patch.br $f.patch.bw $f.patch.bm $f.patch.bc -side left -padx 0
bind $f.patch.br <ButtonRelease-3> { helpwin patch_read }
bind $f.patch.bw <ButtonRelease-3> { helpwin patch_write }
bind $f.patch.bm <ButtonRelease-3> { helpwin patch_mask }
bind $f.patch.bc <ButtonRelease-3> { helpwin patch_cut }

#### old dipoles (F3 only)
############################################################################
set f .files
edlabval $f "dipoles"    default   w  7 11
setfile dip $dip
setfile dec $dec
$f.dipoles.e config -textvariable dipabbrev
$f.dipoles.bw config -command {
  setfile dip [.files.dipoles.e get]
  testreplace $dip write_binary_dipoles
}
## pack former decimated (plus its extra entry) onto same line as dipoles
$f.dipoles.bw config -text "W" -padx 2
edlabval $f.dipoles "dec"  default  w 4 12 row
pack $f.dipoles.bw -before $f.dipoles.dec -side left ;# else next to other "W"
$f.dipoles.dec.e config -textvariable decabbrev
$f.dipoles.dec.bw config -text "W" -padx 2 -command {
  setfile dec [.files.dipoles.dec.e get]
  if {$dip_spacing > 0.999} {
    subsample_dist $dip_spacing
    logcmd "subsample_dist $dip_spacing"
  } else {
    subsample_orient $dip_spacing
    logcmd "subsample_orient $dip_spacing"
  }
  testreplace $dec write_binary_decimation
}
edlabval $f.dipoles.dec "sp" $dip_spacing  n 3 3 row
$f.dipoles.dec.sp.e config -textvariable dip_spacing
bind $f.dipoles.dec.sp.e  <ButtonRelease-3> { helpwin dip_spacing }
#TODO: new helpfile (when panels stable)
bind $f.dipoles.e <ButtonRelease-3> { helpwin dipoles }
bind $f.dipoles.bw <ButtonRelease-3> { helpwin dipoles_write }
bind $f.dipoles.dec.e <ButtonRelease-3> { helpwin decimated }
bind $f.dipoles.dec.bw <ButtonRelease-3> { helpwin decimated_write }

#### label (display, (re-)cut, clear, read, write, stat/timecourses, xcorr)
############################################################################
set f .files
frame $f.label -padx 0
pack $f.label -side top -fill x -padx 0
### label check
checkbutton $f.label.ck -variable labelflag -padx 0 -bd 0
pack $f.label.ck -side left -padx 0
bind $f.label.ck <ButtonRelease-1> {
  logcmd "set labelflag $labelflag"
  redrawbutton
  labeltickctrls    ;# immed access even w/o R-click
}
# overload label check (middle-click)
bind $f.label.ck <ButtonRelease-2> {
  set vtxcolflag [expr !$vtxcolflag]
  logcmd "set vtxcolflag $vtxcolflag"
  if {$vtxcolflag} {
    confirmalert "show vertex color overlays (if any)"
  } else {
    confirmalert "hide vertex color overlays"
  }
  redrawbutton
}
# second overload label check (shift-middle-click)
bind $f.label.ck <Shift-ButtonRelease-2> {
  set annotbordflag [expr !$annotbordflag]
  logcmd "set annotbordflag $annotbordflag"
  if {$annotbordflag} {
    confirmalert "(1) show only borders of labels/annotations\
              \n\n(2) also affects functions that dump .val's (surface\
                \n        data) from displayed labels/annotations:\
              \n\n    write_val_annoted_vertices (single label)\
                \n    write_val_annotedcol_vertices <r> <g> <b>\
                \n    write_val_annotedcols_vertices"
  } else {
    confirmalert "show full labels/annotations"
  }
  redrawbutton
}
# third overload label check (control-shift-middle-click)
bind $f.label.ck <Control-Shift-ButtonRelease-2> {
  if {!$annotloadedflag && !$annotborddotflag} {  ;# OFF after clear lab OK
    confirmalert "no label/annotation loaded\
              \n\nrequest for white border dots (\$annotborddotflag) ignored"
    break
  }
  set annotborddotflag [expr !$annotborddotflag]
  logcmd "set annotborddotflag $annotborddotflag"
  if {$annotborddotflag} {
    confirmalert "add 1-pix white dots to borders of labels/annotations\
              \n\nN.B.: to make dots less prominent, render at higher res"
  } else {
    confirmalert "don't show white dots at label/annotation borders"
  }
  redrawbutton
}
# fourth overload label check (control-shift-right-click)
bind $f.label.ck <Control-Shift-ButtonRelease-3> {
  if {!$annotborddotflag} {
    confirmalert "no label/annotation dots displayed to prune\
              \n\ndisplay annotation border dots with:\
                \nctrl-shift-mid-click on tick to left of \"label:\""
    break
  }
  prune_annotbord
  logcmd "prune_annotbord"
  confirmalert "Annotation border dots pruned (update on OK)\
            \n\nN.B.: re-read annotation to restore full borders"
  redrawbutton
}
# fifth overload label check (shift-right-click)
bind $f.label.ck <Shift-ButtonRelease-3> {
  set annotmaskflag [expr !$annotmaskflag]
  logcmd "set annotmaskflag $annotmaskflag"
  if {$annotmaskflag} {
    confirmalert "mask overlay by idnum(s) (if any idnum set masked)"
  } else {
    confirmalert "make all idnums visible"
  }
  redrawbutton
}
bind $f.label.ck <Shift-ButtonRelease-1> {
  set padlabelvtxsflag [expr !$padlabelvtxsflag]
  logcmd "set padlabelvtxsflag $padlabelvtxsflag"
  if {$padlabelvtxsflag} {
    confirmalert "label neighbors to better see isolated vertices\
                \n(applies to next label read w/\"D\" on \"label:\" line)"
  } else {
    confirmalert "do not label neighbors of each vertex on label read"
  }
}
# bind right-click help + pop-up
bind $f.label.ck <ButtonRelease-3> {
  helpwin label_toggle
  after 500 { labeltickctrls }
  # bug: (1) mk labeltickctrls, (2) destroy it, (3), mk lut2annotctrls,
  #      (4) mk labeltictrls again: winfo says exists, pops lut2annot instead!
  # workaround: labeltickctrls always destroys - see labeltickctrls
}
### label combo
setfile label $label  ;# create labelabbrev (N.B.: file may not exist)
tixComboBox $f.label.cbx -label "label:" -dropdown true -editable true \
  -variable labelabbrev -listcmd "listcmd_label $f.label.cbx" -listwidth 348 \
  -options "label.width 4 entry.width 18 listbox.height 15" ;# listbox.width 45
bind [$f.label.cbx subwidget label] <ButtonRelease-1> {
  sampclustctrls
  helpwin label_label
}
bind [$f.label.cbx subwidget label] <ButtonRelease-3> { helpwin label_label }
$f.label.cbx subwidget label config -font $ffontb  ;# $ffontb -> clickable lab
$f.label.cbx subwidget entry config -selectforeground black
$f.label.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
set currabbrev $labelabbrev  
$f.label.cbx config -value $currabbrev
pack $f.label.cbx -side left -padx 0
bind [$f.label.cbx subwidget entry] <ButtonRelease-3> { helpwin label }
bind [$f.label.cbx subwidget entry] <Shift-ButtonRelease-3> { helpwin annot }
#bind [$f.label.cbx subwidget entry] <Return> "$f.label.br invoke"
bind [$f.label.cbx subwidget entry] <Return> "labelD_display" ;#vs invoke: nocmd
### buttons -- bind no-arg "label:" line procs (also used by buttonbar)
## label D button (display single/multi-color annot) (was DSP)
button $f.label.br -text "D" -font $ffontb -pady 0 -padx 0
bind $f.label.br <ButtonRelease-1>               { labelD_display }
bind $f.label.br <ButtonRelease-2>               { labelD_undocut }
bind $f.label.br <Shift-ButtonRelease-1>         { labelD_label2roi3d }
bind $f.label.br <Shift-ButtonRelease-2>         { labelD_annot2roi3d }
bind $f.label.br <Shift-ButtonRelease-3>         { labelD_masksubset }
bind $f.label.br <Control-Shift-ButtonRelease-1> { labelD_annots2roi }
bind $f.label.br <Control-ButtonRelease-2>       { labelD_countnei }
bind $f.label.br <Control-ButtonRelease-1>       { labelD_label2select }
bind $f.label.br <Control-Shift-ButtonRelease-3> { labelD_calcoverlap }
bind $f.label.br <Control-ButtonRelease-3>       { labelD_currcol2vtxcol }
bind $f.label.br <Control-Shift-ButtonRelease-2> { labelD_labelcol2vtxcol }
# no bind for labelW_displaynearest b/c all used: buttonbar only
## label C button (cut)
button $f.label.br0 -text "C" -font $ffontb -pady 0 -padx 1 
bind $f.label.br0 <ButtonRelease-1>               { labelC_recut }
bind $f.label.br0 <ButtonRelease-2>               { labelC_hole }
bind $f.label.br0 <Shift-ButtonRelease-2>         { labelC_add }
bind $f.label.br0 <Control-ButtonRelease-1>       { labelC_recutcurr }
bind $f.label.br0 <Control-ButtonRelease-2>       { labelC_holecurr }
bind $f.label.br0 <Control-Shift-ButtonRelease-1> { labelC_recutuniq }
## label CLR button (clear)
button $f.label.bc -text "CLR" -font $ffontb -pady 0 -padx 0
bind $f.label.bc <ButtonRelease-1>         { labelCLR_annot }
bind $f.label.bc <ButtonRelease-2>         { labelCLR_vtxcol }
bind $f.label.bc <Shift-ButtonRelease-2>   { labelCLR_annotvtxcol }
bind $f.label.bc <Control-ButtonRelease-1> { labelCLR_label }
bind $f.label.bc <Control-ButtonRelease-2> { labelCLR_color }
## label R button (read)
button $f.label.br2 -text "R" -font $ffontb -pady 0 -padx 2
bind $f.label.br2 <ButtonRelease-1>         { labelR_val }
bind $f.label.br2 <ButtonRelease-2>         { labelR_vtxcol }
bind $f.label.br2 <Shift-ButtonRelease-2>   { labelR_valcut }
bind $f.label.br2 <Control-ButtonRelease-1> { labelR_uniqsamp }
## label W button (write)
button $f.label.bw -text "W" -font $ffontb -pady 0 -padx 1
bind $f.label.bw <ButtonRelease-1>               { labelW_write }
bind $f.label.bw <ButtonRelease-2>               { labelW_vtxcol }
bind $f.label.bw <Shift-ButtonRelease-2>         { labelW_annot }
bind $f.label.bw <Shift-ButtonRelease-1>         { labelW_annotcol }
bind $f.label.bw <Shift-Control-ButtonRelease-1> { labelW_annotcols }
bind $f.label.bw <Control-ButtonRelease-1>       { labelW_selected }
bind $f.label.bw <Control-ButtonRelease-2>       { labelW_mghannot }
bind $f.label.bw <Shift-Control-ButtonRelease-2> { labelW_searchlights }
bind $f.label.bw <Shift-Control-ButtonRelease-3> { labelW_annotcolname }
bind $f.label.bw <Control-ButtonRelease-3>       { labelW_vtxcol2vtxcol }
bind $f.label.bw <Shift-ButtonRelease-3>         { labelW_writeadjphase }
# no bind for labelW_{randcolannot,sortbydist} b/c all used: buttonbar only
## label T button (time series)
button $f.label.bt -text "T" -font $ffontb -pady 0 -padx 1
bind $f.label.bt <ButtonRelease-1>       { labelT_tseries_at_label }
bind $f.label.bt <Shift-ButtonRelease-1> { labelT_tseries_at_label_amp }
bind $f.label.bt <ButtonRelease-2>       { labelT_tseries_at_annotcol }
bind $f.label.bt <Shift-ButtonRelease-2> { labelT_tseries_all_annotcols }
## label S button (stat/time series)
button $f.label.bst -text "S" -font $ffontb -pady 0 -padx 1
bind $f.label.bst <ButtonRelease-1>         { labelS_stat_tseries_at_label }
bind $f.label.bst <ButtonRelease-2>         { labelS_stat_tseries_at_annotcol }
bind $f.label.bst <Shift-ButtonRelease-2>   { labelS_stat_tseries_all_annotcols}
bind $f.label.bst <Control-ButtonRelease-1> { labelS_stat_at_label }
bind $f.label.bst <Control-ButtonRelease-2> { labelS_stat_at_annotcol }
bind $f.label.bst <Shift-Control-ButtonRelease-2> { labelS_stat_all_annotcols }
## label X button (searchlight cross-corr)
button $f.label.bx -text "X" -font $ffontb -pady 0 -padx 1
bind $f.label.bx <ButtonRelease-1> { labelX_searchlight_corr_at_label }
bind $f.label.bx <ButtonRelease-2> { labelX_searchlight_corr_at_annotcol }
## pack all 8 label buttons
pack $f.label.br $f.label.br0 $f.label.bc $f.label.br2 \
     $f.label.bw $f.label.bt $f.label.bst $f.label.bx -side left
## "label:" line R-click bind: helpwin + no-arg procs buttonbar popups
bind $f.label.br <ButtonRelease-3> {
  helpwin label_read
  buttonbar \
    "\"Display Label or Annot (left-click-D)\" \
     \"Undo Cut with Label (mid-click-D)\" \
     \"Convert Label to 3D ROI (shift-mid-click-D)\" \
     \"Convert One Annot ID to 3D ROI (shift-left-click-D)\" \
     \"Pick Annot Idnums to View/Mask (shift-right-click-D)\" \
     \"All Annots to 3D ROIs (ctrl-shift-left-click-D)\" \
     \"Count/Print annot neighbors (ctrl-mid-click-D)\" \
     \"Read Label to Select (ctrl-left-click-D)\" \
     \"Calc Overlap Annots w/Non-0 (ctrl-shift-right-clk-D)\" \
     \"Copy Current Cols to Vtxcols (ctrl-right-clk-D)\"
     \"Copy Curr Lab/Annot to Vtxcols (ctrl-shift-mid-clk-D)\" \
     \"Display Label on Nearest Vertices (no hotkey)\"" \
    "labelD_display labelD_undocut labelD_label2roi3d labelD_annot2roi3d \
     labelD_masksubset labelD_annots2roi labelD_countnei labelD_label2select \
     labelD_calcoverlap labelD_currcol2vtxcol labelD_labelcol2vtxcol \
     labelD_displaynearest" \
    ver "Label \"D\" (Display) Button" label_read
}
bind $f.label.br0 <ButtonRelease-3> {
  helpwin label_readcut
  buttonbar \
    "\"Re-cut Label File (left-click-C)\" \
     \"Make Hole w/Label File (mid-click-C)\" \
     \"Add Label File to Existing (shift-mid-clk-C)\" \
     \"Re-cut CurrLabeled (ctrl-left-click-C)\" \
     \"Make Hole w/CurrLabeled (ctrl-mid-click-C)\" \
     \"Re-cut Label w/Uniq (ctrl-shift-left-clk-C)\"" \
    "labelC_recut labelC_hole labelC_add \
     labelC_recutcurr labelC_holecurr \
     labelC_recutuniq" \
    ver "Label \"C\" (Cut) Button" label_readcut
}
bind $f.label.bc <ButtonRelease-3> {
  helpwin label_clear
  buttonbar \
    "\"Clear All Annotation (left-click-CLR)\" \
     \"Clear All VtxCol Paint (mid-clk-CLR)\" \
     \"Clear Annot+VtxCol (shift-mid-clk-CLR)\" \
     \"Clear One Label (ctrl-left-click-CLR)\" \
     \"Clear One Color (ctrl-mid-click-CLR)\"" \
    "labelCLR_annot labelCLR_vtxcol labelCLR_annotvtxcol labelCLR_label \
     labelCLR_color" \
    ver "Label \"CLR\" (Clear) Button" label_clear
}
bind $f.label.br2 <ButtonRelease-3> {
  helpwin label_read2val
  buttonbar \
    "\"Read Label -> Val (left-click-R)\" \
     \"Read VtxCol Paint (middle-click-R)\" \
     \"Read/Recut Label->Val (shift-mid-clk-R)\" \
     \"Read Uniqsamp Vtxs (ctrl-left-click-R)\"" \
    "labelR_val labelR_vtxcol labelR_valcut labelR_uniqsamp" \
    ver "Label \"R\" (Read) Button" label_read2val
}
bind $f.label.bw <ButtonRelease-3> {
  helpwin label_write
    buttonbar \
    "\"All Visible To Label (left-click-W)\" \
     \"Labeled Vals to VtxCol (mid-click-W)\" \
     \"Labeled Vals to Label (shift-mid-click-W)\" \
     \"AnnotCol Vals to Label (shift-left-click-W)\" \
     \"AnnotCols Vals to Labels (shift-ctrl-left-clk-W)\" \
     \"Selected Vertices/Vals to Label (ctrl-left-click-W)\" \
     \"Assemble MGH Annot from LUT (ctrl-mid-clk-W)\" \
     \"Searchlights On Label (shift-ctrl-mid-click-W)\" \
     \"AnnotCol Vals to Named (shift-ctrl-right-clk-W)\" \
     \"Write Curr VtxCols to ColsFile (ctrl-right-clk-W)\" \
     \"Write Adjusted Phase to Label (shift-right-clk-W)\" \
     \"Write StatIDs to RandCol MGH Annot (no hotkey)\"
     \"Sort Label By Dist Last Clicked Vtx (no hotkey)\"
     \"Write Region Centers to scriptsdir (no hotkey)\"" \
    "labelW_write labelW_vtxcol labelW_annot labelW_annotcol \
     labelW_annotcols labelW_selected labelW_mghannot labelW_searchlights \
     labelW_annotcolname labelW_vtxcol2vtxcol labelW_writeadjphase \
     labelW_randcolannot labelW_sortbydist labelW_centers" \
    ver "Label \"W\" (Write) Button" label_write  ;# last 2 no-hotkey bind
}
bind $f.label.bt <ButtonRelease-3> {
  helpwin label_timecourses
  buttonbar \
    "\"Dump Time-Series from Label Vtxs (left-click-T)\" \
     \"Same As Above + Avg FT Percent (shift-left-clk-T)\" \
     \"Dump Time-Series from Annot RGB (middle-click-T)\" \
     \"Dump Time-Series All Annots (shift-middle-click-T)\"" \
    "labelT_tseries_at_label labelT_tseries_at_label_amp \
     labelT_tseries_at_annotcol labelT_tseries_all_annotcols" \
    ver "Label \"T\" (Dump TimeCourse) Button" label_timecourses
}
bind $f.label.bst <ButtonRelease-3> {
  helpwin label_stat
  buttonbar \
    "\"Dump Stat+TimeSeries at Label Vtxs (left-click-S)\" \
     \"Dump Stat+TimeSer at Annot RGB (middle-click-S)\" \
     \"Dump Stat+TimeSer All Annots (shift-middle-clk-S)\" \
     \"Dump Just Stat at Label Vtxs (ctrl-left-click-S)\" \
     \"Dump Just Stat at Annot RGB (ctrl-middle-click-S)\" \
     \"Dump Just Stat All Annots (shift-ctrl-middle-clk-S)\"" \
    "labelS_stat_tseries_at_label labelS_stat_tseries_at_annotcol \
     labelS_stat_tseries_all_annotcols labelS_stat_at_label \
     labelS_stat_at_annotcol labelS_stat_all_annotcols" \
    ver "Label \"S\" (Dump Stat +/- TimeCourse) Button" label_stat
}
bind $f.label.bx <ButtonRelease-3> {
  helpwin label_corr
  buttonbar \
    "\"SearchLight CrossCorr at Label Vtxs (left-click-X)\" \
     \"Searchlight CrossCorr at Annot RGB (mid-click-X)\"" \
    "labelX_searchlight_corr_at_label labelX_searchlight_corr_at_annotcol" \
    ver "Label \"X\" (Searchlight CrossCorr) Button" label_corr
}

#=============================
#### lut plus fieldsign frame
#=============================
set f .files
frame $f.lf
pack $f.lf -side top -fill x -padx 2

#### lut (color look up table)
############################################################################
set f .files.lf
frame $f.lut
pack $f.lut -side left -padx 0
### combo
setfile val2rgblut $val2rgblut ;# create val2rgblutabbrev (N.B.: may not exist)
tixComboBox $f.lut.cbx -label "lut:" -dropdown true -editable true \
  -variable val2rgblutabbrev -listcmd "listcmd_lut $f.lut.cbx" \
  -command "select_lut $f.lut.cbx" -listwidth 297 \
  -options "label.width 2 entry.width 10 listbox.height 10" ;# listbox.width 38
$f.lut.cbx subwidget label config -font $ffont
$f.lut.cbx subwidget entry config -selectforeground black
$f.lut.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
set currabbrev $val2rgblutabbrev
$f.lut.cbx config -value $currabbrev
pack $f.lut.cbx -side left -padx 2
$f.lut.cbx subwidget entry xview moveto 1
bind [$f.lut.cbx subwidget entry] <ButtonRelease-3> { helpwin val2rgb }
## buttons
button $f.lut.be -text "ED" -font $ffontb -pady 0 -padx 0
bind $f.lut.be <ButtonRelease-1> { ;# bind b/c break doesn't work in -command
  if [divider [.files.lf.lut.cbx subwidget entry get]] { break }
  setfile val2rgblut [.files.lf.lut.cbx subwidget entry get]
  defmissinglutfile
  editfile $val2rgblut
}
pack $f.lut.be -side left -padx 0
# N.B.: live R click selects PHA[SE], not AMP
button $f.lut.br -text "R" -font $ffontb -pady 0 -padx 1
bind $f.lut.br <ButtonRelease-1> { ;# bind b/c break doesn't work in -command
  if [divider [.files.lf.lut.cbx subwidget entry get]] { break }
  setfile val2rgblut [.files.lf.lut.cbx subwidget entry get]
  if ![file exists $val2rgblut] {
    confirmalert "File not found:\n\n    $val2rgblut"
  } else {
    read_val2rgblut
    logcmd "read_val2rgblut"
    .files.lf.lut.cbx subwidget entry xview moveto 1
    if {$complexvalflag} {
      set colscale 14
      logcmd "set colscale 14"
    } else {
      set colscale 12
      logcmd "set colscale 12"
    }
    redrawbutton
  }
}
pack $f.lut.br -side left -padx 0
button $f.lut.bw -text "W" -font $ffontb -pady 0 -padx 0
bind $f.lut.bw <ButtonRelease-1> { ;# bind b/c break doesn't work in -command
  if [divider [.files.lf.lut.cbx subwidget entry get]] { break }
  setfile val2rgblut [.files.lf.lut.cbx subwidget entry get]
  testreplace $val2rgblut write_val2rgblut
}
pack $f.lut.bw -side left -padx 0
bind $f.lut.be <ButtonRelease-3> { helpwin val2rgb_edit }
bind $f.lut.br <ButtonRelease-3> { helpwin val2rgb_read }
bind $f.lut.bw <ButtonRelease-3> { helpwin val2rgb_write }

#### fieldsign and gradients
############################################################################
set f .files.lf
### buttons -- bind no-arg "label:" line procs (also used for buttonbar)
## old fieldsign (still edlabval, no combo)
edlabval $f "fieldsign"  default  rw 10 20
setfile fs $fs
setfile fm $fm
$f.fieldsign.e config -textvariable fsabbrev
## auto-read fsmask -- read fieldsign suffix but assume fsmask suff is .fm
$f.fieldsign.br config -command {
  setfile fs [.files.lf.fieldsign.e get]
  read_fieldsign
  logcmd "read_fieldsign"
  logcmd "set fieldsignflag $fieldsignflag" ;#read_fieldsign did, report anyway
  setfile fm [string range [.files.lf.fieldsign.e get] 0 \
                [expr [string length [.files.lf.fieldsign.e get]] - 4]].fm
  read_fsmask
  logcmd "read_fsmask"
  if {$fieldsignloaded} {
    set colscale 9   ;# callback reports colscale change
    redrawbutton
  }
}
$f.fieldsign.bw config -command {
   setfile fs [.files.lf.fieldsign.e get]
   setfile fm [string range [.files.lf.fieldsign.e get] 0 \
                [expr [string length [.files.lf.fieldsign.e get]] - 4]].fm
   testreplace $fm write_fsmask_curvfmt
   testreplace $fs write_fieldsign_curvfmt
}
## fieldsign nonbinary control (could omit these)
checkbutton $f.fieldsign.ck -variable nonbinaryfsflag -padx 0 -bd 0
pack $f.fieldsign.ck -side left -before $f.fieldsign.la
bind $f.fieldsign.ck <ButtonRelease-1> {
  logcmd "set nonbinaryfsflag $nonbinaryfsflag"
  if {$nonbinaryfsflag} {
    confirmalert "show nonbinary fieldsign (fs near 0 or Pi is gray)"
  } else {
    confirmalert "show fieldsign as binary (blue=nonmirror, yellow=mirror)"
  }
  fstickctrls    ;# show w/o req. R-click
  redrawbutton
}
## omit fsslope label to save space
#label $f.fieldsign.la2 -text "s:" -font $ffont -pady 0  ;# was "sl"
#pack $f.fieldsign.la2 -side left -before $f.fieldsign.la -padx 0
entry $f.fieldsign.e2 -textvariable fsslope -font $ffont -width 2 \
  -selectforeground black  ;# black: linux
pack $f.fieldsign.e2 -side left -before $f.fieldsign.la -padx 0
bind $f.fieldsign.e2 <Return> { logcmd "set fsslope $fsslope"; redrawbutton }
$f.fieldsign.la config -text "fs:" -width 2
## squish fieldsign for lut
$f.fieldsign.e config -width 5
$f.fieldsign.br config -padx 0 -text R
$f.fieldsign.bw config -padx 0 -text W
pack $f.fieldsign.bw -side left
## fs help
bind $f.fieldsign.ck <ButtonRelease-3> {
  helpwin gradfsarrows
  after 500 { fstickctrls }
}
bind $f.fieldsign.e2 <ButtonRelease-3> { helpwin fsslope }
bind $f.fieldsign.e <ButtonRelease-3> { helpwin fieldsign }
bind $f.fieldsign.br <ButtonRelease-3> { helpwin fieldsign_read }
bind $f.fieldsign.bw <ButtonRelease-3> { helpwin fieldsign_write }
## "fs:" line F (fielsign) button
button $f.fieldsign.bf -text "F" -font $ffontb -pady 0 -padx 0 \
  -command comp_disp_fs
pack $f.fieldsign.bf -side left
bind $f.fieldsign.bf <ButtonRelease-3> { helpwin comp_fs }
## "fs:" line GR button -- gradients on curv/val/phase
##bind no-arg "fs:" line GR procs (also used for buttonbar)
button $f.fieldsign.bg -text GR -font $ffontb -pady 0 -padx 0
pack $f.fieldsign.bg -side left
bind $f.fieldsign.bg <ButtonRelease-1>               { fsGR_2d_curv }
bind $f.fieldsign.bg <ButtonRelease-2>               { fsGR_2d_val }
bind $f.fieldsign.bg <Shift-ButtonRelease-2>         { fsGR_2d_phase }
bind $f.fieldsign.bg <Control-ButtonRelease-1>       { fsGR_surf_curv }
bind $f.fieldsign.bg <Control-ButtonRelease-2>       { fsGR_surf_val }
bind $f.fieldsign.bg <Control-Shift-ButtonRelease-2> { fsGR_surf_phase }
#skip hotkeys for 6 BrainRegAvg buttons

### "fs:" line GR button R-click bind: helpwin + no-arg procs buttonbar popups
#laplacian
set includelaplacian 0
if {$includelaplacian} {
  bind $f.fieldsign.bg <ButtonRelease-3> {
    helpwin comp_grad
    buttonbar \
      "\"Calc 2D/Flat Gradient Curv (left-click-GR)\" \
       \"Calc 2D/Flat Gradient RealVal (mid-click-GR)\" \
       \"Calc 2D/Flat Gradient Phase (shift-mid-clk-GR)\" \
       \"whitespace\" \
       \"Calc Surf Gradient Curv (ctrl-left-click-GR)\" \
       \"Calc Surf Gradient RealVal (ctrl-mid-click-GR)\" \
       \"Calc Surf Gradient Phase (ctrl-shift-mid-clk-GR)\" \
       \"whitespace\" \
       \"Calc 2D/Flat BrainRegAvg Curv (no hotkey)\"
       \"Calc 2D/Flat BrainRegAvg RealVal (no hotkey)\"
       \"Calc 2D/Flat BrainRegAvg Grad Phase (no hotkey)\"
       \"whitespace\" \
       \"Calc Surf BrainRegAvg Curv (no hotkey)\"
       \"Calc Surf BrainRegAvg RealVal (no hotkey)\"
       \"Calc Surf BrainRegAvg Grad Phase (no hotkey)\"
       \"whitespace\" \
       \"Find Gradient Reversals (no hotkey)\"
       \"whitespace\" \
       \"Calc Laplacian Curv (no hotkey)\"
       \"Calc Laplacian RealVal (no hotkey)\"
       \"Calc Laplacian Phase (no hotkey)\"" \
      "fsGR_2d_curv fsGR_2d_val fsGR_2d_phase no-op \
       fsGR_surf_curv fsGR_surf_val fsGR_surf_phase no-op \
       fsGR_2d_avgcurv fsGR_2d_avgval fsGR_2d_avgphase no-op \
       fsGR_surf_avgcurv fsGR_surf_avgval fsGR_surf_avgphase no-op \
       fsGR_findrev no-op \
       fsGR_laplace_curv fsGR_laplace_val fsGR_laplace_phase" \
      ver "Fieldsign \"GR\" (calc gradient arrows) Button" comp_grad
    fstickctrls
  }
} else {
  bind $f.fieldsign.bg <ButtonRelease-3> {
    helpwin comp_grad
    buttonbar \
      "\"Calc 2D/Flat Gradient Curv (left-click-GR)\" \
       \"Calc 2D/Flat Gradient RealVal (mid-click-GR)\" \
       \"Calc 2D/Flat Gradient Phase (shift-mid-clk-GR)\" \
       \"whitespace\" \
       \"Calc Surf Gradient Curv (ctrl-left-click-GR)\" \
       \"Calc Surf Gradient RealVal (ctrl-mid-click-GR)\" \
       \"Calc Surf Gradient Phase (ctrl-shift-mid-clk-GR)\" \
       \"whitespace\" \
       \"Calc 2D/Flat BrainRegAvg Curv (no hotkey)\"
       \"Calc 2D/Flat BrainRegAvg RealVal (no hotkey)\"
       \"Calc 2D/Flat BrainRegAvg Grad Phase (no hotkey)\"
       \"whitespace\" \
       \"Calc Surf BrainRegAvg Curv (no hotkey)\"
       \"Calc Surf BrainRegAvg RealVal (no hotkey)\"
       \"Calc Surf BrainRegAvg Grad Phase (no hotkey)\"
       \"whitespace\" \
       \"Find Gradient Reversals (no hotkey)\"" \
      "fsGR_2d_curv fsGR_2d_val fsGR_2d_phase no-op \
       fsGR_surf_curv fsGR_surf_val fsGR_surf_phase no-op \
       fsGR_2d_avgcurv fsGR_2d_avgval fsGR_2d_avgphase no-op \
       fsGR_surf_avgcurv fsGR_surf_avgval fsGR_surf_avgphase no-op \
       fsGR_findrev" \
      ver "Fieldsign \"GR\" (calc gradient arrows) Button" comp_grad
    fstickctrls
  }
}

#zzzz - make next (and other overloaded tick bind's) into procs for readability
## overload fs nonbinaryfs check w/toggle valbak/val2bak arrows (usu. gradient)
bind $f.fieldsign.ck <ButtonRelease-2> {
  set gradvecbakflag [expr !$gradvecbakflag]
  logcmd "set gradvecbakflag $gradvecbakflag"
  if {$gradvecbakflag && !$gradvecflag} {  ;# if not toggling vec/vecbak
    set arrownormflag 0
    logcmd "set arrownormflag 0"
    set arrowscale 5.0  ;# curv
    logcmd "set arrowscale 5.0"
    set angoffrevarrflag 0
    logcmd "set angoffrevarrflag 0"
  }
  if {$gradvecbakflag} {
    confirmalert "toggle \$gradvecbakflag to $gradvecbakflag:\
              \n\nshow .valbak/.valbak2 as gradient arrows"
  } else {
    confirmalert "toggle \$gradvecbakflag to $gradvecbakflag:;\
              \n\nhide .valbak/.valbak2 gradient arrows"
  }
  redrawbutton
}
## second overload fs nonbinaryfs check w/toggle val/val2 arrows (usu. polar)
bind $f.fieldsign.ck <Shift-ButtonRelease-2> {
  set gradvecflag [expr !$gradvecflag]
  logcmd "set gradvecflag $gradvecflag"
  if {$gradvecflag && !$gradvecbakflag} {  ;# if not toggling vec/vecbak
    set arrownormflag 1
    logcmd "set arrownormflag 1"
    set arrowscale 0.5   ;# mm if arrownormflag
    logcmd "set arrowscale 0.5"
    set angoffrevarrflag 1
    logcmd "set angoffrevarrflag 1"
  }
  if {$gradvecflag} {
    confirmalert "toggle \$gradvecflag to $gradvecflag:\
              \n\nshow .val/.val2 as gradient arrows"
  } else {
    confirmalert "toggle \$gradvecflag to $gradvecflag:\
              \n\nhide .val/.val2 gradient arrows"
  }
  redrawbutton
}
## third overload fs nonbinaryfs check w/toggle val/val2 arrows (usu. polar)
bind $f.fieldsign.ck <Control-ButtonRelease-2> {
  set gradvecbak3dflag [expr !$gradvecbak3dflag]
  logcmd "set gradvecbak3dflag $gradvecbak3dflag"
  if {$gradvecbak3dflag} {  ;# leave other 2 since ignored if 3D
    #set gradvecbakflag 0
    #logcmd "set gradvecbakflag 0"
    #set gradvecflag 0
    #logcmd "set gradvecflag 0"
    set arrownormflag 0
    logcmd "set arrownormflag 0"
    set arrowscale 5.0   ;# curv
    logcmd "set arrowscale 5.0"
    set angoffrevarrflag 1
    logcmd "set angoffrevarrflag 1"
  }
  if {$gradvecbak3dflag} {
    confirmalert "toggle \$gradvecbak3dflag to $gradvecbak3dflag:\
              \n\nshow .val/.val2/.val3 as gradient arrows"
  } else {
    confirmalert "toggle \$gradvecbak3dflag to $gradvecbak3dflag:\
              \n\nhide .val/.val2/.val3 gradient arrows"
  }
  redrawbutton
}

#### val (read, swap, cluster, clear, write)
############################################################################
set f .files
frame $f.val
pack $f.val -side top -fill x -padx 0
### combo
setfile val $val  ;# create valabbrev (N.B.: file may not exist)
tixComboBox $f.val.cbx -label "val:" -dropdown true -editable true \
  -variable valabbrev -listcmd "listcmd_val $f.val.cbx" \
  -command "select_val $f.val.cbx" -listwidth 418 \
  -options "label.width 3 entry.width 27 listbox.height 11" ;# listbox.width 55
$f.val.cbx subwidget label config -font $ffont
$f.val.cbx subwidget entry config -selectforeground black
$f.val.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
set currabbrev $valabbrev
$f.val.cbx config -value $currabbrev
pack $f.val.cbx -side left -padx 1
bind [$f.val.cbx subwidget entry] <ButtonRelease-3> { helpwin val }
bind [$f.val.cbx subwidget entry] <Double-ButtonRelease-1> {
  confirmalert "CURRENT LOCATION\
            \n\n    subj:  $env(SUBJECTS_DIR)/$subject\
            \n\n    sess:  $isession"
}
bind [$f.val.cbx subwidget label] <ButtonRelease-2> { valfiletypectrls }
### buttons
## val R button (read values)
button $f.val.br -text "R" -font $ffontb -pady 0 -padx 1
bind $f.val.br <ButtonRelease-1>       { valR_read }
bind $f.val.br <ButtonRelease-2>       { valR_read_demean_varnorm }
bind $f.val.br <Shift-ButtonRelease-2> { valR_read_cmplxamp_1 }
bind $f.val.br <Shift-ButtonRelease-3> { valR_3frame_mgh_to_vec }
#bind [$f.val.cbx subwidget entry] <Return> "$f.val.br invoke"
bind [$f.val.cbx subwidget entry] <Return> "valR_read" ;# vs. invoke b/c no cmd
## val S/V button (swap stat val, etc)
button $f.val.bs -text "S/V" -font $ffontb -pady 0 -padx 0
bind $f.val.bs <ButtonRelease-1>         { valSV_swap_stat_val }
bind $f.val.bs <ButtonRelease-2>         { valSV_swap_val_val2 }
bind $f.val.bs <Shift-ButtonRelease-2>   { valSV_complex_stack }
bind $f.val.bs <Shift-ButtonRelease-1>   { valSV_swap_pval_val }
bind $f.val.bs <Shift-ButtonRelease-3>   { valSV_curv_curvbak }
bind $f.val.bs <Control-ButtonRelease-3> { valSV_curv_val }
bind $f.val.bs <Control-ButtonRelease-2> { valSV_origarea_val }
bind $f.val.bs <Control-ButtonRelease-1> { valSV_idnum_val }
## val CS button (cluster, FDR)
button $f.val.bu -text "CS" -font $ffontb -pady 0 -padx 0
bind $f.val.bu <ButtonRelease-1>         { valCS_run_surfclust }
bind $f.val.bu <ButtonRelease-2>         { valCS_FDR_ctrls }
## val CLR button (clear, clear all)
button $f.val.bc -text "CLR" -font $ffontb -pady 0 -padx 0 
bind $f.val.bc <ButtonRelease-1> { valCLR_clear_valval2 }
bind $f.val.bc <Shift-ButtonRelease-1> { valCLR_clear_stats }
bind $f.val.bc <ButtonRelease-2> { valCLR_clear_all }
## val W button (multiple)
button $f.val.bw -text "W" -font $ffontb -pady 0 -padx 1
bind $f.val.bw <ButtonRelease-1>               { valW_write }
bind $f.val.bw <ButtonRelease-2>               { valW_FT2percent }
bind $f.val.bw <Control-ButtonRelease-1>       { valW_mgh1D }
bind $f.val.bw <Control-ButtonRelease-2>       { valW_vtkvals }
bind $f.val.bw <Shift-Control-ButtonRelease-2> { valW_vtksurfvals }
bind $f.val.bw <Shift-ButtonRelease-2>         { valW_sphimcurv }
bind $f.val.bw <Shift-ButtonRelease-3>         { valW_sphimstat }
bind $f.val.bw <Shift-ButtonRelease-1>         { valW_sphimvalval2 }
bind $f.val.bw <Shift-Control-ButtonRelease-1> { valW_sphimvalval2baks }
bind $f.val.bw <Shift-Control-ButtonRelease-3> { valW_sphimctrls }
## pack all 5 val buttons
pack $f.val.br $f.val.bs $f.val.bu $f.val.bc $f.val.bw -side left
## "val:" line R-click bind: helpwin + no-arg procs buttonbar popups
bind [$f.val.cbx subwidget label] <ButtonRelease-3> { helpwin val_lab }
bind $f.val.br <ButtonRelease-3> {
  helpwin val_read
  buttonbar \
    "\"Read Valfile, Real Or Complex (left-click-R)\" \
     \"Same As Above + Demean, VarNorm (mid-clk-R)\" \
     \"Read Valfile Real/Imag,Set Amp=1 (shift-mid-clk-R)\" \
     \"Read 3-Frame *.mgh File as Vect (shift-right-clk-R)\"" \
    "valR_read valR_read_demean_varnorm valR_read_cmplxamp_1 \
     valR_3frame_mgh_to_vec" \
    ver "Val \"R\" (Read) Button" val_read
}
bind $f.val.bs <ButtonRelease-3> {
  helpwin swapstatval
  buttonbar \
    "\"Swap Stat/Val (left-click-S/V)\" \
     \"Swap Val/Val2 (mid-click-S/V)\" \
     \"Swap Two Complex (ctrl-mid-clk-S/V)\" \
     \"Swap Pval/Val (ctrl-left-click-S/V)\" \
     \"Swap Curv/Curvbak (shift-right-click-S/V)\" \
     \"Swap Curv/Val (ctrl-right-click-S/V)\" \
     \"Swap OrigArea/Val (ctrl-mid-click-S/V)\"
     \"Copy IDnum to Val (ctrl-left-click-S/V)\"" \
    "valSV_swap_stat_val valSV_swap_val_val2 valSV_complex_stack \
     valSV_swap_pval_val valSV_curv_curvbak valSV_curv_val valSV_origarea_val \
     valSV_idnum_val" \
    ver "Val \"S/V\" (Swap Stack Stuff) Button" swapstatval
}
bind $f.val.bu <ButtonRelease-3> {
  helpwin val_clust
  buttonbar \
    "\"Run SurfCluster (left-click-CS)\" \
     \"FDR Controls Pop-Up (mid-clk-CS)\"" \
    "valCS_run_surfclust valCS_FDR_ctrls" \
    ver "Val \"R\" (Cluster/FDR) Button" val_clust
}
bind $f.val.bc <ButtonRelease-3> {
  helpwin val_clear
  buttonbar \
    "\"Clear Real/Imag DataVal (val,val2) (left-click-CLR)\" \
     \"Clear Stat Values (stat) (shift-left-clk-CLR)\"
     \"Clearall (val,val2,valbaks,stat,pval,uniq) (mid-clk-CLR)\"" \
    "valCLR_clear_valval2 valCLR_clear_stats valCLR_clear_all" \
    ver "Val \"CLR\" (Clear Surface Overlay Data) Button" val_clear
}
bind $f.val.bw <ButtonRelease-3> {
  helpwin val_write
  buttonbar \
    "\"Write Curr Val to *.w File (left-click-W)\" \
     \"Conv FT Amp To Percent (mid-click-W)\" \
     \"Write MGH 1D *.mgh File (ctrl-left-click-W)\" \
     \"Write VTK *.vtk ValOnly File (ctrl-mid-click-W)\" \
     \"Write VTK Surf/Val File (shift-ctrl-mid-click-W)\" \
     \"Write Curv to Sphim (shift-mid-click-W)\" \
     \"Write Stat to Sphim (shift-right-click-W)\" \
     \"Write val/val2 to Sphim (shift-left-click-W)\" \
     \"Write val/val2baks Sphim (shift-ctrl-left-clk-W)\" \
     \"Debug/View SphimPanel (shift-ctrl-right-clk-W)\"" \
    "valW_write valW_FT2percent valW_mgh1D valW_vtkvals valW_vtksurfvals \
     valW_sphimcurv valW_sphimstat valW_sphimvalval2 valW_sphimvalval2baks \
     valW_sphimctrls " \
    ver "Val \"W\" (Write) Button" val_write
}

#### val3d (could add RI=readimag,RM=readmask)
############################################################################
set f .files
frame $f.val3d
pack $f.val3d -side top -fill x -padx 2
### combo
tixComboBox $f.val3d.cbx -label "val3d:" -dropdown true -editable true \
 -variable statpattabbrev -command "select_val3d $f.val3d.cbx" -listwidth 418 \
 -options "label.width 5 entry.width 26 listbox.height 10" ;# listbox.width 55
$f.val3d.cbx subwidget label config -font $ffont
$f.val3d.cbx subwidget entry config -selectforeground black
$f.val3d.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
set fullfilelist [glob -nocomplain $isession/$scandir/*+orig.BRIK]
set fullfilelist "$fullfilelist \
  [glob -nocomplain $isession/$scandir/*_???.bfloat]"
if [llength fullfilelist] { set statpatt [lindex $fullfilelist 0] }
setfile statpatt $statpatt  ;# create abbrev (skip "scan1" def if any files)
set currabbrev $statpattabbrev
set abbrevlist ""
foreach fullfile $fullfilelist {
  setfile statpatt $fullfile; set abbrevlist "$abbrevlist $statpattabbrev"
}
foreach abbrev $abbrevlist { $f.val3d.cbx insert end $abbrev }
setfile statpatt $currabbrev
$f.val3d.cbx config -value $currabbrev
pack $f.val3d.cbx -side left -padx 2
bind [$f.val3d.cbx subwidget entry] <ButtonRelease-3> { helpwin statpatt }
### buttons
button $f.val3d.br -text R -font $ffontb -pady 0 -padx 1 -command {
  setfile statpatt [.files.val3d.cbx subwidget entry get]
  fix_statpatt_if_bfloat
  read_real_or_complex_native_stats
}
button $f.val3d.bw -text "RD" -font $ffontb -pady 0 -padx 0 -command {
  regrawctrls
}
button $f.val3d.bp -text "PA" -font $ffontb -pady 0 -padx 0 -command {
  paint_real_or_complex
  redrawbutton
}
# overload PA (PAINT) button (auto smooth)
bind $f.val3d.bp <ButtonRelease-2> {
  paint_real_or_complex 1  ;# smoothflag
  redrawbutton
}
button $f.val3d.bq -text "UQ" -font $ffontb -pady 0 -padx 1 -command {
  find_uniqsamp_vertices_real_or_complex select
}
button $f.val3d.bv -text "V" -font $ffontb -pady 0 -padx 0 -command {
  dtivecctrls
}
pack $f.val3d.br $f.val3d.bw $f.val3d.bp $f.val3d.bq $f.val3d.bv -side left
bind [$f.val3d.cbx subwidget label] <ButtonRelease-3> { helpwin val_lab }
bind $f.val3d.br <ButtonRelease-3> { helpwin val3d_read }
bind $f.val3d.bw <ButtonRelease-3> { helpwin val3d_raw  }
bind $f.val3d.bp <ButtonRelease-3> { helpwin val3d_paint }
bind $f.val3d.bq <ButtonRelease-3> { helpwin val3d_uniq }
bind $f.val3d.bv <ButtonRelease-3> { helpwin val3d_vecs }
# overload UQ button
bind $f.val3d.bq <ButtonRelease-2> {
  find_uniqsamp_vertices_real_or_complex mklabel
}

#### clicking bold "val" or "val3d" labels swaps readwfile/read3d
############################################################################
$f.val.cbx subwidget label config -font $ffontb
$f.val3d.cbx subwidget label config -font $ffontb
bind [$f.val3d.cbx subwidget label] <ButtonRelease-1> { \
  pack .files.val -after .files.val3d; pack forget .files.val3d }
bind [$f.val.cbx subwidget label] <ButtonRelease-1> { \
  pack .files.val3d -after .files.val; pack forget .files.val; brikfromval }
pack forget .files.val3d  ;# start w/wfile
# detect state: winfo viewable .files.{val,val3d} -> 0,1

#### rgb (tiffoutflag, read, write, write-no-redraw)
############################################################################
set f .files
frame $f.rgb
pack $f.rgb -side top -fill x -padx 2
## combo
setfile rgb $rgb
set rel_rgbname [file tail $rgb]  ;# dir resettable; global for uplevel setfile
tixComboBox $f.rgb.cbx -label "rgb:" -dropdown true -editable true \
  -variable rgbabbrev -listcmd "listcmd_rgb $f.rgb.cbx" \
  -command "select_rgb $f.rgb.cbx" -listwidth 453 \
  -options "label.width 3 entry.width 32 listbox.height 10" ;# listbox.width 60
$f.rgb.cbx subwidget label config -font $ffont
$f.rgb.cbx subwidget entry config -selectforeground black
$f.rgb.cbx subwidget listbox config -font $ffont \
  -selectbackground $selbgcol -selectforeground black
$f.rgb.cbx config -value $rgbabbrev
pack $f.rgb.cbx -side left -padx 0 ;# -pady 0
$f.rgb.cbx subwidget entry xview moveto 1
bind [$f.rgb.cbx subwidget entry] <Return> "$f.rgb.bw invoke"  ;# guess write
bind [$f.rgb.cbx subwidget entry] <ButtonRelease-3> { helpwin rgb }
bind [$f.rgb.cbx subwidget label] <ButtonRelease-3> { showrgbs }
## unlabeled tiffout checkbutton
checkbutton $f.rgb.ck -variable tiffoutflag -padx 0 -bd 0 -command {
  if {$tiffoutflag} {
    setfile rgb [file rootname [.files.rgb.cbx subwidget entry get]].tiff
  } else {
    setfile rgb [file rootname [.files.rgb.cbx subwidget entry get]].rgb
  }
}
pack $f.rgb.ck -side left -padx 0
bind $f.rgb.ck <ButtonRelease-1> { logcmd "set tiffoutflag $tiffoutflag" }
bind $f.rgb.ck <ButtonRelease-3> { helpwin tiffout }
## read, R (display w/nmovie)
button $f.rgb.br -text "R" -font $ffontb -pady 0 -padx 1 -command {
  setfile rgb [.files.rgb.cbx subwidget entry get]
  set rel_rgbname [file tail $rgb]
  logcmd "set rel_rgbname $rel_rgbname"
  if ![file exists $rgb] {
    confirmalert "File not found:\n\n    $rgb"
  } else {
    catch { exec nmovie $rgb & } ret  ;# catch nmovie quit slop
    logcmd "exec nmovie $rgb &"
  }
}
# overload
bind $f.rgb.br <ButtonRelease-2> {
  setfile rgb [.files.rgb.cbx subwidget entry get]
  catch { eval exec nmovie [glob [file dirname $rgb]/*.tiff] & } ret
  logcmd "eval exec nmovie [glob [file dirname $rgb]/*.tiff] &"
}
pack $f.rgb.br -side left -padx 0
bind $f.rgb.br <ButtonRelease-3> { helpwin rgb_read }
## regular write, W
button $f.rgb.bw -text "W" -font $ffontb -pady 0 -padx 0 -command {
  setfile rgb [.files.rgb.cbx subwidget entry get]
  raise_window
  logcmd "raise_window"
  redraw
  logcmd "redraw"
  testreplace $rgb save_rgb_checkfirst
  set rel_rgbname [file tail $rgb]
  logcmd "set rel_rgbname $rel_rgbname"
}
pack $f.rgb.bw -side left -padx 0
bind $f.rgb.bw <ButtonRelease-3> { helpwin rgb_write }
# overload to force write transparent
bind $f.rgb.bw <ButtonRelease-2> {
  if {!$tiffoutflag} {
    confirmalert "can't write SGI RGB w/transparency (tiff OK)"
    break
  }
  setfile rgb [.files.rgb.cbx subwidget entry get]
  raise_window
  logcmd "raise_window"
  redraw
  logcmd "redraw"
  set saveblack2transparentflag $black2transparentflag
  set black2transparentflag 1
  logcmd "set black2transparentflag 1"
  if [testreplace $rgb save_rgb_checkfirst] {
    confirmalert "Wrote 4-byte/pix tiff w/black converted to transparent"
  }
  set black2transparentflag $saveblack2transparentflag
  logcmd "set black2transparentflag $black2transparentflag"
  set rel_rgbname [file tail $rgb]
  logcmd "set rel_rgbname $rel_rgbname"
}
## no pop/redraw WN saves cursor, timecourse
button $f.rgb.bw2 -text "WN" -font $ffontb -pady 0 -padx 1 -command {
  setfile rgb [.files.rgb.cbx subwidget entry get]
  testreplace $rgb save_rgb_checkfirst
  set rel_rgbname [file tail $rgb]
  logcmd "set rel_rgbname $rel_rgbname"
}
pack $f.rgb.bw2 -side left -padx 0
bind $f.rgb.bw2 <ButtonRelease-3> { helpwin rgb_write2 }
# overload to force write transparent
bind $f.rgb.bw2 <ButtonRelease-2> {
  if {!$tiffoutflag} {
    confirmalert "can't write SGI RGB w/transparency (tiff OK)"
    break
  }
  setfile rgb [.files.rgb.cbx subwidget entry get]
  set saveblack2transparentflag $black2transparentflag
  set black2transparentflag 1
  logcmd "set black2transparentflag 1"
  if [testreplace $rgb save_rgb_checkfirst] {
    confirmalert "Wrote 4-byte/pix tiff w/black converted to transparent"
  }
  set black2transparentflag $saveblack2transparentflag
  logcmd "set black2transparentflag $black2transparentflag"
  set rel_rgbname [file tail $rgb]
  logcmd "set rel_rgbname $rel_rgbname"
}

#### REDRAW, RESTORE, SEND, GOTO
#############################################################################
set f .draw.main

### REDRAW
buttons $f "REDRAW" { } row 3 0 
bind $f.aREDRAW.bu <ButtonRelease-1> {
  if {$stereoflag} { confirmalert "don't display stereo" }
  set stereoflag 0
  logcmd "set stereoflag 0"
  set convergentflag 0           ;# silent restore def
  logcmd "set convergentflag 0"
  redrawbutton
}
bind $f.aREDRAW.bu <ButtonRelease-2> {
  set stereoflag 1
  logcmd "set stereoflag 1"
  set convergentflag 0
  logcmd "set convergentflag 0"
  confirmalert "display brain for divergent stereo"
  redrawbutton
}
bind $f.aREDRAW.bu <Shift-ButtonRelease-2> {
  set stereoflag 1
  logcmd "set stereoflag 1"
  set convergentflag 1
  logcmd "set convergentflag 1"
  confirmalert "display brain for convergent stereo"
  redrawbutton
}
bind $f.aREDRAW.bu <Control-ButtonRelease-2> {
  set lighttwosidedflag [expr !$lighttwosidedflag]
  logcmd "set stereoflag $lighttwosidedflag"
  if {$lighttwosidedflag} {
    confirmalert "set lighttwosidedflag 1\
              \n\nlight back/inside surfaces\
              \n\n(again to toggle OFF)"
    redrawbutton  ;# hack (2x) to fix rand inside color of init redraw
  } else {
    confirmalert "set lighttwosidedflag 0\
              \n\ndon't light back/inside surfaces\
              \n\n(again to toggle ON)"
  }
  redrawbutton   ;# do_lighting_model
}
bind $f.aREDRAW.bu <Shift-ButtonRelease-3> {
  lightsctrls
}
bind $f.aREDRAW.bu <Control-ButtonRelease-3> {
  set multitimecourseflag [expr !$multitimecourseflag]
  logcmd "set multitimecourseflag $multitimecourseflag"
  if {$multitimecourseflag} {
    confirmalert "set multitimecourseflag 1\
              \n\noverlay multiple single-voxel timecourses\
              \n\n(again to toggle OFF)"
  } else {
    confirmalert "set multitimecourseflag 0\
              \n\ndon't overlay single-voxel timecourses\
              \n\n(again to toggle ON)"
  }
}
bind $f.aREDRAW.bu <Shift-ButtonRelease-1> {
  set bigcursorflag [expr !$bigcursorflag]
  logcmd "set bigcursorflag $bigcursorflag"
  if {$bigcursorflag} {
    confirmalert "set bigcursorflag 1\
              \n\nturn ON big cursor\
              \n\n(again to toggle OFF)"
  } else {
    confirmalert "set bigcursorflag 0\
              \n\nturn OFF big cursor\
              \n\n(again to toggle ON)"
  }
}
# no-arg event generate procs for buttonbar buttons
proc redraw_orig { } {
  event generate .draw.main.aREDRAW.bu <ButtonRelease-1>
}
proc redraw_divergentstereo { } {
  event generate .draw.main.aREDRAW.bu <ButtonRelease-2>
}
proc redraw_convergentstereo { } {
  event generate .draw.main.aREDRAW.bu <Shift-ButtonRelease-2>
}
proc redraw_lighttwosided { } {
  event generate .draw.main.aREDRAW.bu <Control-ButtonRelease-2>
}
proc redraw_lightsctrls { } {
  event generate .draw.main.aREDRAW.bu <Shift-ButtonRelease-3>
}
proc redraw_multitimecourse { } {
  event generate .draw.main.aREDRAW.bu <Control-ButtonRelease-3>
}
proc redraw_bigcursor { } {
  event generate .draw.main.aREDRAW.bu <Shift-ButtonRelease-1>
}
# buttonbar
bind $f.aREDRAW.bu <ButtonRelease-3> {
  helpwin redraw
  buttonbar \
    "\"REDRAW (if stereo, bak to single) (left-click-REDRAW)\" \
     \"Divergent Stereo REDRAW (mid-click-REDRAW)\" \
     \"Convergent Stereo REDRAW (shift-mid-clk-REDRAW)\" \
     \"Toggle Light Inside/Back Surf (ctrl-mid-clk-REDRAW)\" \
     \"Lights Bright/Position Popup (shift-R-clk-REDRAW)\"
     \"Toggle Disp Mult Timecourses (ctrl-R-clk-REDRAW)\" \
     \"Toggle BigCursor (shows neigh) (shift-L-clk-REDRAW)\"" \
    "redraw_orig redraw_divergentstereo redraw_convergentstereo \
     redraw_lighttwosided redraw_lightsctrls redraw_multitimecourse \
     redraw_bigcursor" \
    ver "REDRAW Button" redraw
}
$f.aREDRAW.bu config -font $ffontbb

### RESTORE
buttons $f "RESTORE" { } row 2 0
# left-click command -> bind for button bar
bind $f.aRESTORE.bu <ButtonRelease-1> { restore }  ;# logs cmds
# first overload
bind $f.aRESTORE.bu <ButtonRelease-2> {
  recalc_surface_center
  logcmd "recalc_surface_center"
  restore
  confirmalert "recalculated surface center, using new center"
}
# second overload
bind $f.aRESTORE.bu <Shift-ButtonRelease-1> {
  confirmalert "restore_zero_position (before rotate to lateral view)"
  restore_zero_position
  logcmd "restore_zero_position"
  redrawbutton
}
# third overload
bind $f.aRESTORE.bu <Shift-ButtonRelease-2> {
  if [okreplace ""\
          "OK to really center/move brain surface coordinates?\
       \n\n(N.B.: may misalign a folded surf with struct!)\
         \n(N.B.: no permanent effect unless saved w/F3 panel)" \
       "Really Center Brain"] {
    really_center_brain
    logcmd "really_center_brain"
    restore
  } else { confirmalert "brain not centered/moved" }
}
# no-arg event generate procs for buttonbar buttons
proc restore_orig { } {
  event generate .draw.main.aRESTORE.bu <ButtonRelease-1>
}
proc restore_zeropos { } {
  event generate .draw.main.aRESTORE.bu <Shift-ButtonRelease-1>
}
proc restore_recenterdisplay { } {
  event generate .draw.main.aRESTORE.bu <ButtonRelease-2>
}
proc restore_recentercoords { } {
  event generate .draw.main.aRESTORE.bu <Shift-ButtonRelease-2>
}
# buttonbar
bind $f.aRESTORE.bu <ButtonRelease-3> {
  helpwin restore
  buttonbar \
    "\"Restore original brain pose (left-click-RESTORE)\" \
     \"Restore zero pos before rot->lat (shift-L-clk-RESTORE)\" \
     \"Recalc Disp Center, coords unchanged (mid-clk-RES.)\" \
     \"ReCent Coords (misaligns surf/3D) (shift-mid-clk-RES.)\"" \
    "restore_orig restore_zeropos \
     restore_recenterdisplay restore_recentercoords" \
    ver "RESTORE Button" restore
}
$f.aRESTORE.bu config -font $ffontbb

### SEND/GOTO
buttons $f "SEND PNT" {
  if {$selected == -1} {
    confirmalert "no vertex selected"
  } else {
    find_orig_vertex_coordinates
    logcmd "find_orig_vertex_coordinates"
  }
} row 1 1
## removed from SEND PNT since requires xhost +
#  findsendto
#  logcmd "findsendto"
#  catch {send tkanalyse { goto_point; redraw; set curslice $curslice } }
#  catch { send $fulltkmedit { goto_point; redraw; unzoomcoords $plane; \
#                              sendupdate; sendgoto } }
#  catch { send $fulltkregister { goto_point; set updateflag 1; \
#                                 unzoomcoords $plane } }
buttons $f "GOTO PNT" {
  select_orig_vertex_coordinates
  logcmd "select_orig_vertex_coordinates"
} row 1 1
bind "$f.aSEND PNT.bu" <ButtonRelease-3> { helpwin save_pnt }
bind "$f.aGOTO PNT.bu" <ButtonRelease-3> { helpwin goto_pnt }
# alt mirror GOTO
bind "$f.aGOTO PNT.bu" <ButtonRelease-2> {
  if ![string match fsaverage* $subject] {
    confirmalert "GOTO opposite hemisphere point only accurate on fsaverage\
             \n\n    . . . (doing GOTO anyway)"
  }
  raise_window   ;# get back focus from popup
  logcmd "raise_window"
  select_opphemi_vertex_coordinates
  logcmd "select_opphemi_vertex_coordinates"
}
# F3 panel only
buttons $f "FlipHemi" {
  if [okreplace ""\
          "OK to really mirror-image x,y,z surface coordinates?\
       \n\n(N.B.: will misalign a folded surf with struct images!)\
         \n(N.B.: no permanent effect unless surf saved w/F3 panel)" \
       "Really Flip Brain"] {
    really_flip_brain_x
    logcmd "really_flip_brain_x"
    compute_normals_areas
    logcmd "compute_normals_areas"
    rotate_brain_y 180
    logcmd "rotate_brain_y 180"
    redraw
  } else { confirmalert "brain not flipped" }
} row 1 1
bind $f.aFlipHemi.bu <ButtonRelease-3> { helpwin fliphemi }
# tksurfer help, print_hist
button $f.bu -text "h" -font $ffontb -pady 1 -padx 0 -command {
  helpwin $env(CSURF_DIR)/lib/help/csurf/tksurfer
}
# 2nd overload histogram controls
bind $f.bu <ButtonRelease-2> { histctrls }
bind $f.bu <ButtonRelease-3> { helpwin hbutt }
pack $f.bu -side left -padx 0

### blinkbuffer (TODO: update read_second_binary_surf -> tri, macro: rm PNT's)
#set f .draw.main
#set redraw2flag 0
#label $f.sp -width 1 -bg $bgcol
#pack $f.sp -side left
#buttons $f RD2 { redraw_second } row 2 2
#buttons $f RS2 { restore_second } row 2 2
#buttons $f CPM { \
#  if {$redraw2flag} { redraw_second; set redraw2flag 0 } \
#  else              { redraw; set redraw2flag 1 } } row 2 2

#### ROTATE, TRANSLATE, SCALE
set f .draw.main

### ROTATE (also zrot, winxy)
#############################################################################
set f .xform.rotate.top
### label
label $f.la -text "ROTATE (deg)" -font $ffontb -pady 0
pack $f.la -side top
bind $f.la <ButtonRelease-3> { helpwin brainpose }
### horiz
scale $f.y -from 180 -to -180 -length $sclenx -variable yrot \
    -orient horizontal -tickinterval 90 -showvalue false -font $sfont -width 11
pack $f.y -side top
#xxxxx -- still occasional runaway yrot, etc, increment
bind $f.y <ButtonRelease-1> { redrawbutton }
#bind $f.y <B1-Motion> { redrawbutton }  ;# transform does curr, not 0/pushed
### vertical
set f .xform.rotate.bot
scale $f.x -from 180 -to -180 -length $scleny -variable xrot \
    -orient vertical -tickinterval 90 -showvalue false -font $sfont -width 11
pack $f.x -side left ;# -anchor e
bind $f.x <ButtonRelease-1> { redrawbutton }
### entries
set f .xform.rotate.bot.la
edlabval $f "yrot" 0 n 5 4
edlabval $f "xrot" 0 n 5 4
edlabval $f "zrot" 0 n 5 4
$f.yrot.e config -textvariable yrot -font $sfont
$f.xrot.e config -textvariable xrot -font $sfont
$f.zrot.e config -textvariable zrot -font $sfont
$f.yrot.la config -font $sfont
$f.xrot.la config -font $sfont
$f.zrot.la config -font $sfont
bind $f.xrot.e <Return> { redrawbutton }
bind $f.yrot.e <Return> { redrawbutton }
bind $f.zrot.e <Return> { redrawbutton }
### jam in unrelated winxy
edlabval $f "winxy" 0 n 5 4 col
$f.winxy.e config -textvariable glwinxydim -font $sfont
bind $f.winxy.e <Return> {
  resize_window $glwinxydim
  logcmd "resize_window $glwinxydim"
  after 100 { redrawbutton }
  after 500 { set glwinxydim $glxwinw }
}
pack $f.zrot.e -pady 13
bind $f.xrot.e <ButtonRelease-3> { helpwin xrot }
bind $f.yrot.e <ButtonRelease-3> { helpwin yrot }
bind $f.zrot.e <ButtonRelease-3> { helpwin zrot }
bind $f.winxy.e <ButtonRelease-3> { helpwin winxy }

### TRANSLATE (also: save/goto view, DIST, Dijk, coord isocont, closeup select)
#############################################################################
set f .xform.translate.top
### label
label $f.la -text "TRANSLATE (mm/scale)" -font $ffontb -pady 0
pack $f.la -side top
bind $f.la <ButtonRelease-3> { helpwin brainpose }
### horiz
scale $f.x -from -100 -to 100 -length $sclenx -variable xtrans \
   -orient horizontal -tickinterval 50 -showvalue false -width 11 -font $sfont
pack $f.x -side top
bind $f.x <ButtonRelease-1> { redrawbutton }
### vertical
set f .xform.translate.bot
scale $f.y -from 100 -to -100 -length $scleny -variable ytrans \
    -orient vertical -tickinterval 50 -showvalue false -width 11 -font $sfont
pack $f.y -side left -padx 0
bind $f.y <ButtonRelease-1> { redrawbutton }

### subdivide translate entries frame (top/bot, top->right/left)
set f .xform.translate.bot.la
frame $f.top -bg $bgcol
frame $f.bot -bg $bgcol
pack $f.top $f.bot -side top -padx 0
frame $f.top.le -bg $bgcol
frame $f.top.ri -bg $bgcol
pack $f.top.le -side left -padx 0
pack $f.top.ri -side left -padx 10
### entries
set f .xform.translate.bot.la.top.le
edlabval $f "x" 0 n 2 4
edlabval $f "y" 0 n 2 4
$f.x.e config -textvariable xtrans -font $sfont
$f.y.e config -textvariable ytrans -font $sfont
$f.x.la config -font $sfont
$f.y.la config -font $sfont
bind $f.x.e <Return> { redrawbutton }
bind $f.y.e <Return> { redrawbutton }
bind $f.x.e <ButtonRelease-3> { helpwin xtrans }
bind $f.y.e <ButtonRelease-3> { helpwin ytrans }
### insert save/restore pose: Save/Goto View
set f .xform.translate.bot.la.top.ri
# View
label $f.la -text "View" -font $ffontb -pady 0
bind $f.la <ButtonRelease-1> {
  set surfermatlist [glob -nocomplain $subjtmpdir/surfer.mat*]
  set ffi "These buttons can save and restore particular brain poses.\
         \nCurrently available view matrices saved in:\n\n    $subjtmpdir\
       \n\nare:\n"
  if {"$surfermatlist" != ""} {
    foreach fi $surfermatlist { set ffi "$ffi\n    [file tail $fi]" }
    unset fi
  } else {
    set ffi "$ffi\n    \[none saved yet\]"
  }
  confirmalert "$ffi\
        \n\n(1) Left-click Save/Goto below to use default file \"surfer.mat\"\
        \n\n      *or*\
        \n\n(2) Middle-click Save/Goto below to create/select file with suffix\
          \n       (surfer.mat<suffix> where suffix is, e.g., \"-MT_closeup\")"
  unset ffi
}
# Save
button $f.bu -text "Save" -font $ffontb -pady 0 -padx 0 -command {
  write_view_matrix
  logcmd "write_view_matrix"
  if [file exists $subjtmpdir/$viewmatrix] {
    puts "[exec cat $subjtmpdir/$viewmatrix]"
  } else {
    confirmalert "Save View: failed\n\nCouldn't write $subjtmpdir/surfer.mat"
  }
}
# alt SAVE
bind $f.bu <ButtonRelease-2> {
  set surfermatlist [glob -nocomplain $subjtmpdir/surfer.mat*]
  set ffi ""
  if {"$surfermatlist" != ""} {
    foreach fi $surfermatlist {
      if { [file tail $fi] != "surfer.mat"} {
        set ffi "$ffi\n[string range [file tail $fi] 10 end]"
      } else {
        set ffi "\[no suffix\]"
      }
    }
    unset fi
  } else {
    set ffi "\n\[none saved yet\]"
  }
  set vmsuffctrlswin \
    [controls "Suffix to append to view matrix\
             \n([file tail $viewmatrix]) before Save-ing it\
           \n\nExisting surfer.mat suffixes:\
           \n\n$ffi\n"
      viewmatrixsuff READY "do_getvmsuff write" 20]
  unset ffi
}
# GoTo
button $f.bu2 -text "Goto" -font $ffontb -pady 0 -padx 0 -command {
  if [file exists $subjtmpdir/$viewmatrix] {
    read_view_matrix
    logcmd "read_view_matrix"
    puts "[exec cat $subjtmpdir/$viewmatrix]"
    redrawbutton
  } else {
    confirmalert "Goto View: view matrix:\n\n     $subjtmpdir/$viewmatrix\
              \n\nnot found\n\nFirst do \"View: Save\""
  }
}
# alt GoTo
bind $f.bu2 <ButtonRelease-2> {
  set surfermatlist [glob -nocomplain $subjtmpdir/surfer.mat*]
  set ffi ""
  if {"$surfermatlist" != ""} {
    foreach fi $surfermatlist {
      if { [file tail $fi] != "surfer.mat"} {
        set ffi "$ffi\n[string range [file tail $fi] 10 end]"
      } else {
        set ffi "\[no suffix\]"
      }
    }
    unset fi
  } else {
    set ffi "\n\[none saved yet\]"
  }
  set vmsuffctrlswin [controls \
       "Use view matrix ([file tail $viewmatrix])\
      \nwith this suffix for Goto \
   \n\nExisting surfer.mat suffixes:\
   \n\n$ffi\n" \
  viewmatrixsuff READY "do_getvmsuff read" 20]
  unset ffi
}
pack $f.la $f.bu $f.bu2 -side top -pady 0
bind $f.la <ButtonRelease-3> { helpwin saveview }
bind $f.bu <ButtonRelease-3> { helpwin saveview }
bind $f.bu2 <ButtonRelease-3> { helpwin saveview }
### insert unrelated DIST/Dijk buttons, isocont butt below
set f .xform.translate.bot.la.bot
frame $f.sp -height 5
pack $f.sp -side top
frame $f.bus
frame $f.tks
pack $f.bus $f.tks -side top
## DIST
button $f.bus.bu -text "DIST" -font $ffontb -pady 0 -padx 1 -command {
  if {$nmarked < 2} {
    confirmalert "first select at least two vertices (last 2 used)"
  } else {
    print_dist_last2_selected
    logcmd "print_dist_last2_selected"
   confirmalert "Euclidean distance between last 2 selected: $genstrret_1k mm"
  }
}
pack $f.bus.bu -side left -padx 2
# first overload: avg intervtx dist
bind $f.bus.bu <ButtonRelease-2> {
  compute_avg_edgewidth
  logcmd "compute_avg_edgewidth"
  logcmd \
    "# avg inter-vertex dist on curr surf ($hemi.$surfext) = $genstrret_1k mm"
  confirmalert "average inter-vertex distance on current surf ($hemi.$surfext):\
            \n\n    [lindex $genstrret_1k 0] mm\
            \n\n$vertexcnt  vertices\
              \n$facecnt  faces\
              \n[lindex $genstrret_1k 1]  edges"
}
bind $f.bus.bu <ButtonRelease-3> { helpwin dist }
## Dijk
button $f.bus.bu2 -text "Dijk" -font $ffontb -pady 0 -padx 0 -command getdijk2
pack $f.bus.bu2 -side left -padx 2
bind $f.bus.bu2 <ButtonRelease-3> { helpwin dijk }
## isocont
checkbutton $f.tks.ck -variable isocontourflag -font $ffont -text "isocont" \
  -command {
  if { $isocontourflag } {
    if {![file exists $env(SUBJECTS_DIR)/$subject/$surfdir/$hemi.sphere.reg]} {
      confirmalert "$hemi.sphere.reg not found (for sphere coords)"
    } else {
      isoconttickctrls
    }
  }
  logcmd "set isocontourflag $isocontourflag"
}
pack $f.tks.ck -side left ;# top
bind $f.tks.ck <ButtonRelease-1> { redrawbutton }
bind $f.tks.ck  <ButtonRelease-3> {
  helpwin isocont
  isoconttickctrls
}
## clo
checkbutton $f.tks.ck2 -variable selectcloseflag -font $ffont -text "clo" \
  -command {
  if { $selectcloseflag } {
    set selectdmax 0.25
    confirmalert "set selectdmax 0.25 mm\
              \n\nEasier to select deep vertex near vertical surface\
                \nN.B.: requires more accurate click!"
  } else {
    set selectdmax 2.0
    confirmalert "set selectdmax 2.0 mm (default)"
  }
  logcmd "set selectdmax $selectdmax"
}
# one overload: setup select inside
bind $f.tks.ck2  <ButtonRelease-2> {
  set selectinsideflag [expr !$selectinsideflag]
  logcmd "set selectinsideflag $selectinsideflag"
  if {$selectinsideflag} {
    set lighttwosidedflag 1
    logcmd "set lighttwosidedflag 1"
    set light1 1.0
    logcmd "set light1 1.0"
    confirmalert "select vertices on INSIDE surface\
             \n\n(N.B.: disables normal select! middle-click again to revert)"
  } else {  ;# leave lighttwosidedflag, light1 modified
    confirmalert "select vertices on outside surface (normal operation)"
  }
  redrawbutton
}
pack $f.tks.ck2 -side left
bind $f.tks.ck2  <ButtonRelease-3> { helpwin selectdmax }

### SCALE
#############################################################################
set f .xform.scale.top
### label
label $f.la -text "SCALE (%)" -font $ffontb -pady 0
pack $f.la -side top
bind $f.la <ButtonRelease-3> { helpwin brainpose }
### vertical
scale $f.xyz -from 300 -to 1 -length [expr $sclenymag] -variable scalepercent \
   -orient vertical -tickinterval 100 -showvalue false -font $sfont -width 11
pack $f.xyz -side top -expand false
bind $f.xyz <ButtonRelease-1> { redrawbutton }
### entry
set f .xform.scale.bot
edlabval $f "%" 0 n 2 4
$f.%.e config -textvariable scalepercent -font $sfont
$f.%.la config -font $sfont
bind $f.%.e <Return> { redrawbutton }
bind $f.%.e <ButtonRelease-3> { helpwin scalepercent }

### BGcolor radiorow
set f .draw.curvswitch
radios $f "ColScales" "none" surfcolor  0 10 row
radios $f ""          "curv" surfcolor  1 10 row
radios $f ""          "a"   surfcolor  2 10 row
radios $f ""          "s"   surfcolor 3 10 row
$f.anone.ra config -bd 0 -padx 0  ;# squish first radio
foreach w "none curv a s" { $f.a$w.ra config -bd 0 -padx 0 } ;# squish radio
pack $f.anone.ra -side left -padx 0
bind $f.anone.ra <ButtonRelease-1> {
  logcmd "set surfcolor $surfcolor"
  redrawbutton
}
bind $f.acurv.ra <ButtonRelease-1> {
  logcmd "set surfcolor $surfcolor"
  redrawbutton
}
# parallel to mid-click on F2 panel "curv" tickbox
bind $f.acurv.ra <ButtonRelease-2> {
  set nobicurvfadeoverfthresh [expr !$nobicurvfadeoverfthresh]
  logcmd "set nobicurvfadeoverfthresh $nobicurvfadeoverfthresh"
  confirmalert "set nobicurvfadeoverfthresh $nobicurvfadeoverfthresh\
             \n\n   0: default: separate fade to sulc/gyrus colors\
               \n   1: no separate fade if overlay amp above \$fthresh"
}
bind $f.aa.ra <ButtonRelease-1> {
  logcmd "set surfcolor $surfcolor"
  redrawbutton
}
bind $f.as.ra <ButtonRelease-1> {
  logcmd "set surfcolor $surfcolor"
  redrawbutton
}
# more compact replacement for radio on small panel
set showcurvflag $surfcolor  ;# init: cp radio
checkbutton $f.ck0 -text "curv" -font $ffont -variable showcurvflag \
  -padx 0 -bd 0
bind $f.ck0 <ButtonRelease-1> {
  set surfcolor $showcurvflag
  logcmd "set surfcolor $surfcolor"
  redrawbutton
}
bind $f.ck0 <ButtonRelease-2> {
  if {$overlayflag} {
    set nobicurvfadeoverfthresh [expr !$nobicurvfadeoverfthresh]
    logcmd "set nobicurvfadeoverfthresh $nobicurvfadeoverfthresh"
    if {$nobicurvfadeoverfthresh} {
      confirmalert "set nobicurvfadeoverfthresh 1\
                \n\nPrevent seperate overlay fade into sulc/gyrus color\
                  \nif overlay amp above fthresh\
                \n\n(only affects complex-valued color scales)"
      if {$fthresh < $fmid} {
        confirmalert "N.B.: \$fthresh < \$fmid:\
                  \n\nThis will disturb sulc/gyrus pattern (more dark gray)\
                    \nin regions where overlay amplitude is above fthresh\
                    \nbut below fmid"
      }
    } else {
      confirmalert "set nobicurvfadeoverfthresh 0\
                \n\nRestore seperate fade into sulc/gyrus color\
                \n\n(only affects complex-valued color scales)"
    }
    redrawbutton
  } else {
    confirmalert "toggle nobicurvfadeoverfthresh:\
             \n\n### no overlay\
            \n\n\$nobicurvfadeoverfthresh (=$nobicurvfadeoverfthresh) unchanged"
  }
}
pack $f.ck0 -side left -padx 0
entry $f.e0 -textvariable offset -font $ffont -width 3 -selectforeground black
entry $f.e1 -textvariable cvfact -font $ffont -width 3 -selectforeground black
pack $f.e0 $f.e1 -side left
bind $f.e0 <Return> { logcmd "set offset $offset"; redrawbutton }
bind $f.e1 <Return> { logcmd "set cvfact $cvfact"; redrawbutton }
#frame $f.sp0; pack $f.sp0 -side left -padx 2  ;# TODO: toggle off in F2
checkbutton $f.ck -variable interpolatelutflag -text "intp" -font $ffont \
  -bd 0 -padx 0
pack $f.ck -side left -padx 0
checkbutton $f.ck2 -variable botedgelutflag -text "bot" -font $ffont \
  -bd 0 -padx 0
pack $f.ck2 -side left -padx 0
checkbutton $f.ck3 -variable zerosymmfadeflag -text "sym" -font $ffont \
  -bd 0 -padx 0
pack $f.ck3 -side left -padx 0
bind $f.ck <ButtonRelease-1> {
  logcmd "set interpolatelutflag $interpolatelutflag"
  redrawbutton
}
bind $f.ck2 <ButtonRelease-1> {
  logcmd "set botedgelutflag $botedgelutflag"
  if {$botedgelutflag} {
    confirmalert "real/amp LUT:  set botedgelutflag $botedgelutflag\
              \n\nColor LUT val entries define bottom of color range"
  } else {
    confirmalert "real/amp LUT:  set botedgelutflag $botedgelutflag\
              \n\nColor LUT val entries define center of color range"
  }
  redrawbutton
}
bind $f.ck3 <ButtonRelease-1> {
  logcmd "set zerosymmfadeflag $zerosymmfadeflag"
  if {$zerosymmfadeflag} {
    confirmalert "real/amp LUT, Jet:  set zerosymmfadeflag $zerosymmfadeflag\
              \n\n(s)fthresh/(s)fmid fade symmetrically around 0"
  } else {
    confirmalert "real/amp LUT, Jet:  set zerosymmfadeflag $zerosymmfadeflag\
              \n\n(s)fthresh/(s)fmid fade toward 0, one-sided"
  }
  redrawbutton
}
bind $f.anone.la <ButtonRelease-3> { helpwin curv_bgcol }
bind $f.anone.ra <ButtonRelease-3> { helpwin curv_none }
bind $f.acurv.ra <ButtonRelease-3> { helpwin curv_curv }
#TODO: new helpfile (when panels stable -- next 2)
bind $f.aa.ra <ButtonRelease-3> { helpwin curv_area }
bind $f.as.ra <ButtonRelease-3> { helpwin curv_shear }
bind $f.e0 <ButtonRelease-3> { helpwin offset }  ;# dup
bind $f.e1 <ButtonRelease-3> { helpwin cvfact }  ;# dup
bind $f.ck <ButtonRelease-3> { helpwin intplut }
bind $f.ck0 <ButtonRelease-3> { helpwin curv_tick }
bind $f.ck2 <ButtonRelease-3> { helpwin botedge }
bind $f.ck3 <ButtonRelease-3> { helpwin zerosymm }

### Colscale RadioButton Row (14 color scales)
#############################################################################
set f .draw.valswitch
#     frm titl lab    var  val wi rowcol
# complex
radios $f "z" "w1"  colscale 0 0 row;  $f.aw1.ra config -padx 0
destroy $f.aw1.la  ;# squish empty label space
radios $f ""  "w2"  colscale 8 2 row;  $f.aw2.ra config -padx 0
radios $f ""  "w3"  colscale 16 2 row; $f.aw3.ra config -padx 0
radios $f ""  "w4"  colscale 18 2 row; $f.aw4.ra config -padx 0
radios $f ""  "ht"  colscale 1 2 row;  $f.aht.ra config -padx 0
# positive
radios $f ""  "bi"  colscale 4 2 row;  $f.abi.ra config -padx 0
#radios $f "" "br"  colscale 2 2 row
#radios $f "" "bgr" colscale 3 2 row
#radios $f "" "gr"  colscale 5 2 row
# signed
radios $f ""  "BRy" colscale 11 2 row; $f.aBRy.ra config -padx 0
radios $f ""  "BR"  colscale 6 2 row;  $f.aBR.ra config -padx 0
radios $f ""  "GR"  colscale 7 2 row;  $f.aGR.ra config -padx 0
radios $f ""  "lt"  colscale 12 2 row; $f.alt.ra config -padx 0
#radios $f "" "ltw" colscale 14 2 row; $f.alt.ra config -padx 0  ;# complex
radios $f ""  "fs"  colscale 9 2 row;  $f.afs.ra config -padx 0
#radios $f ""  "jt"  colscale 15 2 row; $f.ajt.ra config -padx 0
## move several radio buttons up to next row (room for w3)
#TODO; separate radios from ticks, deal with F2/F3
radiobutton .draw.curvswitch.ra2 -text "ltw" -variable colscale -value 14 \
  -font $ffont -bd 0 -padx 0
radiobutton .draw.curvswitch.ra -text "jet" -variable colscale -value 15 \
  -font $ffont -bd 0 -padx 0
radiobutton .draw.curvswitch.ra3 -text "vd" -variable colscale -value 17 \
  -font $ffont -bd 0 -padx 0
pack .draw.curvswitch.ra2 .draw.curvswitch.ra .draw.curvswitch.ra3 -side left
# redraw
bind $f.aw1.ra <ButtonRelease-1> { redrawbutton }
bind $f.aw2.ra <ButtonRelease-1> { redrawbutton }
bind $f.aw3.ra <ButtonRelease-1> { redrawbutton }
bind $f.aw4.ra <ButtonRelease-1> { redrawbutton }
bind $f.abi.ra <ButtonRelease-1> { redrawbutton }
bind $f.aht.ra <ButtonRelease-1> { redrawbutton }
bind $f.aBRy.ra <ButtonRelease-1> { redrawbutton }
bind $f.aBR.ra <ButtonRelease-1> { redrawbutton }
bind $f.aGR.ra <ButtonRelease-1> { redrawbutton }
bind $f.alt.ra <ButtonRelease-1> { redrawbutton }
bind $f.afs.ra <ButtonRelease-1> { redrawbutton }
#bind $f.ajt.ra <ButtonRelease-1> { redrawbutton }
#bind $f.altw.ra <ButtonRelease-1> { redrawbutton }
bind .draw.curvswitch.ra2 <ButtonRelease-1> { redrawbutton }  ;# ltw
bind .draw.curvswitch.ra <ButtonRelease-1> { redrawbutton }   ;# jet
bind .draw.curvswitch.ra3 <ButtonRelease-1> { redrawbutton }   ;# vd
# 2 overload bindings: middle-click w1->w2, shift-middle-click w1->w3
bind $f.aw1.ra <ButtonRelease-2> { set colscale 8; redrawbutton }
bind $f.aw1.ra <Shift-ButtonRelease-2> { set colscale 16; redrawbutton }
# 2 more overload bindings: middle-click BRy->jet, middle-click BR->vd
bind $f.aBRy.ra <ButtonRelease-2> { set colscale 15; redrawbutton }
bind $f.aBR.ra <ButtonRelease-2> { set colscale 17; redrawbutton }
# another alt binding: middle click ltw (phase LUT) to get lta (amp LUT)
bind .draw.curvswitch.ra2 <ButtonRelease-2> {
  confirmalert "use real-valued color LUT for amplitude of complex data"
  set colscale 13
  redrawbutton
}
# help
bind $f.aw1.ra <ButtonRelease-3> { helpwin val_w1 }
bind $f.aw2.ra <ButtonRelease-3> { helpwin val_w2 }
bind $f.aw3.ra <ButtonRelease-3> { helpwin val_w3 }
bind $f.aw4.ra <ButtonRelease-3> { helpwin val_w4 }
bind $f.abi.ra <ButtonRelease-3> { helpwin val_bi }
bind $f.aht.ra <ButtonRelease-3> { helpwin val_ht }
bind $f.aBR.ra <ButtonRelease-3> { helpwin val_BRw }
bind $f.aBRy.ra <ButtonRelease-3> { helpwin val_BRy }
bind $f.aGR.ra <ButtonRelease-3> { helpwin val_GR }
bind $f.alt.ra <ButtonRelease-3> { helpwin val_lt }
bind $f.afs.ra <ButtonRelease-3> { helpwin val_fs }
#bind $f.ajt.ra <ButtonRelease-3> { helpwin val_jt }
bind .draw.curvswitch.ra2 <ButtonRelease-3> { helpwin val_ltw }
bind .draw.curvswitch.ra <ButtonRelease-3> { helpwin val_jt }
bind .draw.curvswitch.ra3 <ButtonRelease-3> { helpwin val_vd }

### pop-up with all colscales, verbose radio labels
set f .draw.curvswitch
bind $f.anone.la <ButtonRelease-1> {
  set nm .colcontrols
  if [winfo exists .colcontrols] { raise .colcontrols; break }
  set f [toplevel $nm -borderwidth 0 -bg $bgcol]
  wm title $f "colscales"
  if {$tksurferinterface == "mini"} {
    wm geometry $f +[expr [winfo rootx .]+624]+[expr [winfo rooty .]-5]
  }
  if {$tksurferinterface == "macro"} {
    wm geometry $f +[expr [winfo rootx .]+360]+[expr [winfo rooty .]+220]
  }
  label $f.la -text "All Overlay Color Scales (Verbose)" \
    -font $ffontb -bg $bgcol
  pack $f.la -side top -pady 5
  ## (almost) all colorscales
  radios $f "" "w1" colscale 0 0 col
  radios $f "" "w2" colscale 8 2 col
  radios $f "" "w3" colscale 16 2 col
  radios $f "" "w4" colscale 18 2 col
  radios $f "" "ht" colscale 1 2 col
  radios $f "" "bi" colscale 4 2 col
  #radios $f "" "Blue/Red (rare) (2)" colscale 2 2 col
  #radios $f "" "Blue/Green/Red (rare) (3)" colscale 3 2 col
  #radios $f "" "Green/Red (rare) (5)" colscale 5 2 col
  radios $f "" "BRy" colscale 11 2 col
  radios $f "" "BR"  colscale 6 2 col
  #radios $f "" "Green/Red (rare) (7)" colscale 7 2 col
  radios $f "" "lt"  colscale 12 2 col
  radios $f "" "lta" colscale 13 2 col
  radios $f "" "ltw" colscale 14 2 col
  radios $f "" "fs"  colscale 9 2 col
  radios $f "" "jt"  colscale 15 2 col
  radios $f "" "vd"  colscale 17 2 col
  ## make verbose labels
  $f.aw1.ra  config -text "w1    (0):\tStd Wheel: Green/Blue/Red Polar/Eccen"
  $f.aw2.ra  config -text "w2    (8):\tStd+Yel Wheel: Green/Blue/Red/Yellow"
  $f.aw3.ra  config -text "w3  (16):\tMirror Wheel: Mag/Blu/Cyan/Grn/Yel/Red  "
  $f.aw4.ra  config -text "w4  (18):\tTono Wheel: Or/Red/Mag/Blu/Cy/Gre/Yel"
  $f.aht.ra  config -text "ht     (1):\tBrown->White Heat: Complex Amp"
  $f.abi.ra  config -text "bi     (4):\tRed/Green Two-Cond Phase"
  $f.aBRy.ra config -text "BRy (11):\tBlue->Cyan, Red->Yellow: Signed"
  $f.aBR.ra  config -text "BR    (6):\tBlue->White, Red->White: Signed"
  $f.alt.ra  config -text "lt     (12):\tLook-Up Table: Real"
  $f.alta.ra config -text "lta   (13):\tLook-Up Table: Complex Amp"
  $f.altw.ra config -text "ltw   (14):\tLook-Up Table: Complex Phase"
  $f.afs.ra  config -text "fs      (9):\tFieldsign: Blue=NonMirr/Yellow=Mirr"
  $f.ajt.ra  config -text "jet   (15):\tMATLAB Jet: Signed"
  $f.avd.ra  config -text "vd   (17):\tCARET Videen-Style: One-sided"
  ## same help
  bind $f.aw1.ra  <ButtonRelease-3> { helpwin val_w1 }
  bind $f.aw2.ra  <ButtonRelease-3> { helpwin val_w2 }
  bind $f.aw3.ra  <ButtonRelease-3> { helpwin val_w3 }
  bind $f.aw4.ra  <ButtonRelease-3> { helpwin val_w4 }
  bind $f.aht.ra  <ButtonRelease-3> { helpwin val_ht }
  bind $f.abi.ra  <ButtonRelease-3> { helpwin val_bi }
  bind $f.aBRy.ra <ButtonRelease-3> { helpwin val_BRy }
  bind $f.aBR.ra  <ButtonRelease-3> { helpwin val_BRw }
  bind $f.alt.ra  <ButtonRelease-3> { helpwin val_lt }
  bind $f.alta.ra <ButtonRelease-3> { helpwin val_lta }
  bind $f.altw.ra <ButtonRelease-3> { helpwin val_ltw }
  bind $f.afs.ra  <ButtonRelease-3> { helpwin val_fs }
  bind $f.ajt.ra  <ButtonRelease-3> { helpwin val_jt }
  bind $f.avd.ra  <ButtonRelease-3> { helpwin val_vd }
  ## record prev val, restore if no LUT loaded (just "Col:" popup ltw button)
  bind $f.altw.ra <Enter> { set prevcolscale $colscale }
  $f.altw.ra config -command {
    if {$val2rgblutcnt == 0} {
      confirmalert "no color look-up table (.lut) loaded"
      set colscale $prevcolscale
      redrawbutton
    }
  }
  ## auto redraw any release (incl on label)
  bind $f <ButtonRelease-1> { redrawbutton }
  frame $f.sp -height 15 -bg $bgcol
  pack $f.sp -side top
  ### was: don't auto REDRAW so easier to see diff
  #button $f.bn -text "REDRAW" -font $ffontb -pady 2 -command redrawbutton
  #pack $f.bn -side top -pady 5
  wm resizable $f 0 0
}

### new two colors scale control
set f .draw.twocols
edlabval $f.r1 "r" $colr1 n 1 3
edlabval $f.g1 "g" $colg1 n 1 3
edlabval $f.b1 "b" $colb1 n 1 3
edlabval $f.r2 "r" $colr2 n 1 3
edlabval $f.g2 "g" $colg2 n 1 3
edlabval $f.b2 "b" $colb2 n 1 3
label $f.la1 -text "col1" -font $ffontb
pack $f.la1 -side left -before $f.r1
label $f.la2 -text "  col2" -font $ffontb
pack $f.la2 -side left -before $f.r2
$f.r1.r.la config -text r
$f.g1.g.la config -text g
$f.b1.b.la config -text b
$f.r2.r.la config -text r
$f.g2.g.la config -text g
$f.b2.b.la config -text b
$f.r1.r.e config -textvariable colr1
$f.g1.g.e config -textvariable colg1
$f.b1.b.e config -textvariable colb1
$f.r2.r.e config -textvariable colr2
$f.g2.g.e config -textvariable colg2
$f.b2.b.e config -textvariable colb2
bind $f.r1.r.e <Return> { logcmd "set colr1 $colr1"; redrawbutton }
bind $f.g1.g.e <Return> { logcmd "set colg1 $colg1"; redrawbutton }
bind $f.b1.b.e <Return> { logcmd "set colb1 $colb1"; redrawbutton }
bind $f.r2.r.e <Return> { logcmd "set colr2 $colr2"; redrawbutton }
bind $f.g2.g.e <Return> { logcmd "set colg2 $colg2"; redrawbutton }
bind $f.b2.b.e <Return> { logcmd "set colb2 $colb2"; redrawbutton }
bind $f.la1 <ButtonRelease-3> { helpwin col1col2 }
bind $f.la2 <ButtonRelease-3> { helpwin col1col2 }
bind $f.r1.r.e <ButtonRelease-3> { helpwin col1col2 }
bind $f.g1.g.e <ButtonRelease-3> { helpwin col1col2 }
bind $f.b1.b.e <ButtonRelease-3> { helpwin col1col2 }
bind $f.r2.r.e <ButtonRelease-3> { helpwin col1col2 }
bind $f.g2.g.e <ButtonRelease-3> { helpwin col1col2 }
bind $f.b2.b.e <ButtonRelease-3> { helpwin col1col2 }
# jam in unrelated non-int (polar-like) eccen disk flag
checkbutton $f.ck -variable noninteccendiskflag -font $ffont -text "ecp" -bd 0
pack $f.ck -side left -padx 0
bind $f.ck <ButtonRelease-1> {
  logcmd "set noninteccendiskflag $noninteccendiskflag"
  redrawbutton
}
#TODO: new helpfile
bind $f.ck <ButtonRelease-3> { helpwin nonintecc }

### MESH/points, mesh/annot r/g/b, scalebars
#############################################################################
# MESH
set f .draw.mesh
buttons $f.me "MESH" {
  if {$edgesflag} {
    set edgesflag 0
    logcmd "set edgesflag 0"
    .draw.mesh.me.aMESH.bu config -relief raised
  } else {
    set edgesflag 1
    logcmd "set edgesflag 1"
    .draw.mesh.me.aMESH.bu config -relief sunken
  }
  redraw
  logcmd "redraw"
} row 0 3 
# overload MESH w/pointsflag
bind $f.me.aMESH.bu <ButtonRelease-2> {
  if {$pointsflag} {
    set pointsflag 0
    logcmd "set pointsflag 0"
  } else {
    set pointsflag 1
    logcmd "set pointsflag 1"
  }
  redraw
  logcmd "redraw"
}
bind $f.me.aMESH.bu <ButtonRelease-3> { helpwin mesh }
# r,g,b
edlabval $f.r "r" $meshr n 1 3
edlabval $f.g "g" $meshg n 1 3
edlabval $f.b "b" $meshb n 1 3
$f.r.r.la config -text r
$f.g.g.la config -text g
$f.b.b.la config -text b
$f.r.r.e config -textvariable meshr
$f.g.g.e config -textvariable meshg
$f.b.b.e config -textvariable meshb
bind $f.r.r.e <Return> { logcmd "set meshr $meshr"; redrawbutton }
bind $f.g.g.e <Return> { logcmd "set meshg $meshg"; redrawbutton }
bind $f.b.b.e <Return> { logcmd "set meshb $meshb"; redrawbutton }
bind $f.r.r.e <ButtonRelease-3> { helpwin meshr }
bind $f.g.g.e <ButtonRelease-3> { helpwin meshg }
bind $f.b.b.e <ButtonRelease-3> { helpwin meshb }
# TODO: could add label-read-specific alpha
# disk (button=rect) -> rect (button=off) -> off (button=disk/bar)
buttons $f.rect "rect" {
  if {!$colscalerectflag && $colscalebarflag} {  ;# state:disk->rect, butt=off
    set colscalerectflag 1
    logcmd "set colscalerectflag 1"
    .draw.mesh.rect.arect.bu config -text "off" -width 4
  } elseif {$colscalerectflag && $colscalebarflag} { ;#state:rect->off,butt=disk
    set colscalebarflag 0
    logcmd "set colscalebarflag 0"
    if {$complexvalflag && $overlayflag} {
      .draw.mesh.rect.arect.bu config -text "disk" -width 4
    } else {
      .draw.mesh.rect.arect.bu config -text "bar" -width 4
    }
  } elseif {!$colscalebarflag} {  ;# state:off->disk, butt=rect
    set colscalebarflag 1
    logcmd "set colscalebarflag 1"
    set colscalerectflag 0
    logcmd "set colscalerectflag 0"
    .draw.mesh.rect.arect.bu config -text "rect" -width 4
  } else { ; }
  redraw
  logcmd "redraw"
} row 0 1
# init label
if {!$colscalerectflag} {.draw.mesh.rect.arect.bu config -text "rect" -width 4}
if { $colscalerectflag} {.draw.mesh.rect.arect.bu config -text "off"  -width 4}
if {!$colscalebarflag}  {
  if {$complexvalflag} {
    .draw.mesh.rect.arect.bu config -text "disk" -width 4
  } else {
    .draw.mesh.rect.arect.bu config -text "bar" -width 4
  }
}
bind $f.rect.arect.bu <ButtonRelease-3> { helpwin rect }
# colscale inset (explicit F3 only)
checks $f.sb ""  "ful" fullpolrectflag row
checks $f.sb ""  "cm"   scalebarflag row
checks $f.sb ""  "bar"  colscalebarflag row
checks $f.sb ""  "exp"  logtransflag row
pack $f.sb.aful $f.sb.acm $f.sb.abar $f.sb.aexp -padx 0  ;# squeeze
$f.sb.aful.ck config -bd 0 -padx 0  ;# squeeze
$f.sb.acm.ck config -bd 0 -padx 0
$f.sb.abar.ck config -bd 0 -padx 0
$f.sb.aexp.ck config -bd 0 -padx 0
bind $f.sb.aful.ck <ButtonRelease-1> {
  logcmd "set fullpolrectflag $fullpolrectflag"
  redrawbutton
}
bind $f.sb.acm.ck <ButtonRelease-1> {
  logcmd "set scalebarflag $scalebarflag"
  redrawbutton
}
bind $f.sb.abar.ck <ButtonRelease-1> {
  logcmd "set colscalebarflag $colscalebarflag"
  redrawbutton
}
bind $f.sb.aexp.ck <ButtonRelease-1> {
  logcmd "set logtransflag $logtransflag"
  redrawbutton
}
bind $f.sb.aful.ck <ButtonRelease-3> { helpwin full } ;# TODO: write this help
bind $f.sb.acm.ck <ButtonRelease-3> { helpwin cm }
bind $f.sb.abar.ck <ButtonRelease-3> { helpwin colbar }
# cm inset
buttons $f.cm "cm" {
  if {$scalebarflag} {
    set scalebarflag 0
    logcmd "set scalebarflag 0"
    .draw.mesh.cm.acm.bu config -relief raised
  } else {
    set scalebarflag 1
    logcmd "set scalebarflag 1"
    .draw.mesh.cm.acm.bu config -relief sunken
  }
  redraw
  logcmd "redraw"
} row 0 1
pack forget .draw.mesh.cm  ;# mini only (dup in macro, first make macro)
bind $f.cm.acm.bu <ButtonRelease-3> { helpwin cm2 } ;#toggles inset too
bind $f.sb.aexp.ck <ButtonRelease-3> { helpwin exptrans }

### 2d vectors checkrow
set f .draw.switch2d
#checks $f "2d Vectors" "shear" shearvecflag row
#checks $f ""           "norm" normvecflag row
#checks $f ""           "move" movevecflag row
###TODO: new helpfile (when panels stable -- N.B. defunct)
#bind $f.ashear.ck <ButtonRelease-3> { helpwin 2d_shear }
#bind $f.anorm.ck <ButtonRelease-3> { helpwin 2d_norm }
#bind $f.amove.ck <ButtonRelease-3> { helpwin 2d_move }
#bind $f.ashear.ck <Return> { logcmd "set shearvecflag $shearvecflag" }
#bind $f.anorm.ck <Return> { logcmd "set normvecflag $normvecflag" }
#bind $f.amove.ck <Return> { logcmd "set movevecflag $movevecflag" }
###TODO: rm this now defunct
#buttons $f "CVAVG" { set cmid 0.0; logcmd "set cmid 0.0" } row 1
#bind $f.aCVAVG.bu <ButtonRelease-3> { helpwin cvavg }

### display panel left (trunc, invph, overlay, complex, mask, colbar, fthresh)
#############################################################################
set f .display.le
## "truncph" tick
checks $f "" "truncph" truncphaseflag col
bind $f.atruncph.ck <ButtonRelease-1> {
  logcmd "set truncphaseflag $truncphaseflag"
  uplevel #0 { set softtruncphaseflag 0 }  ;# toggle hard/soft (update tick)
  logcmd "set softtruncphaseflag $softtruncphaseflag"
  if {$truncphaseflag && $truncphasemin > $truncphasemax} {
    if {!$complexvalflag} {
      confirmalert "N.B.: truncphase min larger than max\
                \n\nReal-valued min/max *don't* wrap: nothing will be visible"
    }
  }
  redrawbutton
}
bind $f.atruncph.ck <ButtonRelease-3> { helpwin truncphase }
## "s" (softtruncphaseflag) tick to right of truncph
checkbutton $f.atruncph.ck2 -variable softtruncphaseflag -text "soft" \
  -font $ffont -padx 0 -bd 0
pack $f.atruncph.ck -side left   ;# repack to override checks pack 'col'
pack $f.atruncph.ck2 -side left -padx 0
bind $f.atruncph.ck2 <ButtonRelease-1> {
  logcmd "set softtruncphaseflag $softtruncphaseflag"
  uplevel #0 { set truncphaseflag 0 }  ;# toggle hard/soft (update tick)
  logcmd "set truncphaseflag $truncphaseflag"
  if {$truncphaseflag && $truncphasemin > $truncphasemax} {
    if {!$complexvalflag} {
      confirmalert "N.B.: truncphase min larger than max\
                \n\nReal-valued min/max *don't* wrap: nothing will be visible"
    }
  }
  redrawbutton
}
bind $f.atruncph.ck2 <ButtonRelease-3> { helpwin truncphasesoft }
## truncphasemin/max
frame $f.tr
pack $f.tr -side top
edlabval $f.tr "truncphasemin" truncphasemin n 0 4 row 
edlabval $f.tr "truncphasemax" truncphasemax n 0 4 row
$f.tr.truncphasemin.e config -textvariable truncphasemin
$f.tr.truncphasemax.e config -textvariable truncphasemax
$f.tr.truncphasemin.la config -text ""  ;# not above so widget path gets id
$f.tr.truncphasemax.la config -text ""
bind $f.tr.truncphasemin.e <Return> {
  #set truncphaseflag 1
  #logcmd "set truncphasemin $truncphasemin"
  if {!$truncphaseflag && !$softtruncphaseflag && 
      $colscale != 15 && $colscale != 17} {
    confirmalert "N.B.: both \$truncphaseflag and \$softtruncphaseflag OFF:\
              \n\n  \"truncph\" => hard truncate phase\
                \n  \"sft\" => soft truncate phase"
  }
  if {$truncphasemin > $truncphasemax} {
    if {!$complexvalflag} {
      confirmalert "N.B.: truncphase min larger than max\
                \n\nReal-valued min/max *don't* wrap: nothing will be visible"
    }
  }
  redrawbutton
}
bind $f.tr.truncphasemax.e <Return> {
  #set truncphaseflag 1
  #logcmd "set truncphasemax $truncphasemax"
  if {!$truncphaseflag && !$softtruncphaseflag &&
      $colscale != 15 && $colscale != 17} {
    confirmalert "N.B.: both \$truncphaseflag and \$softtruncphaseflag OFF:\
              \n\n  \"truncph\" => hard truncate phase\
                \n  \"sft\" => soft truncate phase"
  }
  if {$truncphasemin > $truncphasemax} {
    if {!$complexvalflag} {
      confirmalert "N.B.: truncphase min larger than max\
                \n\nReal-valued min/max *don't* wrap: nothing will be visible"
    }
  }
  redrawbutton
}
bind $f.tr.truncphasemin.e <ButtonRelease-3> {helpwin truncphasemin}
bind $f.tr.truncphasemax.e <ButtonRelease-3> {helpwin truncphasemax}
## inv phase (rev phase moved next to angleoffset)
frame $f.rv 
pack $f.rv -side top
checks $f.rv "" "invph" invphaseflag row
bind $f.rv.ainvph.ck <ButtonRelease-1> {
  logcmd "set invphaseflag $invphaseflag"
  redrawbutton
}
bind $f.rv.ainvph.ck <ButtonRelease-3> { helpwin invphase }
# softtruncwidth
entry $f.rv.e -textvariable softtruncwidth -font $ffont -width 4
pack $f.rv.e -side left
bind $f.rv.e <Return> {
  if {!$softtruncphaseflag} {
    confirmalert "softtruncphaseflag not set (\"s\" tick) -> no effect"
    break
  }
  if {$truncphasemax > $truncphasemin} {
    if {$softtruncwidth > 0.5*(1.0 - ($truncphasemax - $truncphasemin))} {
      confirmalert "truncphase ramps overlap:\
                \n\n\$softtruncwidth must be < \
        [format "%%0.2f" [expr 0.5*(1.0 - ($truncphasemax - $truncphasemin))]]"
      break
    }
  }
  if {$truncphasemin > $truncphasemax} {
    if {$softtruncwidth > 0.5*($truncphasemin - $truncphasemax)} {
      confirmalert "truncphase ramps overlap:\
                \n\n\$softtruncwidth must be < \
        [format "%%0.2f" [expr 0.5*($truncphasemin - $truncphasemax)]]"
      break
    }
  }
  logcmd "set softtruncwidth $softtruncwidth"
  redrawbutton
}
bind $f.rv.e <ButtonRelease-3> {helpwin softtruncwidth}
## overlay, complex
frame $f.oc
pack $f.oc -side top
checks $f.oc "" "ovlay" overlayflag row
checks $f.oc "" "cpx" complexvalflag row
bind $f.oc.aovlay.ck <ButtonRelease-1> {
  if {!$overlayflag} {  ;# force re-autoscale (fixcolscale does other way)
    set minstatcolscale 0.0
    set maxstatcolscale 0.0
    logcmd "set minstatcolscale $minstatcolscale"
    logcmd "set maxstatcolscale $maxstatcolscale"
    if {!$colscalebarflag} {  ;# only update butt if scalebar off
      .draw.mesh.rect.arect.bu config -text "bar" -width 4
    }
  } else {
    if {!$colscalebarflag} {  ;# only update butt if scalebar off
      if {$complexvalflag && $overlayflag} {
        .draw.mesh.rect.arect.bu config -text "disk" -width 4
      } else {
        .draw.mesh.rect.arect.bu config -text "bar" -width 4
      }
    }
  }
  logcmd "set overlayflag $overlayflag"
  redrawbutton
}
bind $f.oc.acpx.ck <ButtonRelease-1> {
  logcmd "set complexvalflag $complexvalflag"
  redrawbutton
  if {!$colscalebarflag} {  ;# only update butt if scalebar off
    if {$complexvalflag && $overlayflag} {
      .draw.mesh.rect.arect.bu config -text "disk" -width 4
    } else {
      .draw.mesh.rect.arect.bu config -text "bar" -width 4
    }
  }
}
$f.oc.acpx.ck config -command {
  ## next 3 to stop loop triggered by fixcolscale
  if {$colscale == 12 && $complexvalflag} {
    set colscale 14
  } elseif {$colscale == 13 && !$complexvalflag} {
    set colscale 12
  } elseif {$colscale == 14 && !$complexvalflag} {
    set colscale 12
  ## cpx -> not cpx: displays as blank, guess real colscale BR
  } elseif {$colscale == 0 && !$complexvalflag} {
    set colscale 6
  } elseif {$colscale == 1 && !$complexvalflag} {
    set colscale 6
  } elseif {$colscale == 4 && !$complexvalflag} {
    set colscale 6
  } elseif {$colscale == 8 && !$complexvalflag} {
    set colscale 6
  } elseif {$colscale == 18 && !$complexvalflag} {
    set colscale 6
  ## not cpx -> cpx: displays as blank, guess std cpx color wheel w1
  } elseif {$colscale == 6 && $complexvalflag} {
    set colscale 0
  } elseif {$colscale == 11 && $complexvalflag} {
    set colscale 0
  ## don't fix b/c these colscales *can* be used to view complex amplitude
  #} elseif {$colscale == 15 && $complexvalflag} {
  #  set colscale 0
  #} elseif {$colscale == 17 && $complexvalflag} {
  #  set colscale 0
  } else { }
} ;# N.B.:
pack $f.oc.aovlay $f.oc.acpx -padx 0
bind $f.oc.acpx.ck <ButtonRelease-3> { helpwin complexval }
bind $f.oc.aovlay.ck <ButtonRelease-3> { helpwin overlay }
## mask or mult mods
frame $f.st
pack $f.st -side top
checks $f.st "" "mask" statmaskampflag row
checks $f.st "" "mult" statmultampflag row
pack $f.st.amask $f.st.amult -padx 0  ;# re-pack squish
$f.st.amask.ck config -bd 0 -padx 0 ;# squish
$f.st.amult.ck config -bd 0 -padx 0  ;# squish
bind $f.st.amask.ck <ButtonRelease-1> {
  logcmd "set statmaskampflag $statmaskampflag"
  redrawbutton
}
bind $f.st.amult.ck <ButtonRelease-1> {
  logcmd "set statmultampflag $statmultampflag"
  redrawbutton
}
$f.st.amask.ck config -command {
  if {$statmaskampflag && !$statloadedflag} {
    confirmalert \
      "statmaskampflag=1 but\nstat field not loaded\n\nfirst do:\n\
      \n  (1) load stat as val\
      \n  (2) S/V (swap stat/val)\
      \n  (3) reload real or cplx val"
    set statmaskampflag 0
    logcmd "set statmaskampflag 0"
    redrawbutton
  }
  if {$sfthresh == 0.0 && $sfslope == 0.0} {
    confirmalert "N.B.: Both sfthresh=0.0 and sfslope=0.0 disables statmask!\
              \n\nresetting sfthresh to 0.01"
    set sfthresh 0.01
    logcmd "set sfthresh 0.01"
  }
  secondsquashents
}
# overload "mask" tick
bind $f.st.amask.ck <ButtonRelease-2> {
  set statANDhypotflag [expr !$statANDhypotflag]
  logcmd "set statANDhypotflag $statANDhypotflag"
  if {$statANDhypotflag} {
    confirmalert "\$statANDhypotflag ON:\
              \n\nSubsequent ROI operation will mask complex data by:\
              \n\n    \$fthresh AND \$sfthresh"
    if {$statANDrealflag} {  ;# silent fix
      set statANDrealflag 0
      logcmd "set statANDrealflag 0"
    }
  } else {
    confirmalert "\$statANDhypotflag OFF:\
               \n\nSubsequent ROI operation will mask complex data ONLY by:\
               \n\n    \$sfthresh"
  }
  redrawbutton
}
# second overload "mask" tick
bind $f.st.amask.ck <Control-ButtonRelease-2> {
  set statANDrealflag [expr !$statANDrealflag]
  logcmd "set statANDrealflag $statANDrealflag"
  if {$statANDrealflag} {
    confirmalert "\$statANDrealflag ON:\
               \n\nSubsequent ROI operation wlll mask real data by:\
               \n\n     \$fthresh AND \$sfthresh"
    if {$statANDhypotflag} {  ;# silent fix
      set statANDhypotflag 0
      logcmd "set statANDhypotflag 0"
    }
  } else {
    confirmalert "\$statANDrealflag OFF:\
                \n\nSubsequent ROI operation will mask real data ONLY by:\
                \n\n    \$sfthresh"
  }
  redrawbutton
}
$f.st.amult.ck config -command {
  if {$statmultampflag && !$statloadedflag} {
    confirmalert \
      "statmultampflag=1 but\nstat field not loaded\n\nfirst do:\n\
       \n  (1) load stat as val\
       \n  (2) S/V (swap stat/val)\
       \n  (3) reload cplx val"
    set statmultampflag 0
    logcmd "set statmultampflag 0"
    redrawbutton
  }
}
bind $f.st.amask.ck <ButtonRelease-3> { helpwin statmaskamp }
bind $f.st.amult.ck <ButtonRelease-3> { helpwin statmultamp }
## colscale limits
frame $f.sb
pack $f.sb -side top
edlabval $f.sb "minstatcolscale" minstatcolscale n 0 4 row
edlabval $f.sb "maxstatcolscale" maxstatcolscale n 0 4 row
$f.sb.minstatcolscale.e config -textvariable minstatcolscale
$f.sb.maxstatcolscale.e config -textvariable maxstatcolscale
$f.sb.minstatcolscale.la config -text "" -padx 0
$f.sb.maxstatcolscale.la config -text "bar" -padx 0
bind $f.sb.minstatcolscale.e <Return> {
  logcmd "set minstatcolscale $minstatcolscale"
  redrawbutton
}
bind $f.sb.maxstatcolscale.e <Return> {
  logcmd "set maxstatcolscale $maxstatcolscale"
  redrawbutton
}
bind $f.sb.minstatcolscale.e <ButtonRelease-3> { helpwin minstat }
bind $f.sb.maxstatcolscale.e <ButtonRelease-3> { helpwin maxstat }
## fthresh
edlabval $f "fthresh" $fthresh n 6 4
$f.fthresh.e config -textvariable fthresh
bind $f.fthresh.e <Return> {
  logcmd "set fthresh $fthresh"
  checkfthreshfmidBRy
  redrawbutton
}
bind $f.fthresh.e <ButtonRelease-3> { helpwin fthresh }
# hideable sfthresh
frame $f.fthresh.st -bg $bgcol
pack $f.fthresh.st -side left
entry $f.fthresh.st.e -textvariable sfthresh -font $ffont -width 3
pack $f.fthresh.st.e -side left
bind $f.fthresh.st.e <Return> {
  if {$sfthresh == 0.0 && $sfslope == 0.0} {
    confirmalert "N.B.: Both sfthresh=0.0 and sfslope=0.0 disables statmask!\
              \n\nresetting sfthresh to 0.01"
    set sfthresh 0.01
    logcmd "set sfthresh 0.01"
  }
  logcmd "set sfthresh $sfthresh"
  redrawbutton
}
bind $f.fthresh.st.e <ButtonRelease-3> { helpwin sfthresh }

### display panel middle (subdivide top half of this column) (phasecontours)
#############################################################################
set f .display.mi
frame $f.to
pack $f.to -side top
frame $f.to.le -bd 2 -relief groove
frame $f.to.ri
pack $f.to.le $f.to.ri -side left
frame $f.bo
pack $f.bo -side top
# subframe: top left
set f .display.mi.to.le
## phase contours
checkbutton $f.ck -variable phasecontoursflag -font $ffont -text "phc" -bd 0
pack $f.ck -side top
bind $f.ck <ButtonRelease-1> {
  logcmd "set phasecontoursflag $phasecontoursflag"
  redrawbutton
}
bind $f.ck <ButtonRelease-3> { helpwin phcont }
edlabval $f "n" phasecontours n 0 3 col
$f.n.e config -textvariable phasecontours
$f.n.la config -text "n"
bind $f.n.e <Return> {
  set phasecontoursflag 1
  logcmd "set phasecontoursflag $phasecontoursflag"
  logcmd "set phasecontours $phasecontours"
  redrawbutton
}
bind $f.n.e <ButtonRelease-3> { helpwin phcont_num }
edlabval $f "w" phasecontoursfrac n 0 3 col
$f.w.e config -textvariable phasecontoursfrac
$f.w.la config -text "w"
bind $f.w.e <Return> {
  set phasecontoursflag 1
  logcmd "set phasecontoursflag $phasecontoursflag"
  logcmd "set phasecontoursfrac $phasecontoursfrac"
  redrawbutton
}
bind $f.w.e <ButtonRelease-3> { helpwin phcont_width }
## gradient arrows control (orthgonal to, so somewhat like phase contours...)
frame $f.arr
pack $f.arr -side top
checkbutton $f.arr.ck -variable arrownormflag -padx 0 -bd 0  ;# no label
entry $f.arr.e -textvariable arrowscale -font $ffont -width 3
pack $f.arr.ck $f.arr.e -side left -padx 0
# arrows tickbox bindings
bind $f.arr.ck <ButtonRelease-1> {
  logcmd "set arrownormflag $arrownormflag"
  if {$arrownormflag} {
    set arrowscale 0.5
    logcmd "set arrowscale 0.5"
  } else {
    set arrowscale 5.0
    logcmd "set arrowscale 5.0"
  }
  if {$arrownormflag} {
    confirmalert "norm gradient arrows to 1 (entry to right scales)"
  } else {
    confirmalert "gradient arrows proportional (entry to right scales)"
  }
  redrawbutton
  arrownormctrls   ;# immed. access even w/o R-click
}
# overload phasecontours arrownormflag check w/toggle angoffrevarrflag
bind $f.arr.ck <ButtonRelease-2> {
  set angoffrevarrflag [expr !$angoffrevarrflag]
  logcmd "set angoffrevarrflag $angoffrevarrflag"
  confirmalert "set angoffrevarrflag $angoffrevarrflag"
  if {$angoffrevarrflag} {
    confirmalert "display polar angle in .val/.val2 as arrows"
  } else {
    confirmalert "display polar angle in .val/.val2 as color"
  }
  redrawbutton
}
# second overload phasecont arrownormflag check w/show gradient ampl as real
bind $f.arr.ck <Shift-ButtonRelease-2> {
  do_grad2col
}
# third overload phasecont arrownormflag check w/show gradient ampl as real
bind $f.arr.ck <Control-ButtonRelease-2> {
  set normalsflag [expr !$normalsflag]
  logcmd "set normalsflag $normalsflag"
  set arrowscale 2.0
  logcmd "set arrowscale 2.0"
  if {$normalsflag} {
    confirmalert "display normal vectors (\$arrowline=$arrowline)"
  } else {
    confirmalert "don't display normal vectors"
  }
  redrawbutton
}
# fourth overload phasecont arrownormflag check w/toggle dipoles
bind $f.arr.ck <Shift-ButtonRelease-3> {
  set dipolesflag [expr !$dipolesflag]
  logcmd "set dipolesflag $dipolesflag"
  set arrowscale 2.0
  logcmd "set arrowscale 2.0"
  if {$dipolesflag} {
    confirmalert "display vectors (\$arrowline=$arrowline)"
  } else {
    confirmalert "don't display vectors"
  }
  redrawbutton
}
bind $f.arr.ck <ButtonRelease-3> {  ;# right-click help plus pop-up
  helpwin arrownorm
  after 500 { arrownormctrls }
}
# arrows entry bindings
bind $f.arr.e <Return> {
  confirmalert "arrowscale -> $arrowscale"
  logcmd "set arrowscale $arrowscale"
  redrawbutton
}
bind $f.arr.e <Shift-Return> {
  confirmalert "arrowline -> $arrowscale\narrowscale -> $arrowscale"
  set arrowline $arrowscale  ;# awk overload (redraw uses new val arrowscale)
  logcmd "set arrowscale $arrowscale"
  logcmd "set arrowline $arrowline"
  redrawbutton
}
bind $f.arr.e <ButtonRelease-3> { helpwin arrowscale }
## subframe: top right
set f .display.mi.to.ri
## fslope/fmid, hideable sfslope/sfmid
# fslope
edlabval $f "fslope"  $fslope  n 7 4
$f.fslope.e config -textvariable fslope 
bind $f.fslope.e <Return> { logcmd "set fslope $fslope"; redrawbutton }
bind $f.fslope.e <ButtonRelease-3> { helpwin fslope }
# hideable sfslope 
frame $f.fslope.st -bg $bgcol
pack $f.fslope.st -side left
entry $f.fslope.st.e -textvariable sfslope -font $ffont -width 3
pack $f.fslope.st.e -side left
bind $f.fslope.st.e <Return> {
  if {$sfthresh == 0.0 && $sfslope == 0.0} {
    confirmalert "N.B.: Both sfthresh=0.0 and sfslope=0.0 disables statmask!\
              \n\nresetting sfthresh to 0.01"
    set sfthresh 0.01
    logcmd "set sfthresh 0.01"
  }
  logcmd "set sfslope $sfslope"
  redrawbutton
}
bind $f.fslope.st.e <ButtonRelease-3> { helpwin sfslope }
# fmid
edlabval $f "fmid"    $fmid    n 7 4
$f.fmid.e config -textvariable fmid
bind $f.fmid.e <Return> {
  logcmd "set fmid $fmid"
  checkfthreshfmidBRy
  redrawbutton
}
bind $f.fmid.e <ButtonRelease-3> { helpwin fmid }
# hideable sfmid
frame $f.fmid.st -bg $bgcol
pack $f.fmid.st -side left
entry $f.fmid.st.e -textvariable sfmid -font $ffont -width 3
pack $f.fmid.st.e -side left
bind $f.fmid.st.e <Return> { logcmd "set sfmid $sfmid"; redrawbutton }
bind $f.fmid.st.e <ButtonRelease-3> { helpwin sfmid }
## cslope, cmid
edlabval $f "cslope"  $cslope  n 7 4
$f.cslope.e config -textvariable cslope 
bind $f.cslope.e <Return> { logcmd "set cslope $cslope"; redrawbutton }
bind $f.cslope.e <ButtonRelease-3> { helpwin cslope }
edlabval $f "cmid"    $cmid    n 7 3
$f.cmid.e config -textvariable cmid
bind $f.cmid.e <Return> { logcmd "set cmid $cmid"; redrawbutton }
bind $f.cmid.e <ButtonRelease-3> { helpwin cmid }
# jam in unlabeled red dimmer
frame $f.cmid.ex
entry $f.cmid.ex.e -textvariable dimredcurvfact -font $ffont -width 3
pack $f.cmid.ex $f.cmid.ex.e -side right
$f.cmid.la config -width 4 
bind $f.cmid.ex.e <Return> {
  logcmd "set dimredcurvfact $dimredcurvfact"
  redrawbutton
}
bind $f.cmid.ex.e <ButtonRelease-3> { helpwin dimredcurvfact }
## subframe: bottom
set f .display.mi.bo
# fadef
frame $f.fy
pack $f.fy -side top
edlabval $f.fy "fad" $fadef n 4 4 row
$f.fy.fad.e config -textvariable fadef
bind $f.fy.fad.e <Return> { logcmd "set fadef $fadef"; redrawbutton }
bind $f.fy.fad.e <ButtonRelease-3> { helpwin fadef }
# ipsi yellow
edlabval $f.fy "iy" $ipsiyellowfact n 3 4 row
$f.fy.iy.e config -textvariable ipsiyellowfact
bind $f.fy.iy.e <Return> {
  logcmd "set ipsiyellowfact $ipsiyellowfact"
  redrawbutton
}
bind $f.fy.iy.e <ButtonRelease-3> { helpwin ipsiyellowfact }
# angle_cycles, angle_offset
edlabval $f "anglecycles" $angle_cycles n 13 4
edlabval $f "angleoffset" $angle_offset n 13 4
$f.anglecycles.e config -textvariable angle_cycles
$f.angleoffset.e config -textvariable angle_offset
bind $f.anglecycles.e <Return> {
  logcmd "set angle_cycle $angle_cycles"
  redrawbutton
}
bind $f.angleoffset.e <Return> {
  logcmd "set angle_offset $angle_offset"
  redrawbutton
}
bind $f.anglecycles.e <ButtonRelease-3> { helpwin angle_cycles }
bind $f.angleoffset.e <ButtonRelease-3> { helpwin angle_offset }
# move phase rev to left of angle_offset to be like csurf render panel
checkbutton $f.angleoffset.ck -variable revphaseflag \
  -text "rev" -font $ffont -padx 0
pack $f.angleoffset.ck -before $f.angleoffset.la -side left -padx 0
$f.angleoffset.la config -width 9  ;# room for "rev", next is rev!
bind $f.angleoffset.ck <ButtonRelease-1> {
  logcmd "set revphaseflag $revphaseflag"
  redrawbutton
}
bind $f.angleoffset.ck <ButtonRelease-3> { helpwin revphase }
$f.anglecycles.la config -width 15   ;# match col
# init fthresh/fslope/fmid and hideable sfthresh/sfslope/sfmid
secondsquashents

### display panel right (fslope, fmid, cslope, cmid, ipsiyel, angcyc, angoff)
#############################################################################
set f .display.ri
edlabval $f "light0" $light0 n 9 4
edlabval $f "light1" $light1 n 9 4
edlabval $f "light2" $light2 n 9 4
edlabval $f "light3" $light3 n 9 4
edlabval $f "offset" $offset n 9 4
edlabval $f "cvfact" $cvfact n 9 4
edlabval $f "blufact" $blufact n 9 4
$f.light0.e config -textvariable light0
$f.light1.e config -textvariable light1
$f.light2.e config -textvariable light2
$f.light3.e config -textvariable light3
$f.offset.e config -textvariable offset
$f.cvfact.e config -textvariable cvfact
$f.blufact.e config -textvariable blufact
bind $f.light0.e <Return> { logcmd "set light0 $light0"; redrawbutton }
bind $f.light1.e <Return> { logcmd "set light1 $light1"; redrawbutton }
bind $f.light2.e <Return> { logcmd "set light2 $light2"; redrawbutton }
bind $f.light3.e <Return> { logcmd "set light3 $light3"; redrawbutton }
bind $f.offset.e <Return> { logcmd "set offset $offset"; redrawbutton }
bind $f.cvfact.e <Return> { logcmd "set cvfact $cvfact"; redrawbutton }
bind $f.blufact.e <Return> { logcmd "set blufact $blufact"; redrawbutton }
bind $f.light0.e <ButtonRelease-3> { helpwin lights }
bind $f.light1.e <ButtonRelease-3> { helpwin lights }
bind $f.light2.e <ButtonRelease-3> { helpwin lights }
bind $f.light3.e <ButtonRelease-3> { helpwin lights }
bind $f.offset.e <ButtonRelease-3> { helpwin offset }
bind $f.cvfact.e <ButtonRelease-3> { helpwin cvfact }
bind $f.blufact.e <ButtonRelease-3> { helpwin blufact }
# jam in extra insidesurffact near related offset
entry $f.offset.e2 -textvariable insidesurffact -font $ffont -width 3
pack $f.offset.e2 -side left
$f.offset.la config -width 5
bind $f.offset.e2 <Return> {
  logcmd "set insidesurffact $insidesurffact"
  redrawbutton
}
bind $f.offset.e2 <ButtonRelease-3> { helpwin insidesurffact }

### cut surface buttons (AREA, FILL, PLANE, PTS, LINE)
#############################################################################
set f .shrink.cut
buttons $f "AREA" {
  if {$nmarked < 1} {
    confirmalert "AREA (cut_line 1 -> closed line cut): nothing to cut\
              \n\nneed at least 1 marked (left-click) vertex"
  } else {
    cut_line 1
    logcmd "cut_line 1"
    redrawbutton
  }
} row 1 0
label $f.aAREA.la -text "cuts:" -font $ffont -padx 0
pack $f.aAREA.la -side left -before $f.aAREA.bu -padx 0
checkbutton $f.ck -variable erodingfillflag -text "er" -font $ffont -command {
  .shrink.cut.ck config -text er -font $ffont
  if {$erodingfillflag} {
    logcmd "set erodingfillflag 1"
    if {$dilatingfillflag} {
      confirmalert "do erode FILL (erodingfillflag=1)\
                \n\n(makes non-verlapping adjoining labels)\
                \n\nN.B.: dilate FILL cancelled (dilatingfillflag=0)"
      set dilatingfillflag 0
      logcmd "set dilatingfillflag 0"
    } else {
      confirmalert "do erode FILL (erodingfillflag=1)\
                \n\n(makes non-overlapping adjoining labels)"
    }
  } else {
    logcmd "set erodingfillflag 0"
    confirmalert "do standard (non-eroding) FILL (erodingfillflag=0)\
              \n\n(N.B.: adjoining labels will have 1-vertex overlap)"
  }
} -padx 0 -bd 0
pack $f.ck -side left -padx 0
# overload erodingfillflag ("er") check
bind $f.ck <ButtonRelease-2> {
  .shrink.cut.ck config -text er -font $ffont
  set dilatingfillflag [expr !$dilatingfillflag]
  logcmd "set dilatingfillflag $dilatingfillflag"
  if {$dilatingfillflag} {
    if {$erodingfillflag} {
      set dilatingfillflag 0
      logcmd "set dilatingfillflag 0"
      confirmalert \
        "erode FILL (erodingfillflag=1) prevents dilate FILL (first untick)"
    } else {
      .shrink.cut.ck config -text dl -font $ffontb
      confirmalert "do dilate FILL (dilatingfillflag=1)"
    }
  } else {
    confirmalert "standard FILL (no dilate/erode) FILL (dilatingfillflag=0)"
  }
}
buttons $f "FILL" { fillbutton } row 1 0
buttons $f "PLANE" {
  if {$nmarked < 4} {
    confirmalert "PLANE (cut_plane) needs 4 marked vertices\
              \n\n3 define plane, 1 marks side to save\
              \n\n(if more than 4 vertices selected, last 4 used)"
  } else {
    cut_plane
    logcmd "cut_plane"
    if {!$lighttwosidedflag} {
      set lighttwosidedflag 1
      logcmd "set stereoflag 1"
      confirmalert "light back/inside surfaces\
                \n\n(to toggle off:  ctrl-middle-click-REDRAW)"
      redrawbutton  ;# hack (2x) to fix rand inside color of init redraw
    }
    redrawbutton
  }
} row 1 0
buttons $f "PTS" {
  if {$nmarked < 1} {
    confirmalert "PTS (cut_vertices): nothing to cut\
              \n\nneed at least 1 marked (left-click) vertex"
  } else {
    cut_vertices
    logcmd "cut_vertices"
    redrawbutton
  }
} row 1 0
buttons $f "LINE" {
  if {$nmarked < 1} {
    confirmalert "LINE (cut_line 0 -> open line cut): nothing to cut\
              \n\nneed at least 1 marked (left-click) vertex"
  } else {
    cut_line 0
    logcmd "cut_line 0"
    redrawbutton
  }
} row 1 0
# overload PTS to uncut neighbors of list
bind $f.aPTS.bu <ButtonRelease-2> {
  if {$nmarked < 1} {
    confirmalert "mid-clk PTS (uncut_connected_vertices): nothing to un-cut\
              \n\nneed at least 1 marked (left-click) vertex"
  } else {
    uncut_connected_vertices
    logcmd "uncut_connected_vertices"
    redrawbutton
  }
}
# second overload PTS to setup to fix strays
bind $f.aPTS.bu <Shift-ButtonRelease-2> {
  set pointsize 2
  logcmd "set pointsize 2"
  set pointsflag 1
  logcmd "set pointsflag 1"
  arrownormctrls
  redrawbutton
}

### ROI's + UNDO's
#############################################################################
buttons $f "ROI" { roibutton } row 1 1
buttons $f "N" { nearestbuttons 0 ${num,sqmm,mm} } row 1 2
frame $f.aN.sp -width 5  ;# insert pre-space after buttons frame there
pack $f.aN.sp -before $f.aN.bu -side left
entry $f.aN.e -textvariable "num,sqmm,mm" -font $ffont -width 3
pack $f.aN.e -side left
buttons $f "A" { nearestbuttons 1 ${num,sqmm,mm} } row 1 2
buttons $f "R" { nearestbuttons 2 ${num,sqmm,mm} } row 1 2
# overload middle click N,A,R buttons to just set fillneartype
pack $f.aN.e -side left
bind $f.aN.bu <ButtonRelease-2> {
  set fillneartype 0; logcmd "set  fillneartype 0"
  confirmalert "set fillneartype 0 (number of vertices)"
}
bind $f.aA.bu <ButtonRelease-2> {
  set fillneartype 1; logcmd "set  fillneartype 1"
  confirmalert "set fillneartype 1 (area mm^2)"
}
bind $f.aR.bu <ButtonRelease-2> {
  set fillneartype 2; logcmd "set  fillneartype 2"
  confirmalert "set fillneartype 2 (radius mm)\
            \n\nN.B.: radius criterion should be smaller than for number/area!"
}
frame $f.aR.sp -width 5
pack $f.aR.sp -side left
buttons $f "UNDO" {
  restore_ripflags 1
  logcmd "restore_ripflags 1"
  redrawbutton
} row 1 0
buttons $f "INIT" {
  restore_ripflags 2
  logcmd "restore_ripflags 2"
  redrawbutton
} row 1 1 ;# was NOCUTS
buttons $f "ALL" {
  clear_ripflags
  logcmd "clear_ripflags"
  read_binary_surface
  logcmd "read_binary_surface"
  read_binary_curv
  logcmd "read_binary_curv"
  set flag2d 0
  logcmd "set flag2d 0"
  restore
  redrawbutton
} row 1 1 ;# was INIT
buttons $f "FL" {
  flatten
  logcmd "flatten"
  set flag2d 1
  logcmd "set flag2d 1"
  restore
  redrawbutton
} row 1 0
bind $f.aAREA.la <ButtonRelease-3> { helpwin cuts }
bind $f.aAREA.bu <ButtonRelease-3> { helpwin cutregion }
bind $f.ck <ButtonRelease-3> { helpwin erode }
bind $f.aFILL.bu <ButtonRelease-3> { helpwin fill }
bind $f.aPLANE.bu <ButtonRelease-3> { helpwin cutplane }
bind $f.aLINE.bu <ButtonRelease-3> { helpwin cutline }
bind $f.aPTS.bu <ButtonRelease-3> { helpwin cutpts }
bind $f.aROI.bu <ButtonRelease-3> { helpwin roi }
bind $f.aN.bu <ButtonRelease-3> { helpwin fill2num }
bind $f.aN.e <ButtonRelease-3> { helpwin fillcrit }
bind $f.aA.bu <ButtonRelease-3> { helpwin fill2area }
bind $f.aR.bu <ButtonRelease-3> { helpwin fill2rad }
bind $f.aUNDO.bu <ButtonRelease-3> { helpwin undo }
bind $f.aINIT.bu <ButtonRelease-3> { helpwin init }
bind $f.aALL.bu <ButtonRelease-3> { helpwin nocut }
bind $f.aFL.bu <ButtonRelease-3> { helpwin flatten }

### SMOOTH
#############################################################################
set f .shrink.smooth
# button
buttons $f "SMOOTH" { } row 0 0
bind $f.aSMOOTH.bu <ButtonRelease-1>       { smoothbutton }
bind $f.aSMOOTH.bu <ButtonRelease-2>       { spotopctrls }
bind $f.aSMOOTH.bu <Shift-ButtonRelease-2> { nonoverlap2statctrls }
## R-click bind: helpwin + no-arg procs buttonbar popups
bind $f.aSMOOTH.bu <ButtonRelease-3> {
  helpwin smooth
  buttonbar \
    "\"Surface Smooth (cv)  - .curv (curv/sulc/area)                  \" \
     \"Surface Smooth (val) - .val(.val2),  and .stat if there       \" \
     \"Surface Smooth  (s)  - .stat field only                              \" \
     \"Surface Smooth  (w) - .val(.val2), distance-weighted       \" \
     \"Surface Smooth (sp) - .val(.val2), sparse, fixed-val interp\" \
     \"Surface Smooth (vo) - .val(.val2), not .stats (valonly)     \" \
     \"Surface Smooth (cr) - .val(.val2), cmplex ang w/realamp\" \
     \"Surface Smooth (gr) - .valbak(.val2bak) gradient arrows  \" \
     \"Fill Annot/Label Holes, 1-Neigh (steps = annotholes)\" \
     \"Fill .val Field Holes, 1-Neigh Avg (steps = valholes) \" \
     \"Fill Annot/Label Holes, AdjNeigh (=annotholes-neigh)\" \
     \"Erode Edges of Annot/Label (steps = annoterode)    \" \
     \"Searchlight Ops Control Popup (mid-click-SMOOTH) \" \
     \"No-overlap .stat Paintballs Popup (shift-mid-clk-SMOOTH)\"" \
    "do_smooth_curv do_smooth_val do_smooth_stat do_smooth_weight \
     do_smooth_sparse \
     do_smooth_valonly do_smooth_cpxreal do_smooth_grad \
     do_annotholes do_valholes fillholesneighctrls do_annoterode \
     spotopctrls nonoverlap2statctrls" \
    ver "SMOOTH, uses current smoothsteps" smooth
}
# smoothsteps
edlabval $f "steps" 1 n 0 3 row
$f.steps.e config -textvariable smoothsteps
pack $f.steps $f.steps.e -padx 0; pack forget $f.steps.la   ;# squish
#bind $f.steps.e <Return> "$f.aSMOOTH.bu invoke; redrawbutton"
bind $f.steps.e <Return> "smoothbutton; redrawbutton" ;# vs. invoke b/c no cmd
bind $f.steps.e <ButtonRelease-3> {
  event generate .shrink.smooth.aSMOOTH.bu <ButtonRelease-3>  ;# makes helpwin
  helpwin smooth_steps   ;# put on top
}
# smoothtype radio buttons
radios $f.steps "" "cv"     smoothtype curv    12 row
radios $f.steps "" "vo"     smoothtype valonly 12 row
radios $f.steps "" "val"    smoothtype val     12 row
radios $f.steps "" "s"      smoothtype stat    12 row
radios $f.steps "" "cr"     smoothtype cpxreal 12 row
radios $f.steps "" "w"      smoothtype weight  12 row
radios $f.steps "" "sp"     smoothtype sparse  12 row
radios $f.steps "" "gr"     smoothtype grad    12 row
bind $f.steps.acv.ra <ButtonRelease-3> { helpwin smooth_curv }
bind $f.steps.avo.ra <ButtonRelease-3> { helpwin smooth_valonly } ;# not stats
bind $f.steps.aval.ra <ButtonRelease-3> { helpwin smooth_val }
bind $f.steps.as.ra <ButtonRelease-3> { helpwin smooth_stat }
bind $f.steps.acr.ra <ButtonRelease-3> { helpwin smooth_cpxreal }
#bind $f.steps.aw.ra <ButtonRelease-3> { helpwin smooth_weight }
bind $f.steps.aw.ra <ButtonRelease-3> {  ;# sm popup to control $halfweightdist
  helpwin smooth_weight
  if [winfo exists $halfweightctrlswin] { raise $halfweightctrlswin; break }
  set halfweightctrlswin \
    [controls "DISTANCE-WEIGHTED SMOOTH\
           \n\nDistance (in mm) where Gaussian\
             \nweight drops to 0.5 for distance-\
             \nand neighbor-density-weighted\
             \nsmoothing (SMOOTH \"w\")\
           \n\nOne step at default (=0.4 mm) is\
            \nless smooth than 1 step std \"val\"\
          \n\nUseful for more gentle smoothing of\
            \nhi-res data where voxel width is near\
            \naverage mesh edge width (~0.85 mm)" \
      "whitespace halfweightdist" none none 10]
}
bind $f.steps.asp.ra <ButtonRelease-3> { helpwin smooth_sparse }
bind $f.steps.agr.ra <ButtonRelease-3> { helpwin smooth_grad }
# HOWTO max squish (to jam in 's' on F3 for stats)
$f.steps.acv.ra config -padx 0
$f.steps.avo.ra config -padx 0
$f.steps.aval.ra config -padx 0
$f.steps.as.ra config -padx 0
$f.steps.acr.ra config -padx 0
$f.steps.aw.ra config -padx 0 
$f.steps.asp.ra config -padx 0
$f.steps.agr.ra config -padx 0
# tmp hack overload val radio
# hack: middle-click on val to set from smaller interface
bind $f.steps.aval.ra <ButtonRelease-2> {
  set smoothtype cpxreal
  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"
}

### SHRINK
#############################################################################
### shrink panel head 
set f .shrink.head
buttons $f REG { startstopmorph $shrinksteps $shrinkcycles } row 1 0
buttons $f SHRINK { startstopshrink $shrinksteps $shrinkcycles } row 1 0
bind $f.aSHRINK.bu <ButtonRelease-2> {
  startstopshrink $shrinksteps $shrinkcycles 1  ;# NormArea each cycle
}
edlabval $f "steps" 1 n 5 3 row
edlabval $f "cyc" 1 n 3 3 row
$f.steps.e config -textvariable shrinksteps 
$f.cyc.e config -textvariable shrinkcycles
$f.cyc.la config -text "cyc"
checkbutton $f.ck -text "ckMRI" -variable MRIflag -font $ffont -padx 0
bind $f.ck <ButtonRelease-1> { logcmd "set MRIflag $MRIflag" }
pack $f.ck -side left -padx 7
buttons $f FAT { mriforce down } row 1 0
buttons $f THIN { mriforce up } row 1 0
bind $f.aREG.bu <ButtonRelease-3> {
  helpwin morph
  #sphimctrls  ;# buttonbar below has everything but 3D output to mgz
  event generate .files.val.bw <ButtonRelease-3>
}
bind $f.aSHRINK.bu <ButtonRelease-3> { helpwin shrink }
bind $f.steps.e <ButtonRelease-3> { helpwin shrink_steps }
bind $f.cyc.e <ButtonRelease-3> { helpwin shrink_cyc }
bind $f.ck <ButtonRelease-3> { helpwin shrink_ckMRI }
bind $f.aTHIN.bu <ButtonRelease-3> { helpwin shrink_adj }
bind $f.aFAT.bu <ButtonRelease-3> { helpwin shrink_adj }

### shrink panel main left
set f .shrink.main.le
edlabval $f "ws"   $ws   n 7 4
edlabval $f "wn"   $wn   n 7 4
edlabval $f "wa"   $wa   n 7 4
#edlabval $f "wt"   $wt   n 7 4  ;# swap area_shrink wt/wc for morph wcrv/wsta
#edlabval $f "wc"   $wc   n 7 4
edlabval $f "wcrv" $wcrv n 7 4
edlabval $f "wsta" $wsta n 7 4
#edlabval $f "wsh"  $wsh  n 7 4  ;# swap shrink2d wsh (shear) for morph wcpx
edlabval $f "wcpx" $wcpx n 7 4
#edlabval $f "wbn"  $wbn  n 7 4  ;# swap shrink2d wbn (boundnorm) for wcpx2
edlabval $f "wcpx2" $wcpx2 n 7 4
$f.ws.e   config -textvariable ws
$f.wn.e   config -textvariable wn
$f.wa.e   config -textvariable wa
#$f.wt.e   config -textvariable wt
#$f.wc.e   config -textvariable wc
$f.wcrv.e config -textvariable wcrv
$f.wsta.e config -textvariable wsta
#$f.wsh.e  config -textvariable wsh
$f.wcpx.e  config -textvariable wcpx
#$f.wbn.e  config -textvariable wbn
$f.wcpx2.e  config -textvariable wcpx2
$f.ws.la   config -text "ws (tan)"
$f.wn.la   config -text "wn (nor)"
$f.wa.la   config -text "wa (a:ar)"
#$f.wt.la   config -text "wt (a:bd)"
#$f.wc.la   config -text "wc (a2n)"
#$f.wsh.la  config -text "wsh (2d)"
$f.wcrv.la config -text "wcrv (rg)"
$f.wsta.la config -text "wsta (rg)"
$f.wcpx.la config -text "wcpx (rg)"
#$f.wbn.la  config -text "wbn (2d)"
$f.wcpx2.la config -text "wcpx2(rg)"
bind $f.ws.e   <Return> { logcmd "set ws $ws" }
bind $f.wn.e   <Return> { logcmd "set wn $wn" }
bind $f.wa.e   <Return> { logcmd "set wa $wa" }
#bind $f.wt.e   <Return> { logcmd "set wt $wt" }
#bind $f.wc.e   <Return> { logcmd "set wc $wc" }
bind $f.wcrv.e <Return> { logcmd "set wcrv $wcrv" }
bind $f.wsta.e <Return> { logcmd "set wsta $wsta" }
#bind $f.wsh.e  <Return> { logcmd "set wsh $wsh" }
bind $f.wcpx.e <Return> { logcmd "set wcpx $wcpx" }
#bind $f.wbn.e  <Return> { logcmd "set wbn $wbn" }
bind $f.wcpx2.e  <Return> { logcmd "set wcpx2 $wcpx2" }
#TODO: new helpfile (when panels stable)
bind $f.ws.e   <ButtonRelease-3> { helpwin shrink_ws }
bind $f.wn.e   <ButtonRelease-3> { helpwin shrink_wn }
bind $f.wa.e   <ButtonRelease-3> { helpwin shrink_wa }
#bind $f.wt.e   <ButtonRelease-3> { helpwin shrink_wt }
#bind $f.wc.e   <ButtonRelease-3> { helpwin shrink_wc }
bind $f.wcrv.e <ButtonRelease-3> { helpwin morph_wcrv }
bind $f.wsta.e <ButtonRelease-3> { helpwin morph_wsta }
bind $f.wcpx.e <ButtonRelease-3> { helpwin morph_wcpx }
#bind $f.wsh.e  <ButtonRelease-3> { helpwin shrink_wsh }
#bind $f.wbn.e  <ButtonRelease-3> { helpwin shrink_wbn }
bind $f.wcpx2.e <ButtonRelease-3> { helpwin morph_wcpx2 }

### shrink panel main middle
set f .shrink.main.mi
## 1st line
frame $f.self -bg $bgcol
pack $f.self -side top
# checks: self,fill,gradient
checks $f.self "" "ckself" chkselfintflag row
checks $f.self "" "ckfill" chkfilledflag row
checks $f.self "" "ckgr" chkgradampflag row
pack $f.self.ackself $f.self.ackfill $f.self.ackgr -padx 0 ;# squish
$f.self.ackself config -padx 0  ;# more squish
$f.self.ackfill config -padx 0
$f.self.ackgr config -padx 0
bind $f.self.ackself.ck <ButtonRelease-1> {
  logcmd "set chkselfintflag $chkselfintflag"
}
bind $f.self.ackfill.ck <ButtonRelease-1> {
  logcmd "set chkfilledflag $chkfilledflag"
}
bind $f.self.ackgr.ck <ButtonRelease-1> {
  logcmd "set chkgradampflag $chkgradampflag"
}
bind $f.self.ackself.ck <ButtonRelease-3> { helpwin shrink_ckself }
bind $f.self.ackfill.ck <ButtonRelease-3> { helpwin shrink_ckfill }
bind $f.self.ackgr.ck <ButtonRelease-3> { helpwin shrink_ckgr }
## 2nd line
frame $f.as -bg $bgcol
pack $f.as -side top
# self CLR,W (repl NormAr w/ck 3rd buff)
label $f.as.la -text "self:" -font $ffont
pack $f.as.la -side left
buttons $f.as "CLR" {clear_selfintersect; logcmd "clear_selfintersect"} row 0 1
buttons $f.as "W" { write_self_images; logcmd "write_self_images" } row 0 1
bind $f.as.aCLR.bu  <ButtonRelease-3> { helpwin shrink_clearself }
bind $f.as.aW.bu  <ButtonRelease-3> { helpwin shrink_writeself }
# selfd
label $f.as.la2 -text "selfd:" -font $ffont -bg $bgcol
entry $f.as.e -textvariable selfstilt -font $ffont -width 4
pack $f.as.la2 $f.as.e -side left
bind $f.as.e <Return> { logcmd "set selfstilt $selfstilt" }
bind $f.as.e <ButtonRelease-3> { helpwin shrink_selfd }
## 3rd line
frame $f.ty -bg $bgcol
pack $f.ty -side top
# chk3rd
checks $f.ty "" "ck3rd" chkthirdflag row
pack $f.ty.ack3rd -padx 0  ;# squish
bind $f.ty.ack3rd.ck <ButtonRelease-1> {
  logcmd "set chkthirdflag $chkthirdflag"
}
bind $f.ty.ack3rd.ck <ButtonRelease-3> { helpwin shrink_ck3rd }
# ar,2d
frame $f.ty.sp -width 18  ;# space to ind diff funct
pack $f.ty.sp -side left
checks $f.ty "" "ar" areaflag row
checks $f.ty "" "2d" flag2d row
pack $f.ty.aar $f.ty.a2d -padx 0  ;# squish
$f.ty.aar config -padx 0  ;# more squish
$f.ty.a2d config -padx 0
bind $f.ty.aar.ck <ButtonRelease-1> { reloadarea }
bind $f.ty.a2d.ck <ButtonRelease-1> { logcmd "set flag2d $flag2d" }
bind $f.ty.aar.ck <ButtonRelease-2> { ;# 2nd overload 
  set bordneiflag [expr !$bordneiflag]
  logcmd "set bordneiflag $bordneiflag"
  if {$bordneiflag} {
    confirmalert "area shrink bords mv using avg near nonbord vtxs"
  } else {
    confirmalert "area shrink bords mv w/orig centrifugal force"
  }
}
bind $f.ty.aar.ck <ButtonRelease-3>  { helpwin shrink_areaflag }
bind $f.ty.a2d.ck <ButtonRelease-3>  { helpwin shrink_2dflag }
## 4th line
frame $f.th -bg $bgcol
pack $f.th -side top
# lo/hi lims for chkthirdflag
label $f.th.la0 -text "ck3:lo:" -font $ffont -bg $bgcol
label $f.th.la1 -text " ck3:hi:" -font $ffont -bg $bgcol
entry $f.th.e0 -textvariable chkthird_lolim -font $ffont -width 3
entry $f.th.e1 -textvariable chkthird_hilim -font $ffont -width 3
bind $f.th.e0 <Return> { logcmd "set chkthird_lolim $chkthird_lolim" }
bind $f.th.e1 <Return> { logcmd "set chkthird_hilim $chkthird_hilim" }
pack $f.th.la0 $f.th.e0 $f.th.la1 $f.th.e1 -side left
bind $f.th.e0 <ButtonRelease-3> { helpwin shrink_ck3rd }  ;# same help as chk
bind $f.th.e1 <ButtonRelease-3> { helpwin shrink_ck3rd }  ;# same help as chk
## 5th line
frame $f.ncthr2 -bg $bgcol
pack $f.ncthr2 -side top
# locklabelflag
checkbutton $f.ncthr2.ck2 -variable locklabelflag -font $ffont -text "locklabel"
pack $f.ncthr2.ck2 -side left
bind $f.ncthr2.ck2 <ButtonRelease-1> {logcmd "set locklabelflag $locklabelflag"}
# ncthreshflag, ncthresh
checkbutton $f.ncthr2.ck -variable ncthreshflag -font $ffont -text "nc" -padx 0
pack $f.ncthr2.ck -side left
bind $f.ncthr2.ck <ButtonRelease-1> { logcmd "set ncthreshflag $ncthreshflag" }
entry $f.ncthr2.e -textvariable ncthresh -font $ffont -width 4
pack $f.ncthr2.e -side left
bind $f.ncthr2.e <Return> { logcmd "set ncthresh $ncthresh" }
bind $f.ncthr2.ck2 <ButtonRelease-3> { helpwin shrink_locklabel }
bind $f.ncthr2.e <ButtonRelease-3>   { helpwin shrink_ncthr }
bind $f.ncthr2.ck <ButtonRelease-3>  { helpwin shrink_ncthr_ck }
## 6th line
frame $f.ud -bg $bgcol
pack $f.ud -side top
# update, decay, momentum
label $f.ud.la0 -text "upd:" -font $ffont -bg $bgcol
label $f.ud.la1 -text "dec:" -font $ffont -bg $bgcol
entry $f.ud.e0 -textvariable update -font $ffont -width 3
entry $f.ud.e1 -textvariable decay -font $ffont -width 3
pack $f.ud.la0 $f.ud.e0 $f.ud.la1 $f.ud.e1 -side left
bind $f.ud.e0 <Return> { logcmd "set update $update" }
bind $f.ud.e1 <Return> { logcmd "set decay $decay" }
checks $f.ud "" "mo" momentumflag row
$f.ud.amo.ck config -anchor center -padx 0
bind $f.ud.amo.ck <ButtonRelease-1> { logcmd "set momentumflag $momentumflag" }
bind $f.ud.e0 <ButtonRelease-3>     { helpwin shrink_update }
bind $f.ud.e1 <ButtonRelease-3>     { helpwin shrink_decay }
bind $f.ud.amo.ck <ButtonRelease-3> { helpwin shrink_momentum }
## 7th line
frame $f.exp -bg $bgcol
pack $f.exp -side top
# expand, explode
checks $f.exp "" "expand" expandflag row
checks $f.exp "" "explode" explodeflag row
pack $f.exp.aexpand $f.exp.aexplode -padx 0 ;# squish
$f.exp.aexpand config -padx 0  ;# more squish
$f.exp.aexplode config -padx 0
bind $f.exp.aexpand.ck <ButtonRelease-1> {
  logcmd "set expandflag $expandflag"
}
bind $f.exp.aexplode.ck <ButtonRelease-1> {
  logcmd "set explodeflag $explodeflag"
}
bind $f.exp.aexpand.ck <ButtonRelease-3> { helpwin shrink_expand }
bind $f.exp.aexplode.ck <ButtonRelease-3> { helpwin shrink_explode }

### shrink panel main right
set f .shrink.main.ri
edlabval $f  "forcemode"    $forcemode    n 9 5
edlabval $f  "mstrength"    $mstrength    n 9 5
edlabval $f  "mslope"       $mslope       n 9 5
edlabval $f  "mmid"         $mmid         n 9 5
edlabval $f  "cthk"         $cthk         n 9 5
edlabval $f  "whitemid"     $whitemid     n 9 5
edlabval $f  "graymid"      $graymid      n 9 5
$f.forcemode.e config -textvariable forcemode 
$f.mstrength.e config -textvariable mstrength
$f.mslope.e config -textvariable mslope
$f.mmid.e config -textvariable mmid 
$f.cthk.e config -textvariable cthk
$f.whitemid.e config -textvariable whitemid
$f.graymid.e config -textvariable graymid
bind $f.forcemode.e <Return> { 
  if {$forcemode < 0 || $forcemode > 3} {
    confirmalert "bad forcemode: $forcemode\n\nOK: 0-3 (see R-click help)"
  } else {
    logcmd "set forcemode $forcemode"
  }
}
bind $f.mstrength.e <Return> { logcmd "set mstrength $mstrength" }
bind $f.mslope.e <Return> { logcmd "set mslope $mslope" }
bind $f.mmid.e <Return> { logcmd "set mmid $mmid" }
bind $f.cthk.e <Return> { logcmd "set cthk $cthk" }
bind $f.whitemid.e <Return> { logcmd "set whitemid $whitemid" }
bind $f.graymid.e <Return> { logcmd "set graymid $graymid" }
bind $f.forcemode.e <ButtonRelease-3> { helpwin shrink_forcemode }
#TODO: new helpfile (when panels stable)
bind $f.mstrength.e <ButtonRelease-3> { helpwin shrink_mstrength }
bind $f.mslope.e <ButtonRelease-3> { helpwin shrink_mslope }
bind $f.mmid.e <ButtonRelease-3> { helpwin shrink_mmid }
bind $f.cthk.e <ButtonRelease-3> { helpwin shrink_cthk }
bind $f.whitemid.e <ButtonRelease-3> { helpwin shrink_whitemid }
bind $f.graymid.e <ButtonRelease-3> { helpwin shrink_graymid }

### compute panel left
buttons .compute.le0 "NormArea" {
  normalize_area
  logcmd "normalize_area"
  redrawbutton
} row 0 1  ;# tri-broken?
buttons .compute.le "CLR CURV" {
  clear_curvature
  logcmd "clear_curvature"
  redrawbutton
} col 0 3
#buttons .compute.le "CMP FS" { compute_fieldsign } col 0
### compute panel left middle
buttons .compute.lm "CMP CURV" {
  compute_curvature
  logcmd "compute_curvature"
  redrawbutton
} col 0 3
### compute panel right middle
checks .compute.rm "" "SumSulc" sulcflag col
bind .compute.rm.aSumSulc.ck <ButtonRelease-1> {
  logcmd "set sulcflag $sulcflag"
}
### compute panel right
buttons .compute.ri "swapcplx" {
  swap_valval2_valbakval2bak
  logcmd "swap_valval2_valbakval2bak"
  redrawbutton
} col 0 3
#TODO: new helpfile (when panels stable)
bind .compute.le0.aNormArea.bu <ButtonRelease-3> { helpwin shrink_normarea }
bind ".compute.le.aCLR CURV.bu" <ButtonRelease-3> { helpwin clear_curv }
#bind ".compute.le.aCMP FS.bu" <ButtonRelease-3> { helpwin comp_fs }
bind ".compute.lm.aCMP CURV.bu" <ButtonRelease-3> { helpwin comp_curv }
bind .compute.rm.aSumSulc.ck <ButtonRelease-3> { helpwin sum_sulc }
bind .compute.ri.aswapcplx.bu <ButtonRelease-3> { helpwin swapcplx }

### compute2: fill_surface (8 widgets squished into one line)
set f .compute2
# norm move
entry $f.e0 -textvariable norm_move_mm_or_frac -font $ffont -width 3 \
  -selectbackground $selbgcol -selectforeground black  ;# linux
button $f.bn -text "N" -font $ffontb -pady 0 -padx 1 -command {
  norm_move_vertices $norm_move_mm_or_frac
  logcmd "norm_move_vertices $norm_move_mm_or_frac"
  compute_normals_areas
  logcmd "compute_normals_areas"
  redrawbutton
}
pack $f.e0 $f.bn -side left
# first overload "N" button
bind $f.bn <ButtonRelease-2> {
  norm_move_vertices_fracthick $norm_move_mm_or_frac
  logcmd "norm_move_vertices_fracthick $norm_move_mm_or_frac"
  compute_normals_areas
  logcmd "compute_normals_areas"
  redrawbutton
}
# fillpix
label $f.la1 -text "pix:" -font $ffont -bg $bgcol
entry $f.e1 -textvariable fillpix -font $ffont -width 3 \
  -selectbackground $selbgcol -selectforeground black  ;# linux
pack $f.la1 $f.e1 -side left
# fillcolor3d
label $f.la2 -text "col:" -font $ffont -bg $bgcol
entry $f.e2 -textvariable fillcolor3d -font $ffont -width 3 \
  -selectbackground $selbgcol -selectforeground black  ;# linux
pack $f.la2 $f.e2 -side left -padx 0
# includeintersectingflag ("fat")
checkbutton $f.ck -variable includeintersectingflag -font $ffont -text "fat" \
  -command { logcmd "set includeintersectingflag $includeintersectingflag" }
pack $f.ck -side left -padx 0
# fill_surface
button $f.bf -text "FILL3d" -font $ffontb -pady 0 -padx 0 -command {
  if {!$onemgzfileloaded} {
    confirmalert "No mgz file has yet been loaded:\
              \n\nFirst load example mgz file with intended resolution\
                \nusing\"R\" on \"im:\" line to define MGH header values"
  } else {
    fill_surface
    logcmd "fill_surface"
    confirmalert "3D fill of surface complete:\
              \n\nNow use bottom right \"W\" to save to images to \$fillim"
  }
}
pack $f.bf -side left -padx 0
# write_images
label $f.la3 -text "fillim:" -font $ffont -bg $bgcol
entry $f.e3 -textvariable fillim -font $ffont -width 11 \
  -selectbackground $selbgcol -selectforeground black  ;# linux
$f.e3 xview moveto 1  ;# show end of long default path
button $f.bw -text "W" -font $ffontb -pady 0 -padx 1 -command chkwritefillim
pack $f.la3 $f.e3 $f.bw -side left
# help
bind $f.e0 <ButtonRelease-3> { helpwin fill3d_mm }
bind $f.bn <ButtonRelease-3> { helpwin fill3d_normmove }
bind $f.e1 <ButtonRelease-3> { helpwin fill3d_pix }
bind $f.e2 <ButtonRelease-3> { helpwin fill3d_col }
bind $f.ck <ButtonRelease-3> { helpwin fill3d_fat }
bind $f.bf <ButtonRelease-3> { helpwin fill3d_op }
bind $f.e3 <ButtonRelease-3> { helpwin fill3d_fillim }
bind $f.bw <ButtonRelease-3> { helpwin fill3d_saveim }

############################################################################
# all traces
############################################################################
trace add variable dip_spacing write fixdecname
trace add variable colscale write fixcolscale
#trace add variable fthresh write var2log  ;# too verbose, just bind to Return

## old syntax example
#trace variable colscale w fixcolscale

############################################################################
# monitor shift key for action modifier (only curr use: suppress select_patch)
############################################################################
# occasionally gets stuck?
# (N.B.: tksurfer.c do_all_glx_events:shiftkeypressed static GLXwin-only)
set shiftkeypressed 0
bind . <KeyPress-Shift_L>   { set shiftkeypressed 1 }
bind . <KeyRelease-Shift_L> { set shiftkeypressed 0 }

############################################################################
# shortcut key bindings
############################################################################
# Mac noeffect/reserved:  a,c,h,m,n,q,v,w,x,z
# Mac useable:  b,d,e,f,g,i,j,k,l,o,p,r,s,t,u,y,-,+,=,*,/
# [Mac remaining:  b,d,e,j,k,p,t,*,/]

## plain keys (N.B.: plain letter keys will get typed into entries)
# interface size
bind . <F2> { mini; logcmd "mini" }    ;# requires fn-F? on Mac
bind . <F3> { macro; logcmd "macro" }

## key combos: alt/cmd + key (redrawbutton call to transform does logcmd's)
# rotate brain (require cmd key in interface window)
bind . <$xcmd-Up>    { set xrot  2; redrawbutton }
bind . <$xcmd-Down>  { set xrot -2; redrawbutton }
bind . <$xcmd-Right> { set yrot -2; redrawbutton }
bind . <$xcmd-Left>  { set yrot  2; redrawbutton }
bind . <$xcmd-Control-Right> { set zrot -2; redrawbutton }
bind . <$xcmd-Control-Left>  { set zrot  2; redrawbutton }

# translate brain (require cmd key in interface window)
bind . <$xcmd-Shift-Up>    { set ytrans 2; redrawbutton }
bind . <$xcmd-Shift-Down>  { set ytrans -2; redrawbutton }
bind . <$xcmd-Shift-Right> { set xtrans 2; redrawbutton }
bind . <$xcmd-Shift-Left>  { set xtrans -2; redrawbutton }
# scale brain (require cmd key in interface window)
bind . <$xcmd-plus>  { set scalepercent 101; redrawbutton }
bind . <$xcmd-equal>  { set scalepercent 101; redrawbutton } ;# dup
bind . <$xcmd-minus> { set scalepercent 99; redrawbutton }
# SEND/GOTO
bind . <$xcmd-g> { ".draw.main.aGOTO PNT.bu" invoke }
bind . <$xcmd-f> { ".draw.main.aSEND PNT.bu" invoke }
# redraw/restore
bind . <$xcmd-r> { redrawbutton }
bind . <$xcmd-R> { restore }
# overlayflag
bind . <$xcmd-l> {
  set overlayflag [expr !$overlayflag]
  logcmd "set overlayflag $overlayflag"
  redrawbutton
}
# bigcursor
bind . <$xcmd-k> {
  set bigcursorflag [expr !$bigcursorflag]
  logcmd "set bigcursorflag $bigcursorflag"
  if {$bigcursorflag} {
    confirmalert "BIG surface cursor (also neighboring vertices)"
  } else {
    confirmalert "NORMAL surface cursor (one vertex)"
  }
}
# fmid
bind . <$xcmd-i> {
  set fmid [format "%%2.2f" [expr $fmid - 0.1]]
  logcmd "set fmid $fmid"
  redrawbutton
}
bind . <$xcmd-I> {
  set fmid [format "%%2.2f" [expr $fmid + 0.1]]
  logcmd "set fmid $fmid"
  redrawbutton
}
# fmid -- bigger steps for raw fourier amp
bind . <$xcmd-u> {
  set fmid [format "%%2.2f" [expr $fmid - 10.0]]
  logcmd "set fmid $fmid"
  redrawbutton
}
bind . <$xcmd-U> {
  set fmid [format "%%2.2f" [expr $fmid + 10.0]]
  logcmd "set fmid $fmid"
  redrawbutton
}
# fslope
bind . <$xcmd-s> {
  set fslope [format "%%2.2f" [expr $fslope-0.5]]
  logcmd "set fslope $fslope"
  redrawbutton
}
bind . <$xcmd-S> {
  set fslope [format "%%2.2f" [expr $fslope+0.5]]
  logcmd "set fslope $fslope"
  redrawbutton
}
# angle_offset
bind . <$xcmd-o> {
  set angle_offset [format "%%2.2f" [expr $angle_offset - 0.01]]
  logcmd "set angle_offset $angle_offset"
  redrawbutton
}
bind . <$xcmd-O> {
  set angle_offset [format "%%2.2f" [expr $angle_offset + 0.01]]
  logcmd "set angle_offset $angle_offset"
  redrawbutton
}
# angle_cycles
bind . <$xcmd-y> {
  set angle_cycles [format "%%2.2f" [expr $angle_cycles - 0.1]]
  logcmd "set angle_cycles $angle_cycles"
  redrawbutton
}
bind . <$xcmd-Y> {
  set angle_cycles [format "%%2.2f" [expr $angle_cycles + 0.1]]
  logcmd "set angle_cycles $angle_cycles"
  redrawbutton
}
# kill FILL
bind . <$xcmd-F> { set killfillflag 1 }
# UNDO (cuts) button
bind . <$xcmd-z> { .shrink.cut.aUNDO.bu invoke }

############################################################################
# choose interface size, tweak arrows
############################################################################
puts "tksurfer.tcl: startup done"

# N.B.: w/command line script, these execute before gl window up
fixcolors
shrinkcomboarrows
if [info exists env(tksurferinterface)] {   ;# env opt
  if {$env(tksurferinterface) == "macro"} { mini; macro; update }
  if {$env(tksurferinterface) == "mini"}  { mini;        update }
} elseif [info exists tksurferinterface] {  ;# cmdline opt
  if {$tksurferinterface == "macro"} { mini; macro; update }
  if {$tksurferinterface == "mini"}  { mini;        update }
} else {  ;# default
  mini
  update
  puts "tksurfer.tcl: default mini interface (change: macro,mini)"
  puts "tksurfer.tcl: or: setenv tksurferinterface {macro,mini}"
}
puts "tksurfer.tcl: version: $tksurfertcl_version"
logcmd "# tksurfer.tcl startup done (cmdline script, interface cmds next)"
after 1000 {
  if {$flag2d} {
    wm title . "tksurfer ($subject $hemi $surfext -- [file tail $patch])"
  }
}
if ![info exists env(FSURF_DIR)] {   ;# remove button that uses MGH mris_pmake
  pack forget .xform.translate.bot.la.bot.bus.bu2 -side left -padx 2
}

### for small screen, move tools window left so it doesn't overlap GLwin
# increase arg to 'after' if GLwin takes longer to render
if { [info exists smallscreenflag] && $smallscreenflag } {
  after 2000 { wm geometry . +0-0 }  ;# lower left
  set followglwinflag 0
}

############################################################################
# various hacks
############################################################################
### stopgap til non-C $dir repl by exported scname/$scandir in std tclscripts
# N.B.: csurf $scandir contains "image", scname/$dir/$scandir does not!!
# N.B.: C-scname *is* now exported to tcl $scandir, so note above is stale
### 1 May 2014: commented out next -- timecourses OK
#proc dir2scandir { varName index op } {
#  global dir scandir
#  set scandir $dir ;# C:scname=>write_timecourses, tcl:$scandir=>"T" button
#}
#if [info exists scandir] { trace variable dir w dir2scandir }

### tk debug: try to distinguish
#.draw.curvswitch.ck0 config -bg green  ;# works
#.draw.curvswitch.ck1 config -bg green -bd 10 ;# no effect
#.draw.curvswitch.ck2 config -bg green
#.draw.curvswitch.ck3 config -bg green

## 8.5.18: can't enter into bare '-' ttk:entry (tk:entry/entry OK on 8.5.19)
#ttk::entry .asdf1 -textvariable colscalebar_width
#pack .asdf1

### horrible tmp hack gives 20x drawing speedup (Yosemite+ 5sec->250ms, AppNap?)
# 10.15: tried mv to mini/macro for F2/F3: slow tk draw starts before xterm (?)
if {$mac_appnap_hack} {
  # tkwait so tk win mv'd from def upper left to below GLwin before xterm copy
  ### workaround (in csurf) for tkwait problem w/csurf log open on MacOS 10.15:
  # --following tkwait works as expected if csurf log is closed
  # --if csurf log is open, log lines are drawn very slowly (compared to 10.6)
  # --tkwait then fails/hangs/blocks even though tk win gets completely drawn?
  # --GLwin is never opened (GL only made when C event loop starts, after tcl)
  # --hack^2: csurf surftestrender turns $macappnap_hack OFF if $logflag ON
  tkwait visibility .  ;# returns before widgets drawn, but after mv below GLwin
  set geom +[winfo rootx .]+[winfo rooty .]   ;# copy for hack xterm position
  set xtermpid [exec xterm -geom 105x25${geom} -bg $bgcol -e bash --norc &]
  #after 500 { exec kill $xtermpid }
  #after 800 { exec kill $xtermpid }  ;# usu works for 10.15 on fast machine
  #after 1000 { exec kill $xtermpid } ;# req'd w/slow USB boot disk 
  after 2000 { exec kill $xtermpid } ;# req'd for polletdilima avg on fast 10.15
  unset geom
} else { set xtermpid -1 }

