Skip to content

feat(plotting): support boolean color mappings from adata.uns - #4252

Draft
daveringelberg wants to merge 2 commits into
scverse:mainfrom
daveringelberg:feat/boolean-uns-color-mapping
Draft

feat(plotting): support boolean color mappings from adata.uns#4252
daveringelberg wants to merge 2 commits into
scverse:mainfrom
daveringelberg:feat/boolean-uns-color-mapping

Conversation

@daveringelberg

Copy link
Copy Markdown

This is a draft PR addressing #4219
Release notes are included in docs/release-notes/4219.feat.md

Summary

This draft PR adds support for mappings stored in adata.uns[f"{key}_colors"], so boolean colors can stay tied to True/False after subsetting.

Existing list-based color behavior is preserved.

Testing

Added tests for:

  • mapping palettes stored in adata.uns
  • boolean mappings after subsetting to only True or only False
  • boolean mappings passed through the explicit palette= argument
  • regression test for Support dictionaries for Boolean colors in 'adata.uns' #4219 covering boolean color mappings in adata.uns after subsetting.

Local checks run:

  • ruff check
  • ruff format --check
  • python -m py_compile
  • git diff --check

I could not run pytest locally due to local environment issues, so I am opening this as a draft for CI and maintainer feedback.

@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
2023 1 2022 1067
View the top 1 failed test(s) by shortest run time
tests/plotting/legacy/test_plotting_utils.py::test_get_palette_bool_mapping_from_palette_argument
Stack Traces | 0.021s run time
#x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_get_palette_bool_mapping_from_palette_argument#x1B[39;49;00m():#x1B[90m#x1B[39;49;00m
        adata = AnnData(#x1B[90m#x1B[39;49;00m
            X=np.ones((#x1B[94m4#x1B[39;49;00m, #x1B[94m1#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            obs={#x1B[33m"#x1B[39;49;00m#x1B[33mflag#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m: [#x1B[94mFalse#x1B[39;49;00m, #x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m, #x1B[94mTrue#x1B[39;49;00m]},#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>       #x1B[94massert#x1B[39;49;00m _get_palette(adata, #x1B[33m"#x1B[39;49;00m#x1B[33mflag#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, palette={#x1B[94mFalse#x1B[39;49;00m: #x1B[33m"#x1B[39;49;00m#x1B[33mred#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[94mTrue#x1B[39;49;00m: #x1B[33m"#x1B[39;49;00m#x1B[33mblue#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}) == {#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mFalse#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m: #x1B[33m"#x1B[39;49;00m#x1B[33m#ff0000#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mTrue#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m: #x1B[33m"#x1B[39;49;00m#x1B[33m#0000ff#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        }#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE       AssertionError: assert {'False': '#f...: '#0000ffff'} == {'False': '#f...e': '#0000ff'}#x1B[0m
#x1B[1m#x1B[31mE         #x1B[0m
#x1B[1m#x1B[31mE         Differing items:#x1B[0m
#x1B[1m#x1B[31mE         #x1B[0m{#x1B[33m'#x1B[39;49;00m#x1B[33mTrue#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m: #x1B[33m'#x1B[39;49;00m#x1B[33m#0000ffff#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m}#x1B[90m#x1B[39;49;00m != #x1B[0m{#x1B[33m'#x1B[39;49;00m#x1B[33mTrue#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m: #x1B[33m'#x1B[39;49;00m#x1B[33m#0000ff#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m}#x1B[90m#x1B[39;49;00m#x1B[0m
#x1B[1m#x1B[31mE         #x1B[0m{#x1B[33m'#x1B[39;49;00m#x1B[33mFalse#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m: #x1B[33m'#x1B[39;49;00m#x1B[33m#ff0000ff#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m}#x1B[90m#x1B[39;49;00m != #x1B[0m{#x1B[33m'#x1B[39;49;00m#x1B[33mFalse#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m: #x1B[33m'#x1B[39;49;00m#x1B[33m#ff0000#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m}#x1B[90m#x1B[39;49;00m#x1B[0m
#x1B[1m#x1B[31mE         #x1B[0m
#x1B[1m#x1B[31mE         Full diff:#x1B[0m
#x1B[1m#x1B[31mE         #x1B[0m#x1B[90m #x1B[39;49;00m {#x1B[90m#x1B[39;49;00m#x1B[0m
#x1B[1m#x1B[31mE         #x1B[91m-     'False': '#ff0000',#x1B[39;49;00m#x1B[90m#x1B[39;49;00m#x1B[0m
#x1B[1m#x1B[31mE         #x1B[92m+     'False': '#ff0000ff',#x1B[39;49;00m#x1B[90m#x1B[39;49;00m#x1B[0m
#x1B[1m#x1B[31mE         ?                      ++#x1B[90m#x1B[39;49;00m#x1B[0m
#x1B[1m#x1B[31mE         #x1B[91m-     'True': '#0000ff',#x1B[39;49;00m#x1B[90m#x1B[39;49;00m#x1B[0m
#x1B[1m#x1B[31mE         #x1B[92m+     'True': '#0000ffff',#x1B[39;49;00m#x1B[90m#x1B[39;49;00m#x1B[0m
#x1B[1m#x1B[31mE         ?                     ++#x1B[90m#x1B[39;49;00m#x1B[0m
#x1B[1m#x1B[31mE         #x1B[90m #x1B[39;49;00m }#x1B[90m#x1B[39;49;00m#x1B[0m

#x1B[1m#x1B[.../plotting/legacy/test_plotting_utils.py#x1B[0m:67: AssertionError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@flying-sheep

flying-sheep commented Jul 27, 2026

Copy link
Copy Markdown
Member

Looks like it mostly works except for a small discrepancy in expected values (alpha channel I suppose):

FAILED tests/plotting/legacy/test_plotting_utils.py::test_get_palette_bool_mapping_from_palette_argument - AssertionError: assert {'False': '#f...: '#0000ffff'} == {'False': '#f...e': '#0000ff'}
  
  Differing items:
  {'True': '#0000ffff'} != {'True': '#0000ff'}
  {'False': '#ff0000ff'} != {'False': '#ff0000'}

But this is a lot of added complexity.

Don’t you think it makes more sense to just add both colors in a list if the categorical is boolean?

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