Skip to content

feat: add cortical region boundary contours (contours parameter)#12

Open
GalKepler wants to merge 10 commits into
teanijarv:mainfrom
GalKepler:contours
Open

feat: add cortical region boundary contours (contours parameter)#12
GalKepler wants to merge 10 commits into
teanijarv:mainfrom
GalKepler:contours

Conversation

@GalKepler
Copy link
Copy Markdown

@GalKepler GalKepler commented May 7, 2026

Summary

Adds a contours parameter to plot_cortical for drawing atlas region boundary lines on the surface, with support for selective regions and per-region styling.

Changes

yabplot/mesh.py

  • get_region_boundaries: new region_ids filter (draw outlines for specific regions only) and smooth_iterations (Laplacian smoothing on boundary line vertices to reduce triangular jaggedness — especially useful with proc_vertices='sharp').

yabplot/plotting.py

  • New contours parameter on plot_cortical (replaces earlier draft's draw_contours + contour_regions).
  • _build_contour_layers() helper resolves contours into a list of (lh_mesh, rh_mesh, kwargs) render groups, allowing multiple style groups per call.
  • Smoothing auto-set to 10 iterations when proc_vertices='sharp', otherwise 0 (user-overridable).

docs/tutorials/plot_styling.ipynb

  • Section 5 updated with all contours forms and a sharp-mode smoothing example.

API

# all regions, default style
plot_cortical(data, atlas='schaefer400', contours=True)

# all regions, custom global style
plot_cortical(data, atlas='schaefer400', contours={'color': 'white', 'line_width': 1.5})

# only regions with data (bool mask)
plot_cortical(data, atlas='schaefer400', contours=~np.isnan(data))

# specific regions by name
plot_cortical(data, atlas='schaefer400', contours=['region_A', 'region_B'])

# per-region style (only listed regions get contours)
plot_cortical(data, atlas='schaefer400', contours={
    'region_A': {'color': 'red',  'line_width': 3.0},
    'region_B': {'color': 'blue', 'line_width': 3.0},
})

# sharp mode — contours auto-smoothed (smooth_iterations=10)
plot_cortical(data, atlas='schaefer400', contours=True, proc_vertices='sharp')

# override smoothing manually
plot_cortical(data, atlas='schaefer400', contours={'smooth_iterations': 20})

contours disambiguation

type detection behavior
False / None no contours
True all regions, default style
dict with primitive values values are not dicts all regions, custom style
list / bool ndarray those regions, default style
dict with dict values all values are dicts per-region style, only listed regions

Breaking changes

None — contours defaults to False.

🤖 Generated with Claude Code

GalKepler and others added 3 commits May 7, 2026 14:04
Extends draw_contours with a contour_regions parameter that restricts
which atlas regions get boundary lines. Accepts a list of region names,
a boolean mask over LUT order, or a dict mapping region name to per-region
style kwargs (merged with the global draw_contours defaults).

Internally, get_region_boundaries gains a region_ids filter and
_render_cortical_views now takes a contour_layers list of
(lh_mesh, rh_mesh, kwargs) tuples, allowing multiple style groups to
render in one pass. Notebook updated with examples for all three input
forms.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@GalKepler GalKepler changed the title feat: add atlas region contours to cortical surface plots feat: add atlas region contours + selective contour_regions to cortical plots May 7, 2026
@teanijarv
Copy link
Copy Markdown
Owner

Hi Gal, this is great addition and one that has been requested before too.

I just now made a commit where i made the proc_vertices='sharp' for plot_cortical() as the default option which makes the atlas regions more sharper and visually more appealing. However, currently running the contour options on it, these lines are a bit too poor in quality (see image below). Would you be able to try to make that the lines are similarly less jagged?

And some more minor things. Could you remove the Claude.md from .gitignore and also we could discuss whether two separate contour related parameters is the best approach or there could be ways to combine them into one - I'm open to having to parameters, but as this is a feature which most won't be using, then ideally it could maybe be combined to single parameter. Besides that, I haven't yet tried it out with more options than the notebook you provided, so I'm unsure if there would be more bugs.

But again, thanks for the PR, this is great work!

image

- Merge draw_contours + contour_regions into single contours parameter:
  True → all regions default style; style-dict → all regions custom style;
  list/bool-ndarray → those regions default style; region-dict (values are
  dicts) → per-region style for listed regions only.

- Add smooth_iterations to get_region_boundaries: Laplacian smoothing on
  boundary line vertices reduces triangular jaggedness. Auto-set to 10
  when proc_vertices='sharp', otherwise 0. User-overridable via
  contours={'smooth_iterations': N}.

- Remove CLAUDE.md from .gitignore.

- Update notebook: section 5 uses new contours param throughout, adds
  sharp-mode smoothing example; section 6 folded into section 5 as a
  subsection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@GalKepler GalKepler changed the title feat: add atlas region contours + selective contour_regions to cortical plots feat: add cortical region boundary contours (contours parameter) May 11, 2026
GalKepler and others added 6 commits May 11, 2026 10:19
smooth_iterations defaults to 10 for all contour rendering modes —
jaggedness is a mesh-topology artefact present in all proc_vertices
modes, not just 'sharp'. User can disable with
contours={'smooth_iterations': 0}. Removes the proc_vertices dependency
from _build_contour_layers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Plain Laplacian moves junction vertices (where ≥3 region boundaries
meet) toward their neighbors' centroid, tearing the lines apart.

Fix: pin vertices with degree != 2 (junctions and endpoints) and only
smooth degree-2 chain vertices. Boundaries now converge cleanly at
meeting points.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Degree-based pinning (len(neighbors) == 2) fails on dense cortical
meshes where boundary vertices regularly have 3-6 boundary edges even
on simple two-region chains, causing nearly all vertices to be pinned
and no smoothing to apply.

Replace with label-count check: pin vertices where ≥3 distinct region
labels converge in the boundary-edge neighborhood (true junctions);
smooth all others regardless of degree.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Smoothing attempts produced gaps and artifacts. Reverts mesh.py,
plotting.py, and the notebook to the state before any smoothing
was introduced. Also restores two-param API (draw_contours +
contour_regions) since consolidation and smoothing were bundled
in the same commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s param

Single parameter accepts: True (all regions, default style), style-dict
(all regions, custom style), list/bool-ndarray (those regions, default
style), or region-dict (per-region style for listed regions only).

No smoothing. Notebook updated accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Width of 2 is barely visible in rendered output.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

2 participants