################################################################### UPDATE: 12 Nov 2024 ################################################################### Summary: (0) fix label header bug introduced in Linux interim releases 240619,240707 (1) tksurfer can write Talairach coords (MNI 305 or 152) to label (10 functs) (2) tkmedit can use MNI 152 instead of MNI 305 (3) read_label_to_nearest_annot_using_col: import label w/diff vtx numbering (4) fill_annot_holes_neigh: fill holes (e.g., in imported label) (5) option to select vertices inside surface (for complexly folded) ------------------------------------------- fix write label header bug on two Linux interim releases ------------------------------------------- I fixed a Linux-specific bug in writing any ASCII *.label header that was just introduced ONLY in the previous two interim releases (240619, 240707). N.B.: no Mac release had this bug. The two-line header, which has a first info/comment line and a second line containing the number of vertices was being omitted. Thus, the label file would look like: 1263 49.014 -57.597 17.263 0.000000 1692 43.572 -53.039 20.957 0.000000 2350 47.215 -54.888 17.173 0.000000 instead of the correct: #!ascii , from subject fsaverage ... 288 1263 49.014 -57.597 17.263 0.000000 1692 43.572 -53.039 20.957 0.000000 2350 47.215 -54.888 17.173 0.000000 ... The resulting label, though containing all the correct data lines, would be unreadable by csurf without hand-editing. The bug was introduced when I added some error checking code that itself contained an error :-{ ------------------------------------------- tksurfer .orig/Talairach/currcoords/normsearch to label ------------------------------------------- The machinery for dumping vertex x,y,z coordinates to labels was overhauled and regularized. Four different kinds of coordinates can be written to a label: 1) .orig coords (gray/white boundary, default) 2) .orig -> MNI 305 (default MGH freesurfer Talairach) 3) .orig -> MNI 152 4) current surface coords (e.g., for flat data analysis) To control these options, there is a small button bar at the far upper-left replacing the "c2lab" (current to label) tickbox. Ticking the "ta" button results in Talairach to label, the "cu" button selected current surface to label. The buttons act like radio buttons (ticking one unticks the other), but they also both be unticked (the default state), which results in .orig coords to label. When you tick "ta", you get a popup to choose MNI 305 vs. MNI 152. A R-click on a ticked "ta" reports the current Talairach choice. In addition, movement along the local vertex normal can optionally be added so that final x,y,z point is in the gray matter (or underneath that border if desired), rather than at the gray/white border. To control this, left-click the bold "label" text on the "label:" line to get a popup. The first tickbox, $normdsampsearchflag, turns normal movement on (N.B.: the default!). The second tickbox, $normdfracflag, determines whether the movement amount is in millimeters or in fraction (0-1) of the local cortical thickness at that vertex. The selected point is halfway between $normdsamp and $normdmax (if in mm), or halfway between $normdfracsamp and $normdfracmax (if in fraction of cortical thickness). These parameters were originally introduced for sampling fMRI data to the surface vertices using the PAINT button. They are also used for writing out timecourses for multiple cortical depths. The tcl functions affected are: write_val_visible_vertices (was write_labeled_vertices, old OK) write_val_annoted_vertices write_val_annotedcol_vertices write_val_idnum_vertices write_val_unmasked_vertices write_annotedcol_autoname write_selected_list_to_label write_annotcols_timecourses_stats write_annotcol_timecourses_stats write_label_timecourses_stats The 305 -> 152 transformation matrix is inverted, so that an MNI 152 Talairach x,y,z can get back to 305, and then back to access native freesurfer .orig coordinates. The 305 -> 152 transformation matrix used is: 0.9975 -0.0073 0.0176 -0.0429 0.0146 1.0009 -0.0024 1.5496 -0.0130 -0.0093 0.9971 1.1840 0.0000 0.0000 0.0000 1.0000 ------------------------------------------- tkmedit can use MNI 152 coords ------------------------------------------- By default, tkmedit uses and reports MNI 305 coordinates (calculated during default recon-all cortical surface reconstruction). To change to using MNI 152 coordinates, tick the "152" tickbox (at the lower right of the "SAGITTAL" button and slider). N.B.: using MNI 152 vs. MNI 305 coordinates does not affect the operation of SEND'ing and GOTO'ing points between tkmedit and tksurfer, since that process always uses native .orig coordinates (possibly modified by normal movement along the local vertex normal). ------------------------------------------- Import label with different vtx numbering ------------------------------------------- Import a label file (for the same subject), but which has a different vertex numbering scheme (e.g., a surface made from a previous edit). This works like read_label_to_annot_using_col in that the requested color is defined in the r,g,b fields to the right of "MESH"), However, instead of reading the label file vertex indices (first entry on each label line) to determine which surface vertices to color, each label file line will be used to color the current surface vertex that has its .orig x,y,z coordinates closest to the x,y,z coordinates in that label file line. N.B.: the label file coordinates are are assumed to be from the .orig surface, which is the default for label-writing (i.e., not from the new Talairach coordinate option above, for from inflated surface coordinates, etc). This makes it possible to display a label file written out from an earlier version of a surface, which will have a different vertex numbering scheme, and which would otherwise be incompatible with the newer surface. N.B.: this will give non-sensical results if the label file comes from a different subject or if the label file contains x.y,z vertex coordinates that are not from the .orig surface. N.B.: to save new label: (1) re-cut current labeled (ctrl-L-clk "C" on "label:" line or tcl funct: labeled_cut_clearvals 0) (2) change name in "label:" line entry to avoid overwrite! (3) save label with \"W\" on \"label:\" line" This works well when edits are localized and no global refinements have been applied (e.g., slightly different target target image value criterion). If not, there will be aliasing between the older label x,y,z vertex positions and the newer surface x,y,z vertex positions, resulting in many small linear-shaped holes in the transferred label where a new surface vertex just missed being assigned an annotation from a label vertex. To fix this, see the next function below. However, even without filling the holes, the converted label can be used as a template to re-cut a new native label. This function is quick on a standard sized freesurfer brain (130K vertices), but it will be slow with a very large surface (e.g., over 30 min for a 5M vertex cerebellum). In that case, it can be sped up by cutting away irrelevant parts of the surface (if these are known), for example, using the "PLANE" button. ------------------------------------------- New funct to fill holes in imported label/annotations ------------------------------------------- A more general, controllable label hole-filler (than the basic one-vertex-hole-fixing "annotholes"). This function, fill_annot_holes_neigh is accessed by typing "annotholes-neigh" into the unlabeled "steps" entry immediately to the right of the "SMOOTH" button plus or click "SMOOTH", which generates a popup window. From the popup window, you can control the size of the smoothing neighborhood, "neighord" (1-5, where 1 means just consider nearest vertex neighbors, 2 means includ neighbors of neighbors, and so on), and the criterion for filling a hole, "annotedfrac" (% of surrounding non-hole vertices required to cause label/annotation hole to be filled with the surrounding color). Larger neighborhoods (3-5) are successively slower with a large surface (e.g., 5M vertex cerebellum), but can be sped up by cutting away irrelevant parts of the surface, for example, by using the "PLANE" button. ------------------------------------------- Option to select vertices inside surface ------------------------------------------- Normally, the inside of a surface is invisible, not lighted, and you cannot select vertices from the inside. However, when editing and cutting a complexly folded surface (e.g., the anterior lobe vermis of the cerbellum), it is sometimes helpful to be able to select points from the inside of the surface. An alternate middle-click on the "clo" tickbox (middle bottom) toggles $selectinsideflag. When this flag is ON, vertices can be selected from the inside/back surface. N.B.: this will disable the normal selecting of vertices on the outside of the surface! (middle=click again to go back to normal). To make the surface and the selected vertices visible, two additional variables are adjusted: set lighttwosidedflag 1 ;# show inside surface set light1 1.0 ;# also light inside/back surface Selections on the inside surface are also marked when viewing the surface from the outside. A shift-R-click on the "REDRAW" button makes a popup with full control over the 4 lights (brightness, x/y/z position, $insidesurffact (brightness inside relative to outside), and $lighttwosidedflag. ----------------------------------------------- Bug fixes, small changes ---------------------------------------------- off-edge access causing occas. startup crash fixed in set_{real,complex}_col R-click help buttonbars for remaining overloaded buttons tksurfer/tkmedit better popups for using 2-D color space for truncation isocontour controls popup catch tkmedit crash in FILL struct 3D ROI if (irrelevant) im2i not loaded ########################################################################## UPDATE: 12 Nov 2024 ########################################################################## --lib/help/tksurfer/{smooth_steps,label_read,selectdmax}: update --tksurfer.c: read_label_to_nearest_annot_using_col: ignore ripflag vtxs --tksurfer.c: fill_annot_holes_neigh: ignore ripflag vtxs to speed high neiorder --tksurfer.c: fill_annot_holes_neigh: add neiorder=5 for smaller surfaces --tksurfer.c: fix fill_annot_holes bugs (fill val sometimes 0, then paren bug) --tksurfer.tcl: rm "annotholes-more" b/c fill_annot_holes_neigh is more general --tksurfer.c: rm fill_annot_holes_more (redundant w/fill_annot_holes_neigh) --tksurfer.tcl: "annotholes-neigh" uses funct: C/tcl fill_annot_holes_neigh --tksurfer.tcl: overload smooth steps: add "{annot,label}holes-neigh popup --tksurfer.c: add fill_annot_holes_neigh(neiorder,annotedfrac) general funct --tksurfer.tcl: smoothsteps: "{annot,label}holes-more" -> fill_annot_holes_more --tksurfer.c: add fill_annot_holes_more(): (filled nei minus 3 (vs. minus 2) --tksurfer.tcl: add no-hotkey "D" button: read_label_to_nearest_annot_using_col --tksurfer.c: read_label_to_nearest_annot_using_col(): for updated surfaces [tmprelease 241028] --tksurfer.c: fix write_label_hdr check-fp-writable-code on Linux (& O_ACCMODE) --tksurfer.tcl: disp annot prints totarea all regions (except Unknown) for csurf --tksurfer.c: tot area annot regions (except Unknown) to genstrret_1k/csurflog --tksurfer.tcl: add $lighttwosidedflag to lights popup from R-click help buttbar --tksurfer.tcl: fix R-click report popups for current ta/cu button state [tmprelease 240709] --csurf: hack^2: slow mac10.15 csurf log hangs tkwait/GLwin if appnaphack so blk [tmprelease 240707] --mk0: comment out version-name tksurfer (leave update-tksurfer for later) --tksurfer.c: set_{real,complex}_color: blk annotmask,adjphase off edge if k=-1 --mk0: add update-tksurfer sh script to dist --update-tksurfer: toggles tksurfer symlink between 10.6/10.15 --mk0: version-name 10.6 tksurfer compile, incl 10.15 compile, tksurfer->symlink [tmprelease 240619] --tksurfer.tcl: fix buttonbar REDRAW (forgot to make def cmd bind for event gen) --tksurfer.tcl: add $insidesurffact to brightness/position lights ctrls --lib/help/tksurfer/{redraw,lights,blufact,selectdmax}: update --tksurfer.c: draw prev selected inside surface vertices w/points --tksurfer.tcl: lights bright/pos ctrls: shift-R-clk-REDRAW, REDRAW buttonbar [tmprelease 240611] --tkmedit.c: do 305->152 xform if $xform_mni_305to152_flag (6 fwd's, 1 inv) --lib/help/tkmedit/xfm305to152,mk0: new helpfile --tkmedit.tcl: "152" tickbox for $xform_mni_305to152_flag under SAGITTAL --tkmedit.c: load_invert_305to152_xform() at startup, $xform_mni_305to152_flag [tmprelease 240609] --tksurfer.c: write_annotcol{s}_timecourse.. warns usecurrcoords cancels norm mv --tksurfer.c:xform_mni_305to152_flag picks find_orig_vertex_coordinates edit.dat --tksurfer.c: find_orig_vertex_coordinates always reports both MNI 305 and 152 --lib/help/tksurfer/: update multiple help (6 renames, 305 vs 152, 15 files) --tksurfer.c: export selected (curr vtx, starts -1) --tksurfer.c: rm xform_mni_305to152(), subst. mni_transform_point(): 5fwd/2inv --tksurfer.c: add load_305to152_xform() to startup seq: always load, invert --tksurfer.c: new global Transform's: {inverse_}mni_305to152_transform --tksurfer.tcl: R-click-"ta" reports MNI 305 vs. MNI 152 --tksurfer.tcl: select Talaiarch "ta" sets up choose MNI 305 vs. MNI 152 --tksurfer.c: test/add xform_mni_305to152(), add/export $xform_mni_305to152_flag --tksurfer.tcl: C:write_selected_list_to_label->write_val_selected_list_to_label --tksurfer.tcl: copy-C:write_annotedcol_autoname-> write_val_annotedcol_autoname --tksurfer.c: rename:write_annotedcol_autoname -> write_val_annotedcol_autoname --tksurfer.c:write_selected_list_to_label->write_val_selected_list_to_label(syn) --tksurfer.tcl: rename: extract_unmasked_flag -> unmasked_to_label_flag --tksurfer.tcl: rename: extract_overlays_flag -> unmasked_to_labels_flag --tksurfer.c: fix write_selected_list_to_label header update bug if bigcursorflg --tksurfer.c: fix all synonyms to use an extra Tcl_CreateCommand --tksurfer.c: rename write_labeled_vertices->write_val_visible_vertices (bakcmp) --searchlight{area,diff}.tcl: write_labeled_vertices->write_val_visible_vertices --tksurfer.tcl: copy-C: write_labeled_vertices->write_val_visible_vertices --tksurfer.c: write_selected_list_to_label uses new functs, but dup'd for neigh --tksurfer.c: write_annotedcol_autoname uses 2 new funct --tksurfer.c: write_{annotcols,annotcol}_timecourses_stats DON'T (do separately) --tksurfer.c: write_val_{annoted,annotedcol,unmasked}_vertices use 2 new functs --tksurfer.tcl: usecurrcoordsflag/usetalcoordsflag ticks to "|ta|cu|" tixSelect --tksurfer.c: extract new funct: write_label_vtxline,write_labeled_vertices uses --tksurfer.c: extract new funct: write_label_hdr, write_labeled_vertices uses --lib/help/tksurfer/nsamp_{search,dfrac,max,min,fracmax,fracmin}: update --tksurfer.tcl: fix R-click help on "label:" label popup --lib/help/tksurfer/label_write: update --tksurfer.c: find_orig_vertex_coordinates, write_labeled_vertices use it --tksurfer.c: extract new function: move_along_normal(k,vb,x,y,z,&x2,&y2,&z2) --tksurfer.tcl: overload "c2lab" button with usetalcoordsflag --tksurfer.c: separator: '=' to '_' for write_val_{annotedcols,idnum}_vertices --tksurfer.tcl: event generate buttonbars for R-clk help for REDRAW, RESTORE --lib/help/tksurfer/selectdmax: update --tksurfer.tcl: overload "clo" button with $selectinsideflag --tksurfer.c: if $selectinsideflag, draw cursor underneath surface (instead) --tksurfer.c: add/export $selectinsideflag (N.B.: cancels outside select!) --tksurfer.tcl: display label (labelD_display) opens label control popup (duh!) --lib/help/tksurfer/isocont: update --tksurfer.tcl: add isocontour controls pop-up for R-click "isocont" --lib/help/tksurfer/{label_read,label_toggle}: update --tksurfer.tcl: padlabelvtxsflag in label tickbox popup, hotkey, warn label read --tksurfer.c: add padlabelvtxsflag to read_label_to_annot_using_col (also neigh) --tkmedit.tcl: "im2:" label popup: better description (test vs. apply) --lib/help/tkmedit/im2label: clarify transpar overlay test vs apply to editable --tkmedit.c: COMPARE/TRUNC: event generate -> call proc, fix TRUNC cmd-. bind --tkmedit.tcl: COMPARE: event generate -> call proc, cleanup TRUNC/PF/PFGAU [tmprelease 240519] --tksurfer.tcl: fix def bind for Return in label: entry (invoke fail w/no-cmd) --tksurfer.tcl: fix def bind for Return in val: entry (invoke fail w/no-cmd) --tksurfer.c/tcl: check " invoke" of "buttons $f SOMEBUTTON { }" --tkmedit.c: WMTRUNC,CORONAL invoke -> event generate (b/c empty cmd/only bind) --tkmedit.tcl: change invoke to event generate: SMOOTHGAUSS,TRUNC,CORONAL,TEST --tkmedit.c: COMPARE Xkeys: add alt/cmd-C for COMPARE --tkmedit.c: COMPARE Xkeys: invoke->event generate (b/c empty cmd/only bind) --tkmedit.tcl: COMPARE hotkeys: add alt/cmd-C for COMPARE --tkmedit.tcl: COMPARE hotkeys: invoke->event generate (b/c empty cmd/only bind) --tkmedit.c,tcl: search " invoke" of "buttons $f SOMEBUTTON { }" -> event gen --tkmedit.tcl: mv up imim2 ctrls un-overlap TRUNC buttbar (not if from OP butt) --lib/help/tkmedit/wmtrunc: add imim2op help (overlap w/imim2op OP help) --tkmedit.tcl: add imim2op colspace ellipse to TRUNC buttbar, ctrls to OP --tkmedit.tcl: rm do_imim2op arg --tkmedit.tcl: add buttbar for SMOOTH{STRUCT/STATS} button, incl calc grad x/y/z --tkmedit.tcl: add buttonbar for PF,PFGAU butts (event gen hack for compact) [tmprelease 240503] --tkmedit.c: catch crash in FILL struct 3D ROI if (irrelevant) im2(i) not loaded --tkmedit.tcl: add buttonbar for FILL button (event gen hack for compactness --tkmedit.tcl: COMPARE/TRUNC: 'after 1' fix butt state race after bind->proc --tksurfer.tcl: put neighbor order info on paintball popup into [tmprelease 240501] --tkmedit.tcl: add toggle linearflag button to COMPARE buttonbar --tkmedit.tcl: add buttonbar for COMPARE button, change bind's to proc's --tkmedit.tcl: buttonbar for F3 TEST butt (event gen hack keep binds like APPLY) --tkmedit.tcl: buttonbar for CORONAL (event gen hack to keep binds like SAG/HOR) --tkmedit.tcl: convert TRUNC butt bind's to procs (rm event generate hacks) --tkmedit.tcl: section dividers for readability ########################################################################## UPDATE: 26 Apr 2024 ########################################################################## --tksurfer.tcl: new buttonbar for areal-line "D" button --tksurfer.tcl: new buttonbar for "SMOOTH" button --tksurfer.tcl: conv val-line "W" butt bind's to procs (rm event generate hacks) --tksurfer.tcl: new buttonbar for val line "CLR" button (just 2: val, all) --tksurfer.tcl: new buttonbar for val-line "CS" button (just 2: cluster, FDR) --tksurfer.tcl: conv val-line "S/V" butt bind's to procs (rm event gen hacks) --tksurfer.tcl: new buttonbar for val-line "R" button (bind's -> proc's) --tksurfer.tcl: new button bar for label-line "X" butt (bind's -> proc's) --tksurfer.tcl: new button bar for label-line "S" butt (bind's -> proc's) --tksurfer.tcl: new button bar for label-line "T" butt (bind's -> proc's) --tksurfer.tcl: conv fs-line GR butt bind's to procs (rm event generate hacks) --tksurfer.tcl: conv label-line W butt bind's to procs (rm event generate hack) --tksurfer.tcl: conv label-line R butt bind's to procs (rm event generate hack) --tksurfer.tcl: conv label-line CLR butt bind's to procs (rm eventgenerate hack) --tksurfer.tcl: conv label-line C butt bind's to procs (rm event generate hack) --tksurfer.tcl: conv label-line D butt bind's to procs (rm event generate hack) --tksurfer.tcl: fix stale funct name: read_poi_annot -> read_poi_to_annot [tmprelease 240418] --lib/help/tksurfer/label_write: update write_sorted_by_pathdist_label --tksurfer.tcl: R-clk label W for C pathsort: write_sorted_by_pathdist_label ...