Skip to content

fix: avoid cumulative size reordering across multi-color subplots#4023

Merged
flying-sheep merged 1 commit intoscverse:mainfrom
Marius1311:fix/scatter-size-reorder
Apr 20, 2026
Merged

fix: avoid cumulative size reordering across multi-color subplots#4023
flying-sheep merged 1 commit intoscverse:mainfrom
Marius1311:fix/scatter-size-reorder

Conversation

@Marius1311
Copy link
Copy Markdown
Contributor

@Marius1311 Marius1311 commented Mar 31, 2026


When sc.pl.embedding (or sc.pl.umap, etc.) is called with multiple color keys and a per-point size array, the size variable is cumulatively reordered across loop iterations:

# line 299 in scatterplots.py
if isinstance(size, np.ndarray):
    size = np.array(size)[order]  # mutates loop variable!

Each subplot computes its own order (for z-ordering by color value), but applies it to the already-reordered size from the previous iteration. This means:

  • Subplot 1: correct sizes
  • Subplot 2: sizes scrambled by order1 × order2
  • Subplot 3: sizes scrambled by order1 × order2 × order3
  • etc.

Fix: use a loop-local _size variable so each iteration reorders from the original size array. The same pattern is applied to the scatter call and add_outline code that consume the size.

Minimal reproduction:

import scanpy as sc
import numpy as np

adata = sc.datasets.pbmc3k_processed()
sizes = np.random.default_rng(0).uniform(10, 200, size=adata.n_obs)
sc.pl.umap(adata, color=["louvain", "n_genes", "n_counts"], size=sizes)
# Dot sizes visibly differ across panels despite being the same array

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.49%. Comparing base (1fbe008) to head (83b4db4).
⚠️ Report is 19 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4023      +/-   ##
==========================================
- Coverage   78.50%   78.49%   -0.01%     
==========================================
  Files         117      117              
  Lines       12740    12739       -1     
==========================================
- Hits        10001    10000       -1     
  Misses       2739     2739              
Flag Coverage Δ
hatch-test.low-vers 77.79% <100.00%> (-0.01%) ⬇️
hatch-test.pre 77.45% <100.00%> (-0.01%) ⬇️

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

Files with missing lines Coverage Δ
src/scanpy/plotting/_tools/scatterplots.py 83.48% <100.00%> (-0.04%) ⬇️

@flying-sheep flying-sheep added this to the 1.12.2 milestone Apr 20, 2026
@flying-sheep flying-sheep merged commit 9909599 into scverse:main Apr 20, 2026
16 of 18 checks passed
@flying-sheep
Copy link
Copy Markdown
Member

thank you!

meeseeksmachine pushed a commit to meeseeksmachine/scanpy that referenced this pull request Apr 20, 2026
flying-sheep pushed a commit that referenced this pull request Apr 20, 2026
…ring across multi-color subplots) (#4075)

Co-authored-by: Marius Lange <marius.lange@bsse.ethz.ch>
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.

Per-point size array is cumulatively reordered across multi-color subplots

2 participants