Skip to content

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

Open
Marius1311 wants to merge 1 commit intoscverse:mainfrom
Marius1311:fix/scatter-size-reorder
Open

fix: avoid cumulative size reordering across multi-color subplots#4023
Marius1311 wants to merge 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).
✅ 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%) ⬇️

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

1 participant