diff --git a/src/spatialdata_plot/pl/_color.py b/src/spatialdata_plot/pl/_color.py index adefb606..038010bd 100644 --- a/src/spatialdata_plot/pl/_color.py +++ b/src/spatialdata_plot/pl/_color.py @@ -28,7 +28,6 @@ from pandas.api.types import CategoricalDtype, is_bool_dtype, is_numeric_dtype, is_string_dtype from pandas.core.arrays.categorical import Categorical from scanpy.plotting._utils import add_colors_for_categorical_sample_annotation -from scanpy.plotting.palettes import default_20, default_28, default_102 from skimage.color import label2rgb from skimage.morphology import erosion, footprint_rectangle from skimage.util import map_array @@ -42,6 +41,7 @@ ) from spatialdata_plot._logging import logger +from spatialdata_plot.pl._scanpy_palettes import default_20, default_28, default_102 from spatialdata_plot.pl.render_params import ( CmapParams, Color, diff --git a/src/spatialdata_plot/pl/_palette.py b/src/spatialdata_plot/pl/_palette.py index 83d1b01b..2b1c056e 100644 --- a/src/spatialdata_plot/pl/_palette.py +++ b/src/spatialdata_plot/pl/_palette.py @@ -20,7 +20,8 @@ import pandas as pd from matplotlib.colors import ListedColormap, to_hex, to_rgb from matplotlib.pyplot import colormaps as mpl_colormaps -from scanpy.plotting.palettes import default_20, default_28, default_102 + +from spatialdata_plot.pl._scanpy_palettes import default_20, default_28, default_102 if TYPE_CHECKING: import spatialdata as sd diff --git a/src/spatialdata_plot/pl/_scanpy_palettes.py b/src/spatialdata_plot/pl/_scanpy_palettes.py new file mode 100644 index 00000000..b873433e --- /dev/null +++ b/src/spatialdata_plot/pl/_scanpy_palettes.py @@ -0,0 +1,14 @@ +"""Access scanpy's built-in categorical palettes across scanpy versions. + +scanpy relocated the ``default_20`` / ``default_28`` / ``default_102`` palettes from +``scanpy.plotting.palettes`` to ``scanpy.plotting.legacy.palettes`` in 1.13. The values are +frozen (identical across versions), so we import from whichever path the installed scanpy +exposes and re-export them from a single place for the rest of the package. +""" + +try: # scanpy >= 1.13 + from scanpy.plotting.legacy.palettes import default_20, default_28, default_102 +except ImportError: # scanpy < 1.13 + from scanpy.plotting.palettes import default_20, default_28, default_102 + +__all__ = ["default_20", "default_28", "default_102"] diff --git a/src/spatialdata_plot/pl/utils.py b/src/spatialdata_plot/pl/utils.py index a3a74abf..2de50ade 100644 --- a/src/spatialdata_plot/pl/utils.py +++ b/src/spatialdata_plot/pl/utils.py @@ -31,7 +31,6 @@ from pandas.api.types import CategoricalDtype, is_numeric_dtype from pandas.core.arrays.categorical import Categorical from scanpy import settings -from scanpy.plotting import palettes from scanpy.plotting._tools.scatterplots import _add_categorical_legend from spatialdata import ( SpatialData, @@ -57,6 +56,7 @@ from xarray import DataArray, DataTree from spatialdata_plot._logging import logger +from spatialdata_plot.pl._scanpy_palettes import default_102 from spatialdata_plot.pl.render_params import ( Color, ColorbarSpec, @@ -451,7 +451,7 @@ def _stack_categorical_legend( # A per-entry legend past this many categories is unreadable, and scanpy builds it in O(categories^2) # (one autoscaling artist each), dominating the render — so skip it with a warning. Tied to scanpy's # default_102 palette, beyond which its *default* colors also stop being distinguishable (uniform grey). -_MAX_LEGEND_CATEGORIES = len(palettes.default_102) +_MAX_LEGEND_CATEGORIES = len(default_102) def _first_color_per_category(source: pd.Categorical, color_vector: Any) -> dict[Any, Any]: