#### write (convert) vtx data ####
-------------------------------------------
funct: "Write Curr Val to *.w File (left-click-W)"
  set val <outfile>
  write_binary_values
-------------------------------------------
functs: "Conv FT Amp To Percent (mid-click-W)"
  compute_tseriesavg2stat
    [output to .stat field of vtxs, next uses as inp]
  compute_dftamp2pcnt2stat $avg_rawamp $time_points
    [output to .stat field of vtxs]
-------------------------------------------
funct: "Write MGH 1D *.mgh File (ctrl-left-click-W)"
  set val <outfile>    [should end in *.mgh]
  write_mgh_values
-------------------------------------------
funct: "Write VTK *.vtk ValOnly File (ctrl-mid-click-W)"
  set val <outfile>    [should end in *.vtk]
  write_vtk_values
-------------------------------------------
funct: "Write VTK Surf/Val File (shift-ctrl-mid-click-W)"
  set val <outfile>    [should end in *.vtk]
  write_vtk_surface_plus_values
-------------------------------------------
funct: "Write Curv to Sphim (shift-mid-click-W)"
  [output to internal 'reverse paint' sph vol]
  surf2sphim 0   [0=curvim]
-------------------------------------------
funct: "Write Stat to Sphim (shift-right-click-W)"
  [output to internal 'reverse paint' sph vol]
  surf2sphim 1   [1=statim]
-------------------------------------------
functs: "Write val/val2 to Sphim (shift-left-click-W)"
  [output to internal 'reverse paint' sph vol]
  surf2sphim 2   [2=realim]
  surf2sphim 3   [3=imagim]
-------------------------------------------
functs: "Write val/val2baks Sphim (shift-ctrl-left-clk-W)"
  [output to internal 'reverse paint' sph vol]
  surf2sphim 4   [4=realim2]
  surf2sphim 5   [5=imagim2]
-------------------------------------------
funct: "Debug/View SphimPanel (shift-ctrl-right-clk-W)"
  sphimctrls     [for debug]
-------------------------------------------


Detailed Description of "W" Button Actions

-------------------------------------------
funct: "Write Curr Val to *.w File (left-click-W)"
  set val <outfile>
  write_binary_values
-------------------------------------------

A default left-click on the "W" button writes out
current (possibly smoothed) value of the
per-vertex .val field to the file $val (filename
in entry to left, after expansion of any
abbreviation).  Must confirm overwrite (direct
use of C/tcl function write_binary_values doesn't
ask).

Default is to write valfile/wfile/*.w format,
which contains only non-zero vertices.

To write wfile containing all vertices, first
use:

  set allverticesflag 1

To instead write out a newcurv format file
(always contains all vertices, so ignores
allverticesflag), first use:

  set val2newcurvflag 1

A middle-click on the "val:" label makes a popup
for interactively controlling these 2 flags.

For details of different binary formats, see
R-click help for "val:" field.  Formats are
auto-detected on read.

-------------------------------------------
functs: "Conv FT Amp To Percent (mid-click-W)"
  compute_tseriesavg2stat
    [output to .stat field of vtxs, next uses as inp]
  compute_dftamp2pcnt2stat $avg_rawamp $time_points
    [output to .stat field of vtxs]
-------------------------------------------

An alternative middle-click on the "W" button
brings up a popup that converts raw Fourier
transform data to vertexwise percent responses,
displays the results, and also writes them to a
wfile (infix: _%).

To do this, we need the time series average
brightness.  This can either be calculated from
the raw time series BRIK if this is available, or
it can be entered directly, if it is not
available (e.g., phase average, or cross-subj
average).

(1) First, load the complex-valued raw Fourier
amplitude wfiles to the surface.  Pick the _x (or
_y) surface wfile from the "val:" dropdown and
click "R" (picking either loads both).

(2) Second, if raw data is present, load it.
This can be done quickly by ctrl-mid-clicking the
surface (to display a single vertex timecourse,
which auto-loads the rawdata), or more explicitly
as follows:

  click "val:" label to change it to "val3d:"
  click "RD" to get read rawdata popup
  select rawdata timeseries BRIK in dropdown
  click READ RAWDATA & REGISTRATION on popup

[now back to the RAW FOURIER TO PERCENT popup]

(3) Third, find average rawdata brightness.  If
rawdata has been loaded, click:

  COMPUTER AVG t-SERIES EACH VTX

on the popup.  Once this finishes, the
.stat field will contain the rawdata average
for each vertex, the $avg_rawamp entry will be
reset to "vtxwise", and the number of
$time_points will be set.

If no rawdata is available, manually enter the
average rawdata brightness (voxels in brain - or
brains), and the number of timecourse timepoints.

  avg_rawamp:  avg brain voxel timecourse brightness
  time_points:    TRs in timecourse (e.g., 512)

(4) Finally, compute percent response by
clicking:

  COMPUTE PERCENT RESP

on the FOURIER TO PERCENT RESPONSE popup.  The
.stat field at each vertex will now be replaced
with response percent, which will then be swapped
to the viewable .val field, the color scale
adjusted to display real values, and finally, the
average rawdata amplitude will be written to a
wfile with a "_%" infix.

To return to viewing the complex data, re-swap
stat and val, by left-clicking S/V.

Implementation details

The tcl/C function to calculate the vertexwise
raw data average is:

  compute_tseriesavg2stat

The tcl/C function to calculate percent resp is:

  compute_dftamp2pcnt2stat $avg_rawamp $time_points

In tksurfer.tcl, the proc writedftampctrls makes
the popup and the two popup buttons call the
following tcl proc's:

  do_computetseravgs
  do_writedftamp

which finally call the two C/tcl functs above.

N.B.: results are valid only if the
complex-valued raw Fourier transform of
timeseries has been read onto the surface (these
wfile typically have _x,_y infixes).

This *vertexwise* operation partly overlaps with
shift-left-click on the "T" button, which, by
contrast, displays the average response percent
across all the vertices in *label*.

The tcl/C functions run by do_writedftamp
include:

  compute_dftamp2pcnt2stat $avg_rawamp $time_points
  swap_stat_val
  set complexvalflag 0
  set colscale 6
  set fmid 0.6
  set fslope 2.0
  setfile val ${stem}_%-${hemi}.w
  write_binary_values

If -1.0 is entered for the $avg_rawamp argument
above, this is a flag meaning use average rawdata
amplitude currently saved in .stat field (vs. use
the argument value, which should be positive).

Here is the C-code for compute_dftamp2pcnt2stat:

  if (avgrawamp == -1.0) usestat = 1;
  for (k=0; k<vertexcnt; k++) {
    dftamp = hypot(vertex[k].val,vertex[k].val2);
    pcnt = dftamp;            /* assume _x,_y in val/val2 */
    pcnt /= (float)tcnt;      /* norm discrete FT */
    if (usestat)
      pcnt /= vertex[k].stat; /* resp frac (use .stat) */
    else
      pcnt /= avgrawamp;      /* resp frac (use func arg) */
    pcnt *= 2.0;              /* incl pos+neg freqs */
    pcnt *= 2.0;              /* report peak-to-peak */
    pcnt *= 100.0;            /* percent */
    vertex[k].stat = pcnt;    /* save to .stat */
  }

As always, to see exactly what's going on, click
the "tcl:" label to see tcl commands as they are
executed by interface clicks.

N.B.: ctrl-middle-clicking a vertex to display
the timecourse can also display the percent
response once the 3D _x,_y BRIKs have been loaded
as follows:

  click "val:" label to change it to "val3d:"
  click "RD" to get read rawdata popup
  select _x (or _y) 3D BRIK in dropdown
  click "R" on "val3d:" line (auto-reads both)

When a vertex is ctrl-middle-clicked, the 3D
rawdata is auto-loaded (if not already), and then
both the rawata and the 3D Fourier _x,_y data is
re-sampled to the surface in order to calculate
percent response.  To see the exact same percent
responses as the functions above (which use the
_x,_y wfiles that have already been sampled to
the surface), be sure the surface smoothing of
the _x,_y files (or lack of it) is the same in
both cases.


-------------------------------------------
funct: "Write MGH 1D *.mgh File (ctrl-left-click-W)"
  set val <outfile>    [should end in *.mgh]
  write_mgh_values
-------------------------------------------

An second alternative ctrl-left-click on the "W"
button writes out the currently displayed values
in the per-vertex .val field to a 1D, one-frame,
float .mgh file, using the current filename in
the "val:" entry (tcl variable: $val).  This file
contains all vertices.

This can be read back onto the surface in using
the "R" button on the "val:" line (format is
auto-detected).


-------------------------------------------
funct: "Write VTK *.vtk ValOnly File (ctrl-mid-click-W)"
  set val <outfile>    [should end in *.vtk]
  write_vtk_values
-------------------------------------------

A third alternative ctrl-middle-click on the "W"
button writes out the currently displayed values
in the per-vertex .val field to a 1D, one-column,
float ASCII .vtk file, using the current filename
in the "val:" entry (tcl variable: $val).  This
file contains all vertices.

The resulting output file begins like this:

POINT_DATA <numvertices>
SCALARS EmbedVertex float 1
LOOKUP_TABLE default
1.293870
5.293872
...
...

There should be <numvertices> lines of values
following the 3-line header.  This file can be
read back onto the surface using the "R" button
on the "val:" line.

It is *not* a valid *.vtk file by itself (tho
tksurfer can read it -- see below).  It is
designed to be contatenated onto the end of an
ASCII .vtk surface with the same number of
vertices.  For example:

  cat lh.surf.vtk lh.vals.vtk > lh.surf+vals.vtk

The end result of concatenation should look like
this:

# vtk DataFile Version 3.0
BB4T130527_S4_mp2rage_0_inf_profiles
ASCII
DATASET POLYDATA
POINTS 954296 float
43.35591 108.78648 122.05577
43.44609 108.62583 122.07568
...
...
19.28717 77.35710 24.23914
19.33012 77.21865 24.23220
POLYGONS 1908740 7634960
3 2 1 0
3 1 3 0
...
...
3 954295 954257 954255
3 954295 954252 954257
POINT_DATA 954296
SCALARS EmbedVertex float 1
LOOKUP_TABLE default
1.293870
5.293872
...
...

The "R" button on the "val:" line will accept
either the bare POINT_DATA file or a full, valid
surface-plus-data *.vtk file.


-------------------------------------------
funct: "Write VTK Surf/Val File (shift-ctrl-mid-click-W)"
  set val <outfile>    [should end in *.vtk]
  write_vtk_surface_plus_values
-------------------------------------------

The fourth alternative shift-ctrl-middle-click on
the "val:" line "W" button writes out the current
surface as an ASCII *.vtk file and auto-appends
the current real vertex-wise values in one
operation (as described in previous section).


-------------------------------------------
funct: "Write Curv to Sphim (shift-mid-click-W)"
  [output to internal 'reverse paint' sph vol]
  surf2sphim 0   [0=curvim]
-------------------------------------------
funct: "Write Stat to Sphim (shift-right-click-W)"
  [output to internal 'reverse paint' sph vol]
  surf2sphim 1   [1=statim]
-------------------------------------------
functs: "Write val/val2 to Sphim (shift-left-click-W)"
  [output to internal 'reverse paint' sph vol]
  surf2sphim 2   [2=realim]
  surf2sphim 3   [3=imagim]
-------------------------------------------
functs: "Write val/val2baks Sphim (shift-ctrl-left-clk-W)"
  [output to internal 'reverse paint' sph vol]
  surf2sphim 4   [4=realim2]
  surf2sphim 5   [5=imagim2]
-------------------------------------------
funct: "Debug/View SphimPanel (shift-ctrl-right-clk-W)"
  sphimctrls
-------------------------------------------

The fifth, sixth, seventh, and eight alternative
operations -- shift-middle-click and
shift-right-click and shift-left-click and
shift-ctrl-left-click on the "val:" line "W"
button -- perform a "reverse paint" of the vertex
data from the current spherical (or other)
surface into a 3D volume (a thin shell) for use
as one (or more) morph targets for sphere_morph
("REG" button on F3 interface).

See also, interactive pop-up available in large
F3 interface by clicking the bold "im:" label,
which can also allow converting any one spherical
shell to an *.mgz volume (~/mri/sphim.$hemi.mgz)
for debugging/display by tkmedit.  Pop-up also
available on standard F2 interface using
shift-ctrl-right-click-"W".

The source for the reverse paint operation are
the data values currently loaded into one of the
following fields on the surface (error/no-op if
not loaded):

   vertex[i].curv		[surf2sphim 0]
   vertex[i].stat		[surf2sphim 1]
   vertex[i].val		[surf2sphim 2]
   vertex[i].val2		[surf2sphim 3]
   vertex[i].valbak		[surf2sphim 4]
   vertex[i].val2bak		[surf2sphim 5]

To avoid holes/aliasing when sampling surface
vertex data (ico vertex spacing ~0.95 mm) to the
"reverse painted" 3D shells (1x1x1mm), the 3D
voxels are set at each point along a normal
search at each vertex starting at -2.0 mm inside
the sphere to 2.0 mm outside the sphere in steps
of 0.1 mm.  To remove the few remaining holes, a
nearest neighbor hole-filling operation is
performed after sampling.

N.B. current files in the "curv:" and/or "val:"
entries are NOT reloaded.

N.B.: to load the .stat field, first "R"
(read_binary_values) a *.w file to get it into
the .val field, then "S/V" (swap_stat_val).

N.B.: to load the .val2 field, first "R"
(read_binary_values) a *.w file containing the
imaginary component to get it into the .val
field, then middle-click-"S/V" (swap_val_val2) to
get it into the .val2 field.  Finally, load the
.val field with another "R" (read_binary_values)
using a *.w file containing the real-valued
component.

N.B.: to load the .valbak and .val2bak fields,
first load the imaginary and real components of a
second complex-valued data set into .val2 and
.val as above.  Then shift-mid-click "S/V"
(swap_valval2_valbakval2bak) to get this second
complex data set into .valbak and .val2bak.
Finally, load the first complex-valued data set
into .val and .val2 (again as above).

N.B.: a data shell can be generated for other
surfaces (e.g., inflated), but sphere_morph()
doesn't (yet) support morphing on them (the
original 'tractor beams' idea!).

Example

To load the curvature image target volume, first
read desired curvature target data onto surface,
then "reverse paint" it to a volume:

  select sulc file from dropdown
  [left-click "R" on "curv:" line]
  shift-middle-click "W" button on "val:" line

or as tcl commands:

  set curv ~/surf/$hemi.sulc
  read_binary_curv
  surf2sphim 0

