Skip to content

feat(plotting): add plot_matrix for connectivity/correlation matrices#243

Open
sdiebolt wants to merge 14 commits into
mainfrom
feat/plot_matrix
Open

feat(plotting): add plot_matrix for connectivity/correlation matrices#243
sdiebolt wants to merge 14 commits into
mainfrom
feat/plot_matrix

Conversation

@sdiebolt

@sdiebolt sdiebolt commented Jul 4, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds plot_matrix, inspired by nilearn.plotting.plot_matrix, for plotting 2D matrices (numpy.ndarray or xarray.DataArray) with lower/diag triangle masking, grid lines, and a symmetric diverging colormap.
  • Adds a groups feature (no Nilearn equivalent): contiguous label runs get colored rectangle strips alongside the matrix, useful for marking anatomical groupings (e.g. cortex, thalamus) when there are too many individual labels to read.
  • Moves color/fontsize helpers shared between image.py and the new matrix.py into module-private plotting/_utils.py.
  • Fixes just generate-baselines, which only regenerated two of the visual-regression test classes and was silently deleting the rest.

Closes #241

sdiebolt added 3 commits July 4, 2026 10:38
…ines

The recipe only regenerated TestPlotVolume/TestPlotContours baselines, so
running `just generate-baselines` silently deleted the carpet, composite,
and (new) matrix baseline PNGs without recreating them.
Adds plot_matrix, inspired by nilearn.plotting.plot_matrix, for displaying
2D matrices (numpy.ndarray or xarray.DataArray) with optional lower/diag
triangle masking, grid lines, and a symmetric diverging colormap. Also adds
a groups feature (no nilearn equivalent): contiguous label runs are
annotated with colored rectangle strips alongside the matrix, useful for
marking anatomical groupings (e.g. cortex, thalamus) when there are too
many individual labels to read.

Moves the color/fontsize helpers shared between image.py and the new
matrix.py into the module-private plotting/_utils.py.

Refs #241
@sdiebolt sdiebolt self-assigned this Jul 4, 2026
@sdiebolt sdiebolt added the enhancement New feature or request label Jul 4, 2026
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

📖 Doc preview: https://confusius.tools/pr-preview/pr-243/

@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

sdiebolt added 10 commits July 4, 2026 10:54
Brings plot_matrix to 100% coverage: missing-coordinate/empty-labels
defaults, all three tri grid variants, show_group_labels=False,
caller-provided ax, and cbar_label. codecov/patch was failing on the
uncovered lines.
… labels

The group-strip axes share their perpendicular axis with the main axes
(sharex/sharey) so the strips line up with rows/columns. Clearing that
shared axis's ticks with set_xticks([])/set_yticks([]) propagated through
the shared locator and wiped out the main axes' own row/column labels too.
Use tick_params to hide the strip's ticks/labels instead of resetting the
shared locator, and widen the row-strip pad so labels have room to render
next to it instead of being covered by the opaque strip.

Found while building a real-world plot_matrix example (fUSI connectivity
matrix with anatomical region groups) where both labels and groups were
used together for the first time.
Demonstrates an end-to-end regional connectivity analysis: register a
single-slice fUSI recording (Nunez-Elizalde 2022, CR022) to the
Pepe-Mariani 2026 template with a rigid transform, resample the Allen
Mouse Brain Atlas onto the recording's native grid, extract region signals
for a handful of cortical/hippocampal/thalamic/hypothalamic ROIs, and plot
their correlation matrix with plot_matrix's new groups annotation.

Wires the new section into the gallery nav, prefetches the Nunez-Elizalde
recording, the Pepe-Mariani template, and the allen_mouse_100um BrainGlobe
atlas in CI, and adds matching actions/cache steps for the template and
BrainGlobe atlas downloads (the Nunez-Elizalde recording reuses the
existing dataset cache step).
The row group-strip axis was inserted with a fixed pad, which only left
enough room for short labels; longer labels (e.g. region acronyms with a
hemisphere suffix) got visually covered by the opaque strip even though
the label text itself was set correctly. Measure the rendered y tick
label width (Nilearn's _fit_axes technique) and size the pad from it
instead.

Found while building a real-world connectivity-matrix example with
longer region labels.
- Use cf.<module>.<func> consistently instead of importing individual
  functions, applied across the example gallery for consistency.
- Resample the recording to a uniform time grid before any time-domain
  processing (its raw timestamps are not perfectly uniform).
- Extract left/right hemispheres separately via get_masks(sides=...) and
  order each area's regions medial-to-lateral, mirrored across the
  midline (lateral-to-medial on the left, medial-to-lateral on the
  right), so each area block reads as one continuous sweep across the
  slice with homotopic pairs meeting in the middle.
- Clean the averaged region signals (high-pass filter + white-matter
  aCompCor regression) before computing the correlation matrix.
Renames "diag" to "diag_lower" and adds "diag_upper" and "upper",
mirroring "lower"/"diag_lower" across the diagonal. Together with the
existing ax= support, this lets two matrices be overlaid on the same
axes (e.g. an estimate on the lower triangle and its significance mask
on the upper), by calling plot_matrix twice with complementary tri
values and show_colorbar=False on the second call.
…ample

The narrative said "rigid transform" while the code already used
transform_type="affine". Also note the visible improvement after
registration, most noticeable around the anterior choroidal arteries in
the bottom of the field of view.
…zing

_y_tick_label_width_inches falls back to 0.0 when get_tightbbox returns
None, which happens for real (not just hypothetically) when labels are
all empty strings: they have no rendered extent. codecov/patch flagged
this line as uncovered.
get_masks accepts sides as a per-region list, so both hemispheres can be
requested in a single call (region acronyms duplicated, sides list
matching) instead of two separate calls concatenated together. Each
layer still needs a unique id reassigned afterward since get_masks
reuses the same region id for both hemispheres of a region.
@sdiebolt sdiebolt requested a review from FelipeCybis July 5, 2026 17:02
@sdiebolt

sdiebolt commented Jul 5, 2026

Copy link
Copy Markdown
Member Author

@FelipeCybis Ready to review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add plot_matrix for connectivity/correlation matrices

1 participant