[current new release: 02 May 2026]

###################################################################
UPDATE:  @@ Dec 2026
###################################################################

-------------------------------------------------------------------
Summary:
  (1) ARM compile for MacOS 26 (Tahoe)
  (1) calculate/display rawdata covariance
  (2) ...
-------------------------------------------------------------------

-------------------------------------------
(1) ARM compile for MacOS 26 (Tahoe)
-------------------------------------------

The Mac upgrade from MacOS 25 (Sequoia) to MacOS
26 (Tahoe) broke all X11/OpenGL apps running on
XQuartz (e.g., glxgears).  Intrepid programmers
(above my pay grade) tracked down some of the
problems and prepared a homebrew 'tap' of working
X11 and GL libraries (mesa25.4.3 -- N.B.: the
latest mesa26 is itself broken on Tahoe).

I compiled all the csurf programs on Tahoe against
the fixed libs, so tksurfer, etc, should now run:

    https://pages.ucsd.edu/~msereno/csurf/csurf0.8-arm-260622.tgz

To avoid having to unquarantine a downloaded
tarfile on Mac, download and unpack in one step:

    cd <install_dir>
    curl -L 'https://server/file.tgz' | tar xz

To unquarantine an already unpacked csurf, do:

    cd <directory_that_contains_csurf_dir>
    sudo xattr -r -d com.apple.quarantine csurf

This distribution includes the fixed X11 and GL
mesa libraries within it, so it should just work
on Tahoe, even with the broken XQuartz and without
homebrew installed.  Just cd into csurf and first
first run FreeSurferEnv.{c}sh, so that csurf apps
can find the fixed X11/GL libraries.  This is a
stopgap until XQuartz is (hopefully) fixed.

N.B.: this distribution *doesn't* contain any
AFNI, but you can link to a working afni with:

  cd csurf           # wherever you installed it
  rm -rf afni        # in case anything stale there
  mkdir -p afni/bin  # make a fresh dir visible to csurf
  cd afni/bin        # cd into it
  ln -s <fullpath_to_dir_containing_afni> Darwin-arm64  # make link to yours

N.B.: This has only been tested on Tahoe on an ARM
(apple silicon) machine, so I don't know if it
will run on ARM/Sequoia or earlier.  If you have
any info on this, please email me!

N.B.: This distribution *won't* work on an
Intel/Tahoe machine (arm64-only binaries).  I
don't yet have -arch x86_64 csurf compiles working
on my ARM/Tahoe machine (and still need to get an
Intel/Tahoe machine for testing).



-------------------------------------------
(2) calculate/display rawdata covariance
-------------------------------------------

New (very) basic functionality to calculate and
display rawdata time series covariance has been
added.  There are 4 new C/tcl functions:

  calc_rawdata_covar
  write_rawdata_covar
  read_rawdata_covar
  copy_rowcovar_val

These functions can be accessed via the buttonbar
from a R-click on the "X" (cross-corr) button on
the "label:" line.

The first step is to set up a new functional
session with a scandir containing a raw time
series data BRIK and register that rawdata to a
subject in the standard way (makes register.dat).

Then read the rawdata BRIK into tksurfer using the
alternate 3D buttons on the "val:" line:

 (1) click "val:" to toggle it to "val3d:"
 (2) click "RD" to get rawdata popup
 (3) select rawdata BRIK from popup "val3d:" dropdown
 (4) click "READ RAWDATA and REGISTRATION"

Next, click "label:" to get NormSamp controls and
set the sampling method and sampling point, using
either mm or fraction of cortical thickness:

  if normdfracflag unticked (mm above orig surface),
  set normdsamp, normdmax equal (e.g., 1.0 [mm])

  if normdfracflag ticked (fraction of cort thickness above),
  set normdfracsamp, normdfracmax equal (e.g., 0.6 [=60%])

Next, R-click the "X" button on the "label:" line
to get a popup and click "Calculate RawData
Covariance" (there will be an error if you are
sampling a range, not a point, along the surface
normals).

This procedure first finds 'representative' or
'unique' vertices.  That is, for each sampled 3D
voxel, find the surface vertex closest to the 3D
positional average of all the vertices that
sampled that voxel (to avoid having duplicate
entries in the covariance matrix). N.B.: to see
the 'representative' vertices, click "UQ" on the
"val3d:" line after "Calculate RawData Covariance"
has run.

The C/tcl functions run by "Calculate RawData
Covariance" are:

  rawdatasubbrik_to_paintable 0   # extract first frame of rawdata
  paint_surface 0                 # 'paint' to surf to find sample voxels
  find_uniqsamp_vertices          # find voxel-unique 'representative' vtxs
  calc_rawdata_covar              # calculate covariance matrix

N.B.: you can do the first three operations
manually one at a time from the tksurfer interface
as follows:

  (1) click "MAKE FIRST VOL PAINTABLE (for uniq)" on popup
  (2) click "PA" button on "val3d:" line
  (3) click "UQ" button on "val3d:" line

(these will be harmlessly redone by "Calculate
RawData Covariance").

Each covariance matrix entry (for a pair of
vertices, v1 and v2) is computed in the usual way
as follows (sum is across t):

           Sum[(v1 - v1_avg) * (v2 - v2_avg)]
corr =   -------------------------------------
                       n - 1

which results in a symmetric matrix with variances
along the diagonal.

To view individual rows of the covariance matrix,
click "Display Correlation for CurrVertex" on the
Label "X" popup, after selecting a 'seed' vertex
(the actual seed will be the 'representative'
vertex closest to your selected vertex).  The
first time this runs, the colscale will be set to
sane values to display the correlations:

  set overlayflag 1
  set truncphaseflag 0
  set complexvalflag 0
  set statmaskampflag 0
  set colscale 11
  set fslope 0.1
  set fthresh 5.0
  set fmid 10.0

Since the (large) covariance matrix (about 13K by
13K) only contains 'representative' vertices, the
correlation data is first interpolated on the
surface with smooth_val_sparse (the "sp" option
for the SMOOTH button).  During this smoothing,
the values at 'representative' vertices are fixed
and only the undefined vertices in between are
interpolated (20 steps).

Finally, to export the covariance matrix to the
current scandir to analyze it with external tools,
use the "Write RawData Covariance" button on the
R-click "X" popup.  This will write out two files
in the current scandir with standard names.  The
first file:

  $hemi-CovarianceMatrix.float

is the covariance matrix, written as a string of
floats in standard freesurfer byte order (MSB).
Use AFNI 4swap to convert to Intel (LSB) byte
order to read the binary data into an external
program, for example:

  4swap rh-CovarianceMatrix.float

The indices of the rows and columns of this matrix
are sequentially numbered 'representative'
vertices, which are a subset of full vertex
subset.  So, in addition to the covariance matrix,
an ASCII file of the original full surface vertex
numbers of these 'representative' vertices is also
written to:

  $hemi-CovarianceMatrixVnums.txt

Since it takes a minute to calculate the large
covariance matrix, you can read a previously
calculated matrix into tksurfer with "Read RawData
Covariance" on the R-click "X" buttonbar popup.

Finally, a new popup to select/query vertices by
vertex number and dispay time series is available
by R-clicking the REDRAW button and clicking the
bottom "Select Vertex By Number Popup" button
(mainly for debugging).  The buttons are:

  CURRENTLY SELECTED VTX   (from display window click)
  SELECT VERTEX BY NUMBER
  SHOW VERTEX TIMECOURSE
  SHOW UNIQSAMP VERTICES


-------------------------------------------
(3) ...
-------------------------------------------
...


-----------------------------------------------
Bug fixes, small changes
----------------------------------------------

UQ popup reports sampvtxcnt, uniqvtxcnt, vtxs per voxel

NormSamp popup: enable/disable relevant parms: normdfracflag, bokflag



##########################################################################
UPDATE: @@ Dec 2026
##########################################################################

[LATEST IN PROGRESS]

   [tmprelease 260622]
--mkcsurflist,update-csurf: now recognize csurf0.8-arm-YYMMDD.tgz
      ------- MacOS 26 Tahoe (release=25) compile working ---------
--FreeSurferEnv.{c}sh: v17: cleanup old, align sh/csh versions
--mk0: add new mpeg_{play,encode} patches for Tahoe
--mk0: arm64 insttmp adds precompiled mesa-25.4.3 libs $CSURF_DIR/X11GL
--mk0: dist incl's 60M precompiled mesa-25.4.3: dist/precompiled/X11GL
--mk0: MacOS 26 Tahoe compile working w/precompiled brew
--{tkmedit/tkregister/tkstrip}.c -- clean up "unsed but set" warnings
--Makefile tkregister: ifeq(${macCGLparms),1) for optional gcc ... -DmacGLparms
--mk: use getonearch to export $macCGLparms 0|1 (CGL parms gone post-Catalina)
--getonearch: also report 0|1 for $macCGLparms (CGL parms gone post-Catalina)
--tkregister.c: #ifdef macCGLparms, include CGLSetParameter swapInterval
--Makefile tkmedit/tkregister/tkstrip: same lib/incl logic as Makefile tksurfer
--tksurfer Makefile: add $macx11gl (xquartz vs. systbrew vs. csurfbrew) logic
--mk: get $macx11gl from getonearch, export it to makefile env
--getonearch: can now output $macx11gl, proc arm -> $oneproc=arm64 (was x86_64)
--tksurfer.c: fix many 'set but not used' and 'misleading indentation' warnings
--tksurfer.c: fix samevtxthickflag no-op in move_along_normal,bug intro'd Jun'24
--tksurfer.tcl: harmonize read_{mgh,poi,obj,gifti}_to_annot set transparency
--tksurfer.c: read_{gifti,obj,poi}_to_annot: init avgx,y,z (drawnames crashers)
--tksurfer.c: read_{gifti,obj,poi}_to_annot: forgot find_regionvtx_nearest_avg
--tksurfer.c: add getkernelreleasenum(),override doublebufferflag Tahoe+/kern>24
--tksurfer.c: add getkernelreleasenum(),override doublebufferflag Tahoe+/kern>24
--mk0: mk0 <badtarg> now gives error (vs. silence)
 ftgl: use homebrew GL libs (same as GLX programs, tksurfer etc), patch demo
 tiff/ezxml/freetype: worked as is
 tix: use consistent (e.g., homebrew) X11 (not just GL) libs
 tix: awk "#include <ctype.h>" to generic/tix{GrUtl,ImgXpm}.c for isspace
 tix: X11 link to *tk* dir already on tix -L path: fix no find -lX11 Mac
 tk/tix: use same X11 libs as libftgl, GLX progs (tksurfer etc)
 tk: use consistent (e.g., homebrew) X11 (not just GL) libs
 tk: patch missing _fixstrtod: add fixstrtod.o to Makefile GENERIC_OBJS
 tk: patch missing _fixstrtod: cp tcl-compiled fixstrtod.o into tk
 tcl: ranlib strtod.o, fixstrtod.o to fix dup'd symbols
 tcl: typedef int->long ptrdiff_t tclInt.h fix tclUnixTime.c redef xc12.4+
 use tcl8.5/tk8.5/tix8.4 (vs. 8.6) for less interface adjust, less tix patch
--mk0: add $kernelreleasenum, homebrew mesa-25.3.4 X11+GL if BigSur+
--wheel.c: first successful port w/homebrew tap patched mesa-25.3.4 (GL + X11!)
      ------- begin MacOS 26 Tahoe (release=25) compile ------------
--tksurfer.c: append hemi, selectedvtx to edit.dat on SEND PNT for xhemi corr
--tksurfer.tcl: do sampclustctrls after "RD" readrawdata remind set sample point
--lib/help/tksurfer/label_corr: update
--[prev 3 a bit overkill :-} ]
--tksurfer.tcl: MAKE FIRST VOL PAINTABLE reports buff mismatch (won't get here)
--tksurfer.tcl: READ RAWDATA err on rawdata_tdim=1 (HEAD read sets rawdata_tdim)
--tksurfer.c: rawdatasubbrik_to_paintable reports mismatched dims vs. just err
--[prev blocks err: read 3D BRIK, calc covar, re-read 4D BRIK, make PAINTABLE
--tksurfer.c: read_rawdata sets rawdataloaded=0 if rawdata_tdim from HEAD is 1
--tksurfer.tcl: fix forgot logcmd for rawdatasubbrik_to_paintable
   [tmprelease 260525]
--tksurfer.tcl: add $isession to top of READ RAWDATA BRIK and REGISTRATION popup
--lib/help/tksurfer/val3d_raw: update
--tksurfer.tcl: calc covar catches non-zero sample points with normsearch OFF
--tksurfer.tcl: rawdata: "MAKE FIRST VOL PAINTABLE" rawdatasubbrik_to_paintable
--tksurfer.tcl: paint_real_or_complex OK if rawdataframerealloaded=1
--tksurfer.c: add/exp rawdataframerealloaded set by rawdatasubbrik_to_paintable
--tksurfer.tcl: add "SHOW UNIQSAMP VERTICES" to "SELECT VERTEX BY NUMBER" popup
--tksurfer.c: extra-safe NULL ptr check in rawdatasubbrik_to_paintable
   [tmprelease 260522]
--tksurfer.c: fix left-out returns in show_timecourse error checks!!
   [tmprelease 260521]
--lib/help/tksurfer/{label_corr,redraw}: update
--ksurfer.tcl: add "SHOW VERTEX TIMECOURSE" button to select-by-vtx-num popup
--tksurfer.c: functify show_timecourse and export to tcl
--tksurfer.tcl: R-click "REDRAW" button: add "Select Vertex By Number Popup"
--tksurfer.tcl: R-click "X" buttonbar: add "Read RawData Covariance"
--tksurfer.c: add/export read_rawdata_covar (a bit overkill)
--tksurfer.tcl: green selbgcol for hacked-in popup comboboxes (mkannot,rawdata)
--tksurfer.c: rawdatasubbrik_to_paintable now accepts short read by read_rawdata
--tksurfer.tcl: R-clk "X" buttonbar: add "Display Correlation for CurrVertex"
--tksurfer.tcl: R-clk "X" buttonbar: add "{Calc,Write} RawData Covariance"
--tksurfer.c: add/export copy_rowcovar_val() (find nearest uniqvtx to selected)
--tksurfer.c: add/export calc_rawdata_covar(), write_rawdata_covar()
--tksurfer.c: new tmp covar mat globals: covarmat{,_dim,_vnum,loaded}
--tksurfer.c: sampvtxcnt, uniqvtxcnt made global for tcl report
--tksurfer.tcl: R-clk menu "label:" line "X" refreshes corr over label/annot
--tksurfer.tcl: NormSamp popup: enable/disable parms: normdfracflag, bokflag
--tksurfer.tcl: UQ popup reports sampvtxcnt, uniqvtxcnt, vtxs per voxel
--tksurfer.c: sampvtxcnt, uniqvtxcnt made global for tcl report

##########################################################################
UPDATE: 02 May 2026
##########################################################################

   [newrelease 260502]
--lib/help/tksurfer/{save,goto}_pnt: update
--tksurfer.c: sensibly rename: *vindex -> *selectedptr (in 2 functs below)
--tksurfer.c: same fix as below for (script-only) select_talairach_point
   [tmprelease 260429]
--tksurfer.c: funct below passed &selected(def=-1) so deref rngchk brks 1stcall
--tksurfer.c: rm bad select_orig_vertex_coords err chk *vindex - broke 1st GOTO
--tksurfer.tcl: bind toggle nobicurvfadeoverfthresh mid-clk F3 panel "cv" radio
   [tmprelease 260426]
--tksurfer.tcl: cut_{line,vertices},uncut_connected_vertices: warn no selected
--lib/help/tksurfer/curv_tick: update
--tksurfer.tcl: bind toggle nobicurvfadeoverfthresh mid-clk "[ ] curv" tickbox
--tksurfer.c: add/exp nobicurvfadeoverfthresh:no diff fade to sulc/gyr > fthresh
   [tmprelease 260412]
--tksurfer.tcl: disp-annot,chng-annotbordflag reselect_selected_list:select->top
--tksurfer.c: finally fix undo logic! select_vertex w/select=-1 restarts baklist
--tksurfer.c: back out: draw_curs 3x for all b/c weird offset select problem?
--tksurfer.c: reselect_selected_list: draw last-in-list curs 2x extra fix fail?
--lib/help/tksurfe/clks: update, undo
--tksurfer.c: glxwin 'cmd-z' restores prev selected list & redisplays
--tksurfer.c; add restore_selected_list()
--tksurfer.c: clear_vertex_marks_list saves prev (if not already clr:2Rclk help)
--tksurfer.c: glxwin 'd' key does reselect_selected_list to see over annot
--tksurfer.c: add/export reselect_selected_list()
   [tmprelease 260108]
--csurf: warn {SUBJECTS,FUNCTIONALS}_DIR autoset to inside csurf (by FS Env)
--update-csurf: non-verbose untar if "ggo" to not clog csurf.log
--csurf: updatecsurfcmd: find moved-aside name before run update-csurf
--csurf: check csurf install/update dir writable
--csurf: add un-quarantine commands to final updatecsurfcmd popup
    [tmprelease 260104]
--update-csurf: echo pwd/install dir!
--update-csurf: Mac warns run xattr (new tar), don't autodo b/c req's passwd
--csurf: Preferences->Update Csurf:setupupdatecsurf,updatecsurfcmd: update-csurf
--update-csurf: add "ggo" for don't-ask install
    [tmprelease 260101]
--8 file/label lightweight 'annots' (8M) added to fsaverage/fsaverage-ADDITIONS
 {rh,lh}-CsurfMaps1_MNI152.label
 {rh,lh}-CsurfMaps1_MNI305.label
 CsurfMaps1_newcurv-{rh,lh}.w
 CsurfMaps1_old3byte-{rh,lh}.w
--tksurfer.c: write_label_hdr() includes Talairach 152 vs. 305, normd{frac}samp
--lib/help/tksurfer/val_{lab,write}: update
--tksurfer.tcl: mid-click "val;" makes allverticesflag,val2newcurfflag popup
--tksurfer.tcl: left-click "label:" auto-pops up label_label help
--lib/help/tksurfer/swapstatval: update
--tksurfer.tcl: add copy_idnum_val to S/V (swap stat val) button bar
--tksurfer.c: add/export copy_idnum_val (for writing annot-like wfile/label)
--lib/help/tksurfer/comp_grad: doc hidden compute_laplacian <0,1,2> funct
--tksurfer.c: scale_brain() updates tcl-exported glxzoomfact (not yet used)
--tksurfer.c: trunc pval dots w/fthresh (not fully general for all mod flags)
--tksurfer.tcl: rm 3 Calc Laplacian (includelaplacian=0),leave procs,tksurfer.c
--tksurfer.tcl add 3 Calc Laplacian buttons, comp_disp_laplace proc
--tksurfer.c: add/export compute_laplacian (curv,val,phase) -> valbak
--wrappers.tcl: allow "whitespace" (use proc null), added into GR gradient menu
--tksurfer.tcl: findgradrevctrls help: non-existent findgradrev -> comp_grad
    [tmprelease 251126]
--lib/help/tksurfer/{gradfsarrows,comp_grad}: updates
--tksurfer.tcl: add flipRHpolararrowsflag to FIELDSIGN and GRADIENT ARR
--tksurfer.tcl: do_gradrev: find_grad..,write pval wfile, borddots/val display
--tksurfer.c: add/export pvalborddotflag/dthresh to view .pval above thr as dots
--tksurfer.c: find_gradient_reversals: get same ang from 2D/3D grads dot prod
--lib/help/tksurfer/gradfsarrows: update stale hotkeys, regularize
--tksurfer.tcl: don't trunc lg early-area curv gradients (curv avg flatter/OK)
--tksurfer.c: find_gradient_reversals: replace w/new neighbors-only version
--tksurfer.c: add/export find_gradient_reversals (similar to find_retin_borders)
--tksurfer.tcl: findgradrevctrls popup to run find_gradient_reversals
--tksurfer.tcl: calc gradient reversals make-popup-button to GR button R-click
--lib/help/csurf/setupfield: respect reordered parms
--csurf: Setup Calculate Fieldsign, Borders: dividers, better var description
--lib/help/tksurfer/comp_grad: fix avggradvecbak{3d}flag->reggradvecbak{3d}flag

