Skip to content

Fix cmap=ListedColormap raising 'unhashable type' and add regression tests - #162

Merged
zihuaihuai merged 1 commit into
masterfrom
fix-cmap-listedcolormap-tests
May 5, 2026
Merged

zihuaihuai merged 1 commit into
masterfrom
fix-cmap-listedcolormap-tests

Conversation

@zihuaihuai

@zihuaihuai zihuaihuai commented May 5, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • build_plotter does cm in colormaps where colormaps is a dict. Passing a matplotlib ListedColormap/LinearSegmentedColormap instance therefore raised TypeError: unhashable type: 'ListedColormap'.
  • Reported by a hippomaps user calling surfplot_canonical_foldunfold(..., cmap=cmc.devon, ...) after reinstalling brainspace; works around with a string cmap name only.
  • Master already guarded the dict lookup with isinstance(cm, str), but still leaned on plt.get_cmap(cm) to coerce the non-string branch. This PR makes the path explicit (Colormap instance vs. string vs. unsupported type) and pins the contract with regression tests so the bug can't slip back in.

Changes

  • brainspace/plotting/surface_plotting.py
    • Import matplotlib.colors.Colormap.
    • In build_plotter's LUT block: accept Colormap instances directly, route strings through plt.get_cmap, and raise a clear TypeError for anything else.
    • Update cmap docstrings on build_plotter, plot_surf, and plot_hemispheres to document Colormap-instance support.
  • brainspace/tests/test_plotting.py — 7 new regression tests:
    • ListedColormap and LinearSegmentedColormap instance cases (the original bug)
    • Matplotlib string names continue to work
    • brainspace-registered names (BuGyRd) continue to resolve to the precomputed lookup
    • Mixed string + Colormap across layout cells
    • Invalid cmap types raise a clear TypeError
    • End-to-end plot_surf smoke test with a Colormap instance

Test plan

  • pytest brainspace/tests/test_plotting.py brainspace/tests/test_colormaps.py — 19 passed locally on macOS / Python 3.10 / matplotlib 3.10.
  • Manually reproduced the original failure (ListedColormap in colormaps -> unhashable) and confirmed build_plotter(..., cmap=ListedColormap(...)) now succeeds.
  • CI (Linux/macOS, Python 3.9-3.13) green.

`build_plotter` previously called `cm in colormaps` directly where
`colormaps` is a dict. Passing a matplotlib `ListedColormap` /
`LinearSegmentedColormap` instance therefore raised
`TypeError: unhashable type: 'ListedColormap'` — the same failure
reported by hippomaps users calling `surfplot_canonical_foldunfold`
with `cmap=cmc.devon`.

Master already guarded the membership check with `isinstance(cm, str)`,
but still relied on `plt.get_cmap(cm)` to coerce the non-string branch.
Make the path explicit:

- accept `matplotlib.colors.Colormap` instances directly
- only call `plt.get_cmap` for string inputs
- raise a clear `TypeError` for any other type

Also broaden the `cmap` parameter docstrings on `build_plotter`,
`plot_surf`, and `plot_hemispheres` to document Colormap-instance
support.

Tests in `brainspace/tests/test_plotting.py` now cover:

- `ListedColormap` and `LinearSegmentedColormap` instances
- matplotlib registered cmap names
- brainspace-registered cmap names (`BuGyRd`)
- mixed string/Colormap entries across layout cells
- invalid cmap types fail with a useful error
- end-to-end `plot_surf` smoke test with a Colormap instance

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zihuaihuai
zihuaihuai merged commit dd6a5a8 into master May 5, 2026
16 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