Skip to content

Commit 173495f

Browse files
author
Sonja Stockhaus
committed
uniform color handling between labels and points/shapes
1 parent d22d3b8 commit 173495f

4 files changed

Lines changed: 49 additions & 27 deletions

File tree

‎src/spatialdata_plot/pl/basic.py‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ def render_labels(
598598
norm: Normalize | None = None,
599599
na_color: ColorLike | None = "default",
600600
outline_alpha: float | int = 0.0,
601-
fill_alpha: float | int = 0.4,
601+
fill_alpha: float | int | None = None,
602602
scale: str | None = None,
603603
table_name: str | None = None,
604604
table_layer: str | None = None,
@@ -643,8 +643,9 @@ def render_labels(
643643
won't be shown.
644644
outline_alpha : float | int, default 0.0
645645
Alpha value for the outline of the labels. Invisible by default.
646-
fill_alpha : float | int, default 0.4
647-
Alpha value for the fill of the labels.
646+
fill_alpha : float | int, optional.
647+
Alpha value for the fill of the labels. When no alpha is implied by the passed color, a default value of 0.4
648+
is used.
648649
scale : str | None
649650
Influences the resolution of the rendering. Possibilities for setting this parameter:
650651
1) None (default). The image is rasterized to fit the canvas size. For multiscale images, the best scale
@@ -702,6 +703,7 @@ def render_labels(
702703
sdata.plotting_tree[f"{n_steps + 1}_render_labels"] = LabelsRenderParams(
703704
element=element,
704705
color=param_values["color"],
706+
col_for_color=param_values["col_for_color"],
705707
groups=param_values["groups"],
706708
contour_px=param_values["contour_px"],
707709
cmap_params=cmap_params,
@@ -984,13 +986,13 @@ def show(
984986

985987
if wanted_labels_on_this_cs:
986988
if (table := params_copy.table_name) is not None:
987-
assert isinstance(params_copy.color, str)
988-
colors = sc.get.obs_df(sdata[table], [params_copy.color])
989-
if isinstance(colors[params_copy.color].dtype, pd.CategoricalDtype):
989+
assert isinstance(params_copy.col_for_color, str)
990+
colors = sc.get.obs_df(sdata[table], [params_copy.col_for_color])
991+
if isinstance(colors[params_copy.col_for_color].dtype, pd.CategoricalDtype):
990992
_maybe_set_colors(
991993
source=sdata[table],
992994
target=sdata[table],
993-
key=params_copy.color,
995+
key=params_copy.col_for_color,
994996
palette=params_copy.palette,
995997
)
996998

‎src/spatialdata_plot/pl/render.py‎

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,8 @@ def _render_labels(
10841084
table_name = render_params.table_name
10851085
table_layer = render_params.table_layer
10861086
palette = render_params.palette
1087-
color = render_params.color
1087+
color = render_params.color.get_hex() if render_params.color else None
1088+
col_for_color = render_params.col_for_color
10881089
groups = render_params.groups
10891090
scale = render_params.scale
10901091

@@ -1137,18 +1138,21 @@ def _render_labels(
11371138
sdata=sdata_filt,
11381139
element=label,
11391140
element_name=element,
1140-
value_to_plot=color,
1141+
# value_to_plot=color, # TODO
1142+
value_to_plot=col_for_color,
11411143
groups=groups,
11421144
palette=palette,
1143-
na_color=render_params.cmap_params.na_color,
1145+
# na_color=render_params.cmap_params.na_color, # TODO
1146+
na_color=render_params.color if render_params.color is not None else render_params.cmap_params.na_color,
11441147
cmap_params=render_params.cmap_params,
11451148
table_name=table_name,
11461149
table_layer=table_layer,
1150+
render_type="labels",
11471151
)
11481152

11491153
# rasterize could have removed labels from label
11501154
# only problematic if color is specified
1151-
if rasterize and color is not None:
1155+
if rasterize and (color is not None or col_for_color is not None):
11521156
labels_in_rasterized_image = np.unique(label.values)
11531157
mask = np.isin(instance_id, labels_in_rasterized_image)
11541158
instance_id = instance_id[mask]
@@ -1157,8 +1161,8 @@ def _render_labels(
11571161
color_vector = color_vector.remove_unused_categories()
11581162
assert color_source_vector is not None
11591163
color_source_vector = color_source_vector[mask]
1160-
else:
1161-
assert color_source_vector is None
1164+
# else:
1165+
# assert color_source_vector is None # TODO: delete?
11621166

11631167
def _draw_labels(seg_erosionpx: int | None, seg_boundaries: bool, alpha: float) -> matplotlib.image.AxesImage:
11641168
labels = _map_color_seg(
@@ -1228,7 +1232,8 @@ def _draw_labels(seg_erosionpx: int | None, seg_boundaries: bool, alpha: float)
12281232
cax=cax,
12291233
fig_params=fig_params,
12301234
adata=table,
1231-
value_to_plot=color,
1235+
# value_to_plot=color, # TODO
1236+
value_to_plot=col_for_color,
12321237
color_source_vector=color_source_vector,
12331238
color_vector=color_vector,
12341239
palette=palette,

‎src/spatialdata_plot/pl/render_params.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,8 @@ class LabelsRenderParams:
254254

255255
cmap_params: CmapParams
256256
element: str
257-
color: str | None = None
257+
color: Color | None = None
258+
col_for_color: str | None = None
258259
groups: str | list[str] | None = None
259260
contour_px: int | None = None
260261
outline: bool = False

‎src/spatialdata_plot/pl/utils.py‎

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -777,10 +777,11 @@ def _set_color_source_vec(
777777
alpha: float = 1.0,
778778
table_name: str | None = None,
779779
table_layer: str | None = None,
780-
render_type: Literal["points"] | None = None,
780+
render_type: Literal["points", "labels"] | None = None,
781781
) -> tuple[ArrayLike | pd.Series | None, ArrayLike, bool]:
782782
if value_to_plot is None and element is not None:
783-
color = np.full(len(element), na_color.get_hex_with_alpha())
783+
n_elements = len(element) if render_type != "labels" else len(dask.array.unique(element.data).compute())
784+
color = np.full(n_elements, na_color.get_hex_with_alpha())
784785
return color, color, False
785786

786787
# Figure out where to get the color from
@@ -1000,7 +1001,7 @@ def _get_categorical_color_mapping(
10001001
alpha: float = 1,
10011002
groups: list[str] | str | None = None,
10021003
palette: list[str] | str | None = None,
1003-
render_type: Literal["points"] | None = None,
1004+
render_type: Literal["points", "labels"] | None = None,
10041005
) -> Mapping[str, str]:
10051006
if not isinstance(color_source_vector, Categorical):
10061007
raise TypeError(f"Expected `categories` to be a `Categorical`, but got {type(color_source_vector).__name__}")
@@ -1648,15 +1649,15 @@ def _type_check_params(param_dict: dict[str, Any], element_type: str) -> dict[st
16481649
}:
16491650
if not isinstance(color, str | tuple | list):
16501651
raise TypeError("Parameter 'color' must be a string or a tuple/list of floats.")
1651-
if element_type in {"shapes", "points"}:
1652+
if element_type in {"shapes", "points", "labels"}:
16521653
if _is_color_like(color):
16531654
logger.info("Value for parameter 'color' appears to be a color, using it as such.")
16541655
param_dict["col_for_color"] = None
16551656
param_dict["color"] = Color(color)
16561657
if param_dict["color"].alpha_is_user_defined():
16571658
if element_type == "points" and param_dict.get("alpha") is None:
16581659
param_dict["alpha"] = param_dict["color"].get_alpha_as_float()
1659-
elif element_type == "shapes" and param_dict.get("fill_alpha") is None:
1660+
elif element_type in ["shapes", "labels"] and param_dict.get("fill_alpha") is None:
16601661
param_dict["fill_alpha"] = param_dict["color"].get_alpha_as_float()
16611662
else:
16621663
logger.info(
@@ -1668,7 +1669,7 @@ def _type_check_params(param_dict: dict[str, Any], element_type: str) -> dict[st
16681669
param_dict["color"] = None
16691670
else:
16701671
raise ValueError(f"{color} is not a valid RGB(A) array and therefore can't be used as 'color' value.")
1671-
elif "color" in param_dict and element_type != "labels":
1672+
elif "color" in param_dict and element_type != "images":
16721673
param_dict["col_for_color"] = None
16731674

16741675
if outline_width := param_dict.get("outline_width"):
@@ -1754,6 +1755,8 @@ def _type_check_params(param_dict: dict[str, Any], element_type: str) -> dict[st
17541755
elif element_type == "shapes":
17551756
# set default fill_alpha for shapes if not given by user explicitly or implicitly (as part of color)
17561757
param_dict["fill_alpha"] = 1.0
1758+
elif element_type == "lables":
1759+
param_dict["fill_alpha"] = 0.4
17571760

17581761
if (cmap := param_dict.get("cmap")) is not None and (palette := param_dict.get("palette")) is not None:
17591762
raise ValueError("Both `palette` and `cmap` are specified. Please specify only one of them.")
@@ -1894,7 +1897,7 @@ def _validate_label_render_params(
18941897
element: str | None,
18951898
cmap: list[Colormap | str] | Colormap | str | None,
18961899
color: str | None,
1897-
fill_alpha: float | int,
1900+
fill_alpha: float | int | None,
18981901
contour_px: int | None,
18991902
groups: list[str] | str | None,
19001903
palette: list[str] | str | None,
@@ -1939,12 +1942,23 @@ def _validate_label_render_params(
19391942
element_params[el]["table_layer"] = param_dict["table_layer"]
19401943

19411944
element_params[el]["table_name"] = None
1942-
element_params[el]["color"] = None
1943-
color = param_dict["color"]
1944-
if color is not None:
1945-
color, table_name = _validate_col_for_column_table(sdata, el, color, param_dict["table_name"], labels=True)
1945+
1946+
# element_params[el]["color"] = None # TODO: delete
1947+
# color = param_dict["color"]
1948+
# if color is not None:
1949+
# color, table_name = _validate_col_for_column_table(sdata, el, color, param_dict["table_name"],
1950+
# labels=True)
1951+
# element_params[el]["table_name"] = table_name
1952+
# element_params[el]["color"] = color
1953+
element_params[el]["color"] = param_dict["color"]
1954+
1955+
element_params[el]["col_for_color"] = None
1956+
if (col_for_color := param_dict["col_for_color"]) is not None:
1957+
col_for_color, table_name = _validate_col_for_column_table(
1958+
sdata, el, col_for_color, param_dict["table_name"], labels=True
1959+
)
19461960
element_params[el]["table_name"] = table_name
1947-
element_params[el]["color"] = color
1961+
element_params[el]["col_for_color"] = col_for_color
19481962

19491963
element_params[el]["palette"] = param_dict["palette"] if element_params[el]["table_name"] is not None else None
19501964
element_params[el]["groups"] = param_dict["groups"] if element_params[el]["table_name"] is not None else None

0 commit comments

Comments
 (0)