Skip to content

CI + docs overhaul: matlab.unittest harness, code maps, per-method help pages, help-example tests#74

Merged
torwager merged 16 commits into
masterfrom
claude_code_dev
May 7, 2026
Merged

CI + docs overhaul: matlab.unittest harness, code maps, per-method help pages, help-example tests#74
torwager merged 16 commits into
masterfrom
claude_code_dev

Conversation

@torwager
Copy link
Copy Markdown
Contributor

@torwager torwager commented May 7, 2026

Summary

This branch consolidates ~6 months of CI and documentation work on claude_code_dev. It is large but the changes break cleanly into independent layers:

  • CI / unit tests. A matlab.unittest-based harness (canlab_run_all_tests.m) plus GitHub Actions workflows: a fast per-push tier (.github/workflows/test.yml) and a slow nightly walkthroughs tier (.github/workflows/tests-walkthroughs.yml). SPM is pinned to tag 25.01.02. The new canlab_test_help_examples.m exercises every doc Quick example on every push so the docs cannot silently bit-rot. ~28 test files total covering atlas, fmri_data, image_vector, region, statistic_image, and end-to-end walkthroughs.
  • Source-code cleanup. ~136 docstrings reformatted to Sphinx / readthedocs style (Phase 1 + 2). flip() fixed to error on multi-image input rather than silently producing nonsense. Old vendored toolboxes that were superseded or unused removed.
  • Object-methods documentation tree under docs/. Object_methods.md is the entry point — a class-by-class index (fmri_data, image_vector, statistic_image, atlas, region, fmridisplay, ...) linking out to per-method pages with runnable ## Quick example blocks, sample PNGs (docs/class_method_pngs/), and per-function code maps. Companion pages cover atlases / regions / patterns, sample datasets, recasting between object types, and the toolbox folder map. README now points to this tree as documentation source Memory Leak in roc_plot #1.
  • Old Sphinx HTML tree removed. docs_sphinx_old/ deleted (~190K lines) — the new markdown tree replaces it. Most of the line-count delta in this PR is that deletion.

Why one PR

The pieces are interleaved (the help-example unit test runs the docs Quick examples; the docs link to PNGs generated by runners that ship with the docs). Splitting into smaller PRs would require a synthetic ordering that does not match how the work was actually built.

Test plan

  • CI fast tier (tests workflow) passes on the merge target — 28+ unit tests including the new canlab_test_help_examples (30 cases)
  • CI walkthroughs tier (tests-walkthroughs workflow) passes on the nightly run after merge
  • Spot-check rendered docs by browsing docs/Object_methods.md on the master branch — relative links and PNGs should resolve
  • Confirm README link to docs/Object_methods.md works on the GitHub web UI

🤖 Generated with Claude Code

torwager and others added 16 commits May 1, 2026 16:22
Sets up automated test infrastructure so future refactors can be
validated:

- Unit_tests/ reorganized into subfolders by class/area; legacy ad-hoc
  scripts moved to Unit_tests/old_to_integrate/ pending rewrite.
- Unit_tests/run_all_tests.m: entry point used both interactively and
  from CI. Adds CanlabCore to path, discovers tests recursively, supports
  tag filtering and JUnit XML output.
- Initial coverage (17 sub-tests, all green locally on R2024b):
  fmri_data construction, load_image_set, replace_empty/remove_empty
  round-trip and idempotence, apply_mask, ttest -> threshold ->
  statistic_image.sig, region from a thresholded map, atlas constructor,
  and an end-to-end pipeline smoke test.
- Unit_tests/helpers/get_sample_fmri_data.m: shared fixture loader so
  the sample-load path is centralized across tests.
- Unit_tests/README.md: conventions for writing tests.
- .github/workflows/test.yml: runs the suite on every push/PR (Ubuntu,
  R2024b) with sibling checkouts of canlab/Neuroimaging_Pattern_Masks
  and spm/spm. Free MATLAB CI for public repos via matlab-actions.
- CLAUDE.md: architecture and conventions guide for AI coding assistants.
- README.md: tests status badge.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The github.com/spm/spm main branch is now SPM26-dev, which
@fmri_data/fmri_data.m:632 does not recognize and rejects with
"Unknown version of SPM!". Pinning to the latest stable SPM25 tag
matches the version users actually install and keeps CI deterministic
across SPM releases.

Follow-up: the version check in fmri_data.m should be relaxed to
accept any SPM>=8 rather than enumerating versions, so future bumps
don't silently break user installs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
SPM ships FieldTrip compatibility shims under external/fieldtrip/compat/
that override MATLAB builtins (flip, isfile, isfolder, ...). When we did
addpath(genpath('spm')) those shims went on the path and shadowed the
real flip; matlab.unittest's discovery code then called flip on a
meta.class object, errored, and silently excluded
test_atlas_constructor.m.

SPM's documented setup is addpath(spm_root) without genpath — SPM
internally adds the subdirs it needs at function-call time, so the
compat shims stay off the path until something actually requests
fieldtrip. Switching CI to that pattern.

Local was unaffected because the local machine has SPM12 on path, which
doesn't ship those shims; the issue surfaced only because the SPM25
bundled FieldTrip is newer and includes more compat layers.

Also revert the diagnostic prints from run_all_tests now that the cause
is identified.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Test infrastructure
- Rename Unit_tests entry-point files to canlab_test_*.m and canlab_run_all_tests.m / canlab_get_sample_fmri_data.m so they don't shadow other toolboxes' identically-named functions on the path. Inner local sub-tests keep the test_* convention.
- Switch the runner to glob canlab_test_*.m and use TestSuite.fromFile, since TestSuite.fromFolder only auto-discovers files starting/ending with 'test'.
- Initialize the empty suite as matlab.unittest.Test.empty (was TestSuite.empty) so concat with concrete Test arrays works.

CI workflow
- Install Statistics_and_Machine_Learning_Toolbox and Signal_Processing_Toolbox in setup-matlab; previously these were silently provided by SPM's bundled FieldTrip compat shims, which we no longer reach since switching to addpath('spm') (no genpath) to dodge the flip-shim shadowing.

SPM version-check relaxation (26 sites across 21 files)
- Replace the brittle 'switch spm(\\'Ver\\') / case {SPM5,SPM8,SPM12,SPM25} / otherwise error' pattern with 'case {SPM2,SPM99} legacy / otherwise modern' so any future SPM version (SPM26+) automatically uses the modern code path.
- Files: @fmri_data/fmri_data, @atlas/atlas, @fmri_timeseries/fmri_timeseries, @image_vector/read_from_file, Data_extraction/{extract_image_data,extract_from_rois,extract_raw_data,timeseries_extract_slice}, Index_image_manip_tools/{iimg_read_img,iimg_reslice,iimg_reconstruct_vols}, Image_computation_tools/{image_eval_function,image_eval_function_multisubj,mean_image,scn_num_volumes,scn_write_plane,tor_global}, Visualization_functions/{montage_clusters,montage_clusters_medial}, Statistics_tools/{classify_naive_bayes,classify_naive_bayes_2010}, Filename_tools/{expand_4d_filenames,scan_get_files}, diagnostics/{scnlab_norm_check,scnlab_pca_denoise_session}, Cluster_contig_region_tools/clusters2mask.

Cruft removal (35 files)
- _old / _backup / tmp .m files: resample_space_old, predictive_model_old, region2imagevec_old, region2imagevec2tmp, cluster_table_old, canlab_glm_subject_levels_old, canlab_glm_subject_levels_run1subject_old, weighted_reg_old2, weighted_reg_oldglmfit_old, HRF_Est_Toolbox{2,4}/Old_stuff/More_recent_old_stuff/Example_old, igls_old, igls_old2, getVertexColors_old_backup{,2}, construct_model_tmpwork, tmp_onsets2dx. Each verified to have an active sibling.
- .asv autosave files: 18 git-tracked under External/spider, External/umap, Image_computation_tools, plus 5 untracked under @fmri_data, @image_vector, Cifti_plotting.

Documentation
- CLAUDE.md: add 'When writing new functions' section with the canlab_<name> namespace rule, the inputParser-with-template requirement, and the runnable-example requirement.
- documentation_template.m: updated by user.
- Unit_tests/README.md: rewritten for the new canlab_test_* naming.

Toolbox / docs deletions
- HRF_Est_Toolbox2/ removed in entirety.
- docs_sphinx_old/ removed in entirety.
- docs/.gitignore and docs/.idea/ removed.

Local CanlabCore unit-test suite passes after all changes (17/17).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… input

fmri_data_methods.md
- New cross-cutting functional index of @fmri_data + @image_vector methods,
  grouped by area (basic math / display / resampling / statistics / tables /
  similarity / extraction / QC / misc) with one-liner descriptions and the
  inheritance source.

Test scaffolding
- helpers/canlab_get_sample_thresholded_t.m: shared fixture that loads
  emotionreg, runs ttest, and thresholds at p<0.05 for use across display,
  table, and extraction tests.

New test files (23 new test cases across 9 areas)
- fmri_data/canlab_test_cat_split.m: cat doubling, split via images_per_session,
  get_wh_image subset, mean collapse to single image.
- fmri_data/canlab_test_regress.m: voxelwise regression with intercept-only
  and a random predictor.
- image_vector/canlab_test_display.m: montage, slices, orthviews, surface
  on the thresholded-t fixture (orthviews/surface guard for headless CI).
- image_vector/canlab_test_resample_space.m: compare_space self-check,
  resample_space-to-self preserves image count.
- image_vector/canlab_test_similarity.m: jackknife_similarity smoke test;
  image_similarity_plot_bucknermaps skip-if-maps-absent.
- image_vector/canlab_test_extract_roi.m: extract_roi_averages over the
  canonical brain mask, including the per-region .dat shape invariant.
- image_vector/canlab_test_qc.m: descriptives returns a struct;
  qc_metrics_second_level runs without error.
- image_vector/canlab_test_misc.m: flip preserves class/count and round-trips
  on a single-image object; flip errors on multi-image input;
  enforce_variable_types preserves class.
- statistic_image/canlab_test_table.m: table() runs and returns useful output.

Bug fix: @image_vector/flip.m
- Add a single-image guard. The slice loop assumed a 3-D reconstruction;
  on multi-image objects it silently iterated only the first image's Z
  planes and rebuild_volinfo_from_dat then errored on the wrong-size vector.
  Now errors with id image_vector:flip:multiImage and a message pointing
  at mean(obj) / get_wh_image(obj, k).
- Call replace_empty(dat) at the top so flip works on either compressed
  or padded inputs without forcing the caller to remember.
- Update the help block to document the single-image requirement.

Local: 40 passed, 0 failed, 1 incomplete (image_similarity_plot skipped
when Buckner network maps are not on the path).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Brings 136 help blocks into conformance with the format defined by
CanlabCore/Misc_utilities/documentation_template.m, which is what
read-the-docs renders. Documentation only — no executable code changed.
Existing information is preserved verbatim; missing sections were added,
and undocumented runtime options were surfaced into the help block where
discovered. The local test suite (40 tests) still passes.

Phase 1: class methods (102 files)
- @fmri_data/         18 (bootstrap_structure_coeff_diff also deleted as dead/deprecated)
- @image_vector/      44 (4 dead operator overloads also deleted: plus, minus, power, horzcat;
                          apply_atlas deleted as always-warning deprecated)
- @atlas/             21
- @region/            18
- @statistic_image/    8
- @fmridisplay/        9
- (fmri_data.m class constructor deferred for a dedicated pass)

Phase 2: high-traffic standalones (17 files)
- Data_extraction/load_image_set, Data_extraction/load_atlas
- Visualization_functions/canlab_results_fmridisplay,
  canlab_canonical_brain_surface_cutaways, scn_export_papersetup
- GLM_Batch_tools/canlab_glm_subject_levels, canlab_glm_group_levels,
  canlab_glm_subject_levels_run1subject, canlab_glm_group_levels_run1input,
  canlab_glm_publish_subject_levels, canlab_glm_publish_group_levels,
  canlab_glm_convolve, canlab_glm_getinfo, canlab_prep_bidsdir
- Misc_utilities/framewise_displacement
- Filename_tools/canlab_get_underlay_image, canlab_list_files
- Data_processing_tools/canlab_extract_ventricle_wm_timeseries

Conventions applied
- First line: function_name + one-line description.
- Sphinx sections in order: :Usage: (with :: block), :Inputs:,
  :Optional Inputs:, :Outputs:, :Examples:, :See also:.
- Boldfaced parameter names: **paramname:** with indented descriptions.
- License / author / programmers' notes wrapped in % .. .. blocks.
- No double-backtick code quoting (per project preference).
- Documented standard 'doplot'/'noplot'/'verbose'/'noverbose' flags
  wherever the function actually parses them.

Other artifacts
- poorly_documented_functions.txt: ranked list of 762 .m files whose help
  blocks differ substantially from the template (used to scope this pass
  and remaining work).

Notes for follow-up (surfaced during the pass; no code change made)
- expand_into_atlas_subregions.m and annotate_continuous_neuroimage_maps.m
  are scripts (no `function` declaration); docstrings added, code untouched.
- check_properties.m (statistic_image) marked "under construction" with
  what looks like an undefined-variable bug in the body.
- One content judgment in canlab_glm_subject_levels: 'NPSpos & NPSpos'
  -> 'NPSpos & NPSneg' based on naming convention; revertable.
- Dependabot still reports 4 moderate vulnerabilities on the default
  branch (vendored JS in old docs); separate cleanup.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Lays out a structured documentation set for the toolbox under docs/, in
plain GitHub-flavored markdown that renders both directly on GitHub and
after a copy-paste into the canlab.github.io Jekyll site.

Index pages
- Object_methods.md: top-level entry point, with a class hierarchy
  diagram, a class-by-class table linking out to per-class pages, and
  visible links to https://canlab.github.io/walkthroughs/ and
  https://canlab.github.io/tutorials/.
- recasting_objects.md: idioms for converting between class types
  (region2fmri_data, atlas2region, region(t), convert2mask, etc.) and a
  note on the replace_empty / remove_empty state machine.
- toolbox_folders.md: one-line description for every CanlabCore
  subfolder, separating @Class folders from function libraries.

Per-class methods pages (one per class, in docs/<class>_methods.md)
- fmri_data_methods.md: relocated from CanlabCore/ to docs/ (the version
  with the user's manual category edits remains the canonical source).
- image_vector_methods.md, statistic_image_methods.md, region_methods.md
- atlas_methods.md, fmridisplay_methods.md
- brainpathway_methods.md (covers brainpathway and
  brainpathway_multisubject), fmri_timeseries_methods.md,
  canlab_dataset_methods.md, fmri_glm_design_matrix_methods.md,
  predictive_model_methods.md, fmri_mask_image_methods.md.

Each per-class page follows the existing fmri_data_methods.md template:
~2-paragraph intro, compact properties table, methods grouped by area
(Basic image math / Display / Resampling / Statistics / Multivariate
prediction / Tables / Annotation / Data extraction / Data processing /
QC / Misc utilities), with the From column showing where the method is
defined. Categories with no methods for a given class are dropped.
Class-name collisions (e.g., region defines its own montage / table) and
overrides (e.g., statistic_image overrides threshold / orthviews) are
flagged in the From column.

Documentation only: no .m files were modified.

Findings worth flagging (left as-is per scope)
- @brainpathway/reorder_regions_by_node_cluster.m looks like a duplicate
  of reorder_regions.m (same function declaration; identical first ~30
  lines).
- @fmri_glm_design_matrix/import_onsets.m references an undefined
  DesginmatrixTable; appears broken.
- @predictive_model has many forthcoming-stub methods (crossval is
  literally an empty function; train, test, report, plot, montage,
  select_features, bootstrap, error_analysis, permutation_test,
  confusionchart, rocplot all error when called). Documented under a
  "forthcoming stubs" sub-section. Only validate_object,
  confusion_matrix, plot_predicted_vs_observed are implemented.
- @brainpathway_multisubject/update_region_connectivity is a listener
  stub that comments mark "DOES NOT WORK".
- @statistic_image/check_properties.m is marked "under construction, do
  not use yet" in its own header.

Phase B (atlases_regions_and_patterns.md and sample_datasets.md, both
research-heavy with paper citations) is in progress.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…tations

Two new pages in docs/, completing the help-doc-agent-instructions task list.

atlases_regions_and_patterns.md (386 lines)
- Intro framing: how CanlabCore consumes the canlab/Neuroimaging_Pattern_Masks
  collection (load_atlas, load_image_set, canlab_load_ROI), with pointers to
  the GitHub repo and the curated Brain Patterns site at
  https://sites.google.com/dartmouth.edu/canlab-brainpatterns/home.
- Atlases section: one-paragraph summaries grouped as combined whole-brain
  (canlab2018/2023/2024/opencanlab2024), cortical (Glasser, Desikan-Killiany,
  DKT, Destrieux, Schaefer/Yeo, Shen), subcortical (CIT168, Pauli striatum,
  Brainnetome), thalamus (Morel/Krauth, Iglesias, Tian), hypothalamus
  (Iglesias/Billot), brainstem and cerebellum (SUIT-Diedrichsen, Bianciardi,
  Harvard AAN, Levinson-Bari Limbic, Kragel PAG), 7T (Keuken), functional
  networks (Buckner/Yeo/Choi), pain pathways, and other (Faillenot insula,
  Cartmell NAc, deLaVega Neurosynth, Julich).
- Named regions section: anatomically grouped tables (cortex, forebrain,
  basal ganglia, thalamus / diencephalon, brainstem, midbrain, pons,
  medulla) sourced from canlab_load_ROI.m, with DOI hyperlinks per ROI.
- Multivariate signatures: brief overview pointing to sample_datasets.md
  for the full keyword table; inline citations for NPS, SIIPS, PINES, VPS,
  Romantic Rejection, Kragel emotion, NCS, MPA2, fibromyalgia patterns.
- 84 hyperlinked DOI citations, plus 6 HTML <!-- TODO --> markers where the
  primary source needs verification (Levinson-Bari, kragel2019pag, SPM
  Anatomy hippocampus, Carmack 2004 midbrain, Brooks RVM, inferior olive).

sample_datasets.md (219 lines)
- Intro pointing to the canlab.github.io loading-datasets walkthrough and
  to load_image_set's :Available Keywords: block as the live registry.
- Built-in Sample_datasets/ files: short subsection citing the source paper
  for each (Atlas 2012 REMI, Wager 2008 Neuron emotionreg, Pinel 2007 BMC
  Neurosci localizer, Woo 2015 PLoS Bio BMRK3, Jepma IE2 single-trial,
  Yarkoni 2011 Nat Methods Neurosynth-derived emotion-regulation map).
- load_image_set keyword registry: comprehensive table organized by family
  (group-level images, single-trial timeseries, parcellations / large-scale
  networks, signature patterns and predictive models), each row carrying
  Type and Citation columns.
- Worked examples lifted from the load_image_set docstring.
- ~36 unique citations with DOI hyperlinks, plus 11 explicit <!-- TODO -->
  markers (Atlas 2012 REMI exact paper, Jepma IE2, single-trial dataset
  origins for nsf / bmrk4 / exp / ie / ilcp / scebl / stephan, neurosynth
  topics, stroop, pifonem, vifs).

Citation verification
- Spot-checked 10 representative DOIs (Wager 2008 Neuron, Wager 2013 NEJM,
  Pauli 2016 PNAS, Yeo 2011 J Neurophysiol, Krishnan 2016 eLife, Woo 2014
  Nat Commun, Glasser 2016 Nature, Hansen 2022 Nat Neurosci, Keuken 2014
  NeuroImage, Woo 2017 Nat Commun) — all resolve via doi.org to the correct
  journals. Agents wrote these from training knowledge rather than live
  web verification, so subtle errors in author lists / page numbers may
  exist. Review before external publication is recommended.

No code changes; documentation only.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Spot-audited the 17 TODOs and a sample of agent-generated DOIs from
docs/atlases_regions_and_patterns.md and docs/sample_datasets.md against
doi.org redirects, PubMed, and journal pages. Most well-known papers
checked out (Wager 2008 Neuron, Wager 2013 NEJM, Yeo 2011, Pauli 2016,
Glasser 2016 Nature, Hansen 2022 Nat Neurosci, Krishnan 2016 eLife,
Woo 2014, Keuken 2014, Woo 2017 Nat Commun — all verified). Five
specific corrections needed:

atlases_regions_and_patterns.md
- Levinson-Bari Limbic Brainstem Atlas: corrected DOI from
  10.3389/fnimg.2023.1665947 (which does not resolve to anything
  matching the description) to the actual Frontiers in Neuroimaging
  paper, 10.3389/fnimg.2022.1009399, "A structural connectivity atlas
  of limbic brainstem nuclei" (Levinson, Miller, Iftekhar et al., 2023,
  vol 1, art. 1009399). Expanded author list. TODO removed.
- kragel2019pag atlas citation: replaced the Neuron 2019 colliculus-
  pulvinar-amygdala paper (which is a different Kragel 2019 paper) with
  the actual PAG-focused publication: Kragel, Bianciardi, Hartley et al.
  (2019), J Neurosci 39(31):6180-6189, "Functional involvement of human
  periaqueductal gray and other midbrain nuclei in cognitive control."
  DOI: 10.1523/JNEUROSCI.2043-18.2019. TODO removed.
- SPM Anatomy Toolbox hippocampus mask: filled in Eickhoff et al. 2005
  NeuroImage citation (DOI 10.1016/j.neuroimage.2004.12.034). TODO
  removed.

sample_datasets.md
- Atlas 2012 REMI behavioral data: confirmed the agent's guess
  (Atlas, Whittington, Lindquist, Wielgosz, Sonty & Wager, 2012, J
  Neurosci 32(23):8053-8064) is correct. TODO removed.
- Removed a hallucinated DOI for the Ke et al. 2024 topic-label
  paper. The agent's previously-listed DOI 10.1038/s41593-024-01807-z
  actually resolves to a different paper (Kunz et al. on hippocampal
  ripples), not the topic-label work. The TODO note now explicitly
  flags this as an incorrect DOI to be replaced with the right Ke 2024
  reference.

Remaining TODOs (15 total): 3 in atlases (Carmack 2004 midbrain, Brooks
RVM, inferior olive — all behind paywalls or unfindable on open web)
and 12 in datasets (mostly single-trial dataset citations, since the
canlab_single_trials repo stores citations inside the .mat files
themselves rather than in a public README; also pifonem 2026 which is
likely forthcoming, vifs which is registry-internal). These should be
filled in by someone with access to the .mat files and the relevant
papers.

Doc-only changes; no code touched.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Walkthrough integration tests
- Unit_tests/walkthroughs/: 10 wrapper tests, one per CANlab_help_examples
  walkthrough script (the 12 in publish_canlab_help_set1.m minus
  first_level_design_matrix_exploration and compare_pain_patterns_sens_spec
  per request). Each wrapper:
  * Applies WorkingFolderFixture so the script runs in a fresh temp cwd
    (output NIfTI files don't collide across runs)
  * close all force in setup and teardown
  * assumeNotEmpty(which(script_name)) so the test skips cleanly
    (Incomplete) when CANlab_help_examples is not on the MATLAB path
  * evalc-runs the script and treats no-error as pass
- canlab_run_all_tests.m: new 'Walkthroughs' parameter
  ('skip' (default) | 'only' | 'include'). Default 'skip' keeps the
  fast CI workflow unchanged. The new tests-walkthroughs.yml workflow
  passes 'only' to run just the walkthroughs.

Nightly CI (.github/workflows/tests-walkthroughs.yml)
- cron '0 7 * * *' (07:00 UTC nightly) plus workflow_dispatch.
- Checks out CanlabCore + Neuroimaging_Pattern_Masks + CANlab_help_examples,
  clones SPM25 25.01.02, installs Statistics + Signal Processing Toolboxes.
- Runs canlab_run_all_tests('Walkthroughs', 'only', 'JUnit', ...) and
  uploads walkthrough-results.xml as an artifact.
- README.md gets a tests-walkthroughs status badge alongside the
  existing tests badge.

Bundled fixes (user)
- fmridisplay_helper_functions/render_blobs.m: fix for the reshape bug
  that was making canlab_help_2b_basic_image_visualization and
  canlab_help_5_regression_walkthrough fail at the region/montage call.
- canlab_help_3_voxelwise_t_test_walkthrough.m (in CANlab_help_examples
  repo): write() now uses 'overwrite' so the script is re-runnable.
- docs/Object_methods.md and docs/predictive_model_methods.md:
  editorial edits to lead with purpose-not-structure, both-and framing
  for dual-natured objects, lifecycle-aware property descriptions, and
  a curated index that omits legacy classes (fmri_mask_image dropped
  from the front-page table). docs/help_doc_agent_instructions extended
  with a new section 5 codifying these patterns for future agents.
- docs/canlab_template_codemap.pptx and
  docs/help_doc_agent_instructions_2_codemaps.txt: scaffolding for a
  follow-up code-map documentation pass (not yet acted on here).

Local verification
- Unit suite still green with the new 'Walkthroughs','skip' default:
  40 passed, 0 failed, 1 incomplete (Buckner-maps assumption-skip).
- Full walkthrough run before this commit: 8/12 passed; the remaining
  4 failures (render_blobs reshape, write 'overwrite', and one transient
  order-dependent issue in first_level_design_matrix_exploration that
  passes in isolation) were diagnosed and either fixed (first two) or
  excluded from the wrapped set (the latter and compare_pain_patterns).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a third documentation tier: a code map and a per-function help page
for 35 commonly-used methods and stand-alone helpers. Patches the per-class
methods pages to hyperlink each documented method to its new page.

Phase 1 — code maps (35 functions)
  - docs/_codemap_tools/codemap_lib.py: pptx-building DSL (Calibri/Cambria,
    file/func/var/script color palette, block + diagonal connector arrows,
    spine and branch helpers, render-and-crop via soffice + PIL).
  - docs/_codemap_tools/specs/*.py: one bespoke layout per function.
  - docs/_codemap_tools/build_all.py: batch renderer.
  - docs/code_maps_pptx/*.pptx: 35 editable code maps.
  - docs/code_maps_png/*.png: 35 cropped renders for embed in markdown.

Phase 2 — per-function markdown (35 pages)
  - docs/individual_functions/*.md: one page per function with the
    reformatted help block, code-map embed, Inputs/Outputs tables,
    canonical example, and See-also cross-links.

Phase 3 — linking (49 hyperlinks)
  - docs/_codemap_tools/relink_methods_pages.py: idempotent script that
    converts bare ``\`name\``` cells in methods-page tables into hyperlinks
    to docs/individual_functions/.
  - docs/{fmri_data,image_vector,statistic_image,atlas,region}_methods.md:
    documented methods now hyperlink to their per-function pages.
  - docs/Object_methods.md: adds a "Cross-validation helpers (stand-alone)"
    section linking xval_select_holdout_set, xval_classify, xval_SVM, xval_SVR.

Other
  - docs/help_doc_agent_instructions_2_codemaps.txt: extends the original
    spec with a "Layout rules learned from the first pass" section codifying
    the Use/Notes/Legend reserved-space rectangle, arrow rules (no
    skip-connections through spine boxes; no fan-in from a 2-row grid;
    connect outputs from the bottom-most spine node; widen boxes for long
    function names), output-row coordinates, and the render-and-check loop.
    Corrects xval_svm/xval_svr to xval_SVM/xval_SVR (on-disk capitalization).
  - CanlabCore/@fmri_data/annotate_binary_results_map.m,
    CanlabCore/@image_vector/outliers.m: minor canonical-example additions
    in the help block.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Each per-method documentation page now has a runnable "Quick example"
code block and a sample PNG showing what to expect. Examples are
mirrored 1:1 in CanlabCore/Unit_tests/canlab_test_help_examples.m so
the docs cannot silently bit-rot — the new test (30 cases) is
auto-discovered by canlab_run_all_tests and runs on every push.

GUI-fragile examples (surface, addbrain, orthviews, cluster_surf,
region.surface/labelled_surface) wrap their calls in try/catch with
tc.assumeFail on missing-graphics errors so headless CI passes
cleanly. region.table_of_atlas_regions_covered is documented as
broken on the @region path and tagged as expected-skip.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Five tests were erroring on the ubuntu runner because the runner is
headless and lacks optional, separately-licensed datasets:

  - test_atlas_methods_isosurface_montage and
    test_atlas_select_atlas_subset hit
    bianciardi_create_atlas_obj.m's input() prompt while loading the
    canlab2024 atlas (Bianciardi brainstem source files not on path),
    raising MATLAB:services:MissingRequiredCapability.
  - test_annotate_binary_results_map needs
    Yarkoni_2013_Neurosynth_featureset1.mat.
  - test_image_similarity_plot and test_statistic_image_riverplot need
    the NPS+ signature image weights_NSF_grouppred_cvpcr.img.

Expand the previous skip_on_graphics_error helper into
skip_on_environment_error covering all three categories (graphics,
interactive input, missing data) and wrap the offending tests so they
report assumeFail rather than erroring on CI. Local runs with the
files present still execute the full example.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
load_image_set and annotate_binary_results_map handle missing optional
data files by printing the actionable text via disp() and then aborting
with `error('Exiting')` - so ME.message is literally "Exiting" with an
empty identifier, not anything that matches our previous string checks.
Add that pattern to skip_on_environment_error so the three tests that
need NPS+ / Neurosynth files (test_annotate_binary_results_map,
test_image_similarity_plot, test_statistic_image_riverplot) skip
cleanly on CI runners that don't ship those files.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@torwager torwager merged commit 5a78402 into master May 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant