Skip to content

Commit 6d18fa7

Browse files
committed
fix: tolerate scanpy 1.13 relocation of internal plotting helpers
scanpy 1.13 moved the default palettes and several private plotting helpers from scanpy.plotting.{palettes,_tools,_utils} to scanpy.plotting.legacy.*, breaking `import spatialdata_plot` on pre-release scanpy (every test errored at conftest collection). Add a single _scanpy_compat module that imports each symbol from the new path and falls back to the old one, and route all call sites through it: - default_20 / default_28 / default_102 (_palette.py, _color.py, utils.py) - _add_categorical_legend (render.py, utils.py) - add_colors_for_categorical_sample_annotation (_color.py) Values and behaviour are unchanged (the palettes hash identically across versions); this only confines the reliance on scanpy internals to one version-tolerant module. scanpy._settings / scanpy.settings are unaffected.
1 parent 227434d commit 6d18fa7

5 files changed

Lines changed: 42 additions & 7 deletions

File tree

src/spatialdata_plot/pl/_color.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
from numpy.random import default_rng
2828
from pandas.api.types import CategoricalDtype, is_bool_dtype, is_numeric_dtype, is_string_dtype
2929
from pandas.core.arrays.categorical import Categorical
30-
from scanpy.plotting._utils import add_colors_for_categorical_sample_annotation
31-
from scanpy.plotting.palettes import default_20, default_28, default_102
3230
from skimage.color import label2rgb
3331
from skimage.morphology import erosion, footprint_rectangle
3432
from skimage.util import map_array
@@ -42,6 +40,12 @@
4240
)
4341

4442
from spatialdata_plot._logging import logger
43+
from spatialdata_plot.pl._scanpy_compat import (
44+
add_colors_for_categorical_sample_annotation,
45+
default_20,
46+
default_28,
47+
default_102,
48+
)
4549
from spatialdata_plot.pl.render_params import (
4650
CmapParams,
4751
Color,

src/spatialdata_plot/pl/_palette.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
import pandas as pd
2121
from matplotlib.colors import ListedColormap, to_hex, to_rgb
2222
from matplotlib.pyplot import colormaps as mpl_colormaps
23-
from scanpy.plotting.palettes import default_20, default_28, default_102
23+
24+
from spatialdata_plot.pl._scanpy_compat import default_20, default_28, default_102
2425

2526
if TYPE_CHECKING:
2627
import spatialdata as sd
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Version-tolerant access to scanpy internals used by spatialdata-plot.
2+
3+
scanpy 1.13 relocated the default palettes and several private plotting helpers from
4+
``scanpy.plotting.{palettes,_tools,_utils}`` to ``scanpy.plotting.legacy.*``. The values and
5+
behaviour are unchanged, so we import from whichever path the installed scanpy exposes and
6+
re-export from a single place. This keeps spatialdata-plot working on scanpy both < and >= 1.13
7+
and confines the reliance on scanpy internals to one module.
8+
"""
9+
10+
try: # scanpy >= 1.13
11+
from scanpy.plotting.legacy.palettes import default_20, default_28, default_102
12+
except ImportError: # scanpy < 1.13
13+
from scanpy.plotting.palettes import default_20, default_28, default_102
14+
15+
try: # scanpy >= 1.13
16+
from scanpy.plotting.legacy._tools.scatterplots import _add_categorical_legend
17+
except ImportError: # scanpy < 1.13
18+
from scanpy.plotting._tools.scatterplots import _add_categorical_legend
19+
20+
try: # scanpy >= 1.13
21+
from scanpy.plotting.legacy._utils import add_colors_for_categorical_sample_annotation
22+
except ImportError: # scanpy < 1.13
23+
from scanpy.plotting._utils import add_colors_for_categorical_sample_annotation
24+
25+
__all__ = [
26+
"_add_categorical_legend",
27+
"add_colors_for_categorical_sample_annotation",
28+
"default_20",
29+
"default_28",
30+
"default_102",
31+
]

src/spatialdata_plot/pl/render.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from matplotlib.cm import ScalarMappable
2222
from matplotlib.colors import BoundaryNorm, Colormap, ListedColormap, Normalize, to_rgba_array
2323
from scanpy._settings import settings as sc_settings
24-
from scanpy.plotting._tools.scatterplots import _add_categorical_legend
2524
from spatialdata import get_extent, get_values
2625
from spatialdata.models import PointsModel, ShapesModel, get_table_keys
2726
from spatialdata.transformations import set_transformation
@@ -60,6 +59,7 @@
6059
_scale_geometries,
6160
_validate_polygons,
6261
)
62+
from spatialdata_plot.pl._scanpy_compat import _add_categorical_legend
6363
from spatialdata_plot.pl._validate import (
6464
_check_obs_var_shadow,
6565
)

src/spatialdata_plot/pl/utils.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
from pandas.api.types import CategoricalDtype, is_numeric_dtype
3232
from pandas.core.arrays.categorical import Categorical
3333
from scanpy import settings
34-
from scanpy.plotting import palettes
35-
from scanpy.plotting._tools.scatterplots import _add_categorical_legend
3634
from spatialdata import (
3735
SpatialData,
3836
get_element_annotators,
@@ -57,6 +55,7 @@
5755
from xarray import DataArray, DataTree
5856

5957
from spatialdata_plot._logging import logger
58+
from spatialdata_plot.pl._scanpy_compat import _add_categorical_legend, default_102
6059
from spatialdata_plot.pl.render_params import (
6160
Color,
6261
ColorbarSpec,
@@ -451,7 +450,7 @@ def _stack_categorical_legend(
451450
# A per-entry legend past this many categories is unreadable, and scanpy builds it in O(categories^2)
452451
# (one autoscaling artist each), dominating the render — so skip it with a warning. Tied to scanpy's
453452
# default_102 palette, beyond which its *default* colors also stop being distinguishable (uniform grey).
454-
_MAX_LEGEND_CATEGORIES = len(palettes.default_102)
453+
_MAX_LEGEND_CATEGORIES = len(default_102)
455454

456455

457456
def _first_color_per_category(source: pd.Categorical, color_vector: Any) -> dict[Any, Any]:

0 commit comments

Comments
 (0)