Skip to content

feat: new holoviz plotting#4188

Open
flying-sheep wants to merge 13 commits into
aggregate-dimfrom
plotting
Open

feat: new holoviz plotting#4188
flying-sheep wants to merge 13 commits into
aggregate-dimfrom
plotting

Conversation

@flying-sheep

@flying-sheep flying-sheep commented Jun 29, 2026

Copy link
Copy Markdown
Member

TODO

  • dotplot
  • more plots?
  • export helpers like dot_size
  • other backends demo
  • selenium for export?
  • example notebook(s)
  • re-export A/AdDim (A = sc.pl.hv_init())

@flying-sheep flying-sheep added this to the 1.13.0 milestone Jun 29, 2026
@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 45.08393% with 229 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.58%. Comparing base (82bb6ad) to head (1061609).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/scanpy/plotting/_v2/_core.py 0.00% 129 Missing ⚠️
src/scanpy/plotting/_v2/_tl.py 0.00% 44 Missing ⚠️
src/scanpy/plotting/_v2/_api.py 0.00% 17 Missing ⚠️
src/scanpy/plotting/_v2/_pp.py 0.00% 17 Missing ⚠️
src/scanpy/plotting/legacy/mpl_settings.py 89.23% 7 Missing ⚠️
src/scanpy/plotting/_v2/__init__.py 0.00% 6 Missing ⚠️
src/scanpy/datasets/_datasets.py 57.14% 3 Missing ⚠️
src/scanpy/plotting/__init__.py 90.00% 2 Missing ⚠️
src/scanpy/tools/_embedding_density.py 60.00% 2 Missing ⚠️
src/scanpy/plotting/legacy/_utils.py 87.50% 1 Missing ⚠️
... and 1 more
Additional details and impacted files
@@                Coverage Diff                @@
##           aggregate-dim    #4188      +/-   ##
=================================================
- Coverage          80.03%   78.58%   -1.46%     
=================================================
  Files                121      128       +7     
  Lines              13030    13282     +252     
=================================================
+ Hits               10429    10438       +9     
- Misses              2601     2844     +243     
Flag Coverage Δ
hatch-test.low-vers 77.51% <45.08%> (-1.47%) ⬇️
hatch-test.pre 78.47% <45.08%> (-1.48%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/scanpy/__init__.py 96.55% <100.00%> (ø)
src/scanpy/_settings/__init__.py 96.11% <ø> (+4.38%) ⬆️
src/scanpy/external/pl.py 29.21% <100.00%> (ø)
src/scanpy/plotting/_common.py 100.00% <100.00%> (ø)
src/scanpy/plotting/legacy/__init__.py 100.00% <100.00%> (ø)
src/scanpy/plotting/legacy/_anndata.py 85.65% <100.00%> (ø)
src/scanpy/plotting/legacy/_baseplot_class.py 80.36% <100.00%> (ø)
src/scanpy/plotting/legacy/_docs.py 100.00% <100.00%> (ø)
src/scanpy/plotting/legacy/_dotplot.py 91.89% <100.00%> (ø)
src/scanpy/plotting/legacy/_easter_egg.py 100.00% <ø> (ø)
... and 21 more

... and 2 files with indirect coverage changes

@flying-sheep flying-sheep changed the base branch from main to naked-base July 2, 2026 08:18
Base automatically changed from naked-base to main July 2, 2026 15:26
@flying-sheep flying-sheep marked this pull request as ready for review July 3, 2026 12:40
@flying-sheep flying-sheep changed the base branch from main to aggregate-dim July 7, 2026 06:53

@ilan-gold ilan-gold left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a first quick pass!

kdims: Collection[AdDim],
vdims: Collection[AdDim] = (),
*,
color: AdDim | None = None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would the complexity be in allowing this to be a list so we can lay out a grid?

sc.pl.scatter(adata, x="CD79A", y="CD3D", color=["bulk_labels", "n_genes"])

current does side-by-side plotting.

Even with bokeh, I'd think something like

sc.pl.scatter(adata, A.X[:, ["C1QA", "PSAP"]], color=[A.obs["bulk_labels"], A.obs["n_genes"]])

would be possible, given the richness holoviz supports: https://hv-anndata.readthedocs.io/en/latest/#manifoldmap-app-to-explore-all-dimensionality-reduction-results allows choosing between labels dynamically but perhaps https://hv-anndata.readthedocs.io/en/latest/examples/Violin.html's example at the bottom of layouts is more what we'd be going for here

If this is an "open question," happy to discuss!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shorter would be color=A.obs[["bulk_labels", "n_genes"]] btw.

faceting in holoviz is pretty simple, I’ll add an example.

diffmap = _embedding("diffmap", "diffusion map")


def heatmap(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

matplotlib version seems a little messed up

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oof yeah definitely addressing this before releasing

return hm


def tracksplot(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not just here, but in general, the MPL versions seem too small (heatmap too I noticed, see other screenshot). This one, though, appears to be missing a few features including labels (bokeh is as well)

Image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, known issues, e.g. holoviz/holoviews#6658

vdims: AdDim,
*,
kdims: Collection[AdDim] = (),
color: AdDim | None = None,

@ilan-gold ilan-gold Jul 15, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems clear that a Collection of color should be supported given its an example on the hv-anndata site

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean matplotlib.typing.ColorLike or so?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No just reshashing #4188 (comment) but for violin

sc.pl.dotplot(adata[:, markers], A.obs["bulk_labels"])

"""
stats_wide = sc.get.aggregate(adata, group_by, funcs.values())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh my gosh, this is so simple :))))

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahaha I know! I was so happy when this came together!

Probably something for the blog post!

)


def dotplot(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both bokeh and matplotlib appear not to have resized dots:

Image

Also probably we want a dendrogram argument, right?

@flying-sheep flying-sheep Jul 15, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent a lot of time on these dot sizes, they weren’t perfect when I stopped but they should definitely be recognizably different. Hmm.

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.

Holoviz based plotting

2 participants