spatialdata-plot icon indicating copy to clipboard operation
spatialdata-plot copied to clipboard

pl.render_shapes do not support normal hex color

Open wangjiawen2013 opened this issue 1 year ago • 5 comments

Hi, An normal hex color is a string include seven chars, such as "#DD4958", but pl.render_shapes uses nine chars when using datashader, which is not compatible with palette in stored in sdata["table"].uns["leiden_colors"]: Image

This is my palette: ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b'] So ian error occurred when using customized palette: Image

wangjiawen2013 avatar Nov 29 '24 10:11 wangjiawen2013

Besides, I must run sdata.pl.render_shapes without groups and palette first , then run sdata.pl.render_shapes with groups and palette for the second time. If I run sdata.pl.render_shapes with groups and palette directly, this error will occur:

Image

wangjiawen2013 avatar Dec 02 '24 08:12 wangjiawen2013

Another question, we can only set groups as one "string" or all the categories. Such as if we have "0", "1", "2", "3", "4", "5" categories, we can only set groups="3" or groups=["0", "1","2","3","4","5"], we cannot set groups=["1","2"] and so on.

wangjiawen2013 avatar Dec 02 '24 08:12 wangjiawen2013

Thanks for reporting. It seems to be related to https://github.com/scverse/spatialdata-plot/issues/375. @timtreis any take?

LucaMarconato avatar Jan 05 '25 22:01 LucaMarconato

hm, odd. Will investigate

timtreis avatar Jan 07 '25 13:01 timtreis

The same issue persists. Besides that, why is it mandatory to specify groups when providing a palette? This restriction prevents me from customizing cell group colors freely, which is very inconvenient.

palette
['#F4A582', '#0571B0', '#CA0020', '#92C5DE', '#7BAFDE', '#BBD0DE']
sdata.pl.render_images("he_image").pl.render_shapes(
    "cell_boundaries",
    color="coarse_celltype_level1",
    method="datashader",
    groups=sdata["table"].obs['coarse_celltype_level1'].cat.categories.tolist(),
    palette=palette
).pl.show(title="Lineage expression over H&E image", coordinate_systems="global", figsize=(10, 5))
File /rsrch8/scratch/genomic_med/tchu1/conda/envs/st-python/lib/python3.10/site-packages/spatialdata_plot/pl/basic.py:937, in PlotAccessor.show(self, coordinate_systems, legend_fontsize, legend_fontweight, legend_loc, legend_fontoutline, na_in_legend, colorbar, wspace, hspace, ncols, frameon, figsize, dpi, fig, title, share_extent, pad_extent, ax, return_ax, save)
    932     wanted_elements, wanted_shapes_on_this_cs, wants_shapes = _get_wanted_render_elements(
    933         sdata, wanted_elements, params_copy, cs, "shapes"
    934     )
    936     if wanted_shapes_on_this_cs:
--> 937         _render_shapes(
    938             sdata=sdata,
    939             render_params=params_copy,
    940             coordinate_system=cs,
    941             ax=ax,
    942             fig_params=fig_params,
    943             scalebar_params=scalebar_params,
    944             legend_params=legend_params,
    945         )
    947 elif cmd == "render_points" and has_points:
    948     wanted_elements, wanted_points_on_this_cs, wants_points = _get_wanted_render_elements(
    949         sdata, wanted_elements, params_copy, cs, "points"
    950     )

File /rsrch8/scratch/genomic_med/tchu1/conda/envs/st-python/lib/python3.10/site-packages/spatialdata_plot/pl/render.py:259, in _render_shapes(sdata, render_params, coordinate_system, ax, fig_params, scalebar_params, legend_params)
    256         if isinstance(ds_cmap, str) and ds_cmap[0] == "#":
    257             ds_cmap = ds_cmap[:-2]
--> 259     ds_result = ds.tf.shade(
    260         agg,
    261         cmap=ds_cmap,
    262         color_key=color_key,
    263         min_alpha=np.min([254, render_params.fill_alpha * 255]),
    264         how="linear",
    265     )
    266 elif aggregate_with_reduction is not None:  # to shut up mypy
    267     ds_cmap = render_params.cmap_params.cmap

File /rsrch8/scratch/genomic_med/tchu1/conda/envs/st-python/lib/python3.10/site-packages/datashader/transfer_functions/__init__.py:720, in shade(agg, cmap, color_key, how, alpha, min_alpha, span, name, color_baseline, rescale_discrete_levels)
    717         return _interpolate(agg, cmap, how, alpha, span, min_alpha, name,
    718                             rescale_discrete_levels)
    719 elif agg.ndim == 3:
--> 720     return _colorize(agg, color_key, how, alpha, span, min_alpha, name, color_baseline,
    721                      rescale_discrete_levels)
    722 else:
    723     raise ValueError("agg must use 2D or 3D coordinates")

File /rsrch8/scratch/genomic_med/tchu1/conda/envs/st-python/lib/python3.10/site-packages/datashader/transfer_functions/__init__.py:378, in _colorize(agg, color_key, how, alpha, span, min_alpha, name, color_baseline, rescale_discrete_levels)
    374 if len(color_key) < len(cats):
    375     raise ValueError(f"Insufficient colors provided ({len(color_key)}) for the categorical "
    376                      f"fields available ({len(cats)})")
--> 378 colors = [rgb(color_key[c]) for c in cats]
    379 rs, gs, bs = map(array, zip(*colors))
    381 # Reorient array (transposing the category dimension first)

File /rsrch8/scratch/genomic_med/tchu1/conda/envs/st-python/lib/python3.10/site-packages/datashader/transfer_functions/__init__.py:378, in <listcomp>(.0)
    374 if len(color_key) < len(cats):
    375     raise ValueError(f"Insufficient colors provided ({len(color_key)}) for the categorical "
    376                      f"fields available ({len(cats)})")
--> 378 colors = [rgb(color_key[c]) for c in cats]
    379 rs, gs, bs = map(array, zip(*colors))
    381 # Reorient array (transposing the category dimension first)

File /rsrch8/scratch/genomic_med/tchu1/conda/envs/st-python/lib/python3.10/site-packages/datashader/colors.py:116, in rgb(x)
    114 if isinstance(x, str):
    115     if x.startswith('#'):
--> 116         return hex_to_rgb(x)
    117     elif x in color_lookup:
    118         return hex_to_rgb(color_lookup[x])

File /rsrch8/scratch/genomic_med/tchu1/conda/envs/st-python/lib/python3.10/site-packages/datashader/colors.py:91, in hex_to_rgb(x)
     83 """Convert a color hexcode to an rgb tuple.
     84 
     85 Example
   (...)
     88 (255, 255, 255)
     89 """
     90 if not (x.startswith('#') and len(x) == 7):
---> 91     raise ValueError("Invalid hex color")
     92 x = x.strip('#')
     93 try:

ValueError: Invalid hex color

@LucaMarconato @timtreis

christophechu avatar Feb 14 '25 21:02 christophechu