diff --git a/src/napari_spatialdata/_widgets.py b/src/napari_spatialdata/_widgets.py index 5431036f..7cab1d64 100644 --- a/src/napari_spatialdata/_widgets.py +++ b/src/napari_spatialdata/_widgets.py @@ -18,7 +18,6 @@ from napari.viewer import Viewer from qtpy import QtCore, QtWidgets from qtpy.QtCore import Qt, Signal -from scanpy.plotting._utils import _set_colors_for_categorical_obs from sklearn.preprocessing import MinMaxScaler from spatialdata._types import ArrayLike from superqt import QRangeSlider @@ -26,6 +25,14 @@ from vispy.color.colormap import Colormap, MatplotlibColormap from vispy.scene.widgets import ColorBarWidget +# See https://github.com/scverse/squidpy/issues/1061 for more details. +# Scanpy 0.11.x-0.12.x renamed set_default_colors_for_categorical_obs to _set_default_colors_for_categorical_obs +# and then changed it back. Try underscore version first, fall back to non-underscore. +try: + from scanpy.plotting._utils import _set_colors_for_categorical_obs as set_colors_for_categorical_obs +except ImportError: + from scanpy.plotting._utils import set_colors_for_categorical_obs + from napari_spatialdata._model import DataModel from napari_spatialdata.utils._utils import _min_max_norm, get_napari_version @@ -213,7 +220,7 @@ def _(self, vec: pd.Series, **kwargs: Any) -> dict[str, Any]: if self._attr != "columns_df": if vec_color_name not in self.model.adata.uns: colorer = AnnData(shape=(len(vec), 0), obs=pd.DataFrame(index=vec.index, data={"vec": vec})) - _set_colors_for_categorical_obs(colorer, "vec", palette="tab20") + set_colors_for_categorical_obs(colorer, "vec", palette="tab20") colors = colorer.uns["vec_colors"] color_dict = dict(zip(vec.cat.categories, colors, strict=False)) color_dict.update({np.nan: "#808080ff"}) @@ -224,7 +231,7 @@ def _(self, vec: pd.Series, **kwargs: Any) -> dict[str, Any]: df = layer.metadata["_columns_df"] if vec_color_name not in df.columns: colorer = AnnData(shape=(len(vec), 0), obs=pd.DataFrame(index=vec.index, data={"vec": vec})) - _set_colors_for_categorical_obs(colorer, "vec", palette="tab20") + set_colors_for_categorical_obs(colorer, "vec", palette="tab20") colors = colorer.uns["vec_colors"] color_dict = dict(zip(vec.cat.categories, colors, strict=False)) color_dict.update({np.nan: "#808080ff"}) diff --git a/tests/conftest.py b/tests/conftest.py index e4f46808..9329ad51 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,15 @@ from __future__ import annotations +# MUST set environment variables BEFORE any Qt/napari/vispy imports +# to enable headless mode in CI environments (Ubuntu/Linux without display) import os +import sys + +# Only use offscreen on Linux - macOS doesn't support the offscreen Qt platform plugin +if sys.platform == "linux": + os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") + +os.environ.setdefault("NAPARI_HEADLESS", "1") import random import string from abc import ABC, ABCMeta