Open camFoltz opened 2 years ago
I have the same issue. We load many OME-Zarr files which specify a channel's color like cm = [[0, 0, 0], [1.0, 0.0, 0.0]]
. For each of them, a new Vispy Colormap
instance is created. Since they are unnamed, Napari treated all of them as separate, unique color maps.
A first, obvious fix was to give the colormap a name (name=str(cm)
), but Vispy's colormaps have no name attribute.
After importing Napari's Colormap which has a name attribute, Napari matches all the Colormap instances by name and displays a single one in the user interface. Still, this is not the right approach: The UI only displays a single colormap because of key collision, but layers keep their separate Colormap instances (with same names).
We would need to lookup whether there already exists a suitable colormap instance (like from Napari's AVAILABLE_COLORMAPS
) and re-use it or create a new one and register it.
It could be possible to compare color values coming from OME-NGFF metadata with those in existing napari colormaps and if there's a match, then use the napari colormap name instead:
https://napari.org/stable/howtos/layers/image.html#working-with-colormaps
It might also be permissible to use the name of the colormap in the omero
channel color
string (as we do in OMERO itself for lookup tables).
When we first look up existing colormap instances, we can avoid creating new identical ones.
If the OME-Zarr colormap is a name (string), one can try to look it up from Napari colormaps (how to handle it if not found?). If it is instead a tuple of two RGB colors, create a new Napari colormap. Since Napari will register it, we can look it up next time.
from vispy.color import Colormap as VispyColormap
from napari.utils.colormaps.colormap import Colormap as NapariColormap
from napari.utils.colormaps import AVAILABLE_COLORMAPS
cms = metadata.get("colormap", [])
for idx, cm in enumerate(cms):
if not isinstance(cm, (VispyColormap, NapariColormap)):
if isinstance(cm, str):
cms[idx] = AVAILABLE_COLORMAPS.get(cm)
# TODO: How to handle this? We have a colormap name not know in Napari,
# are there cases when we can still create a color map?
else:
colormap_name = f"color {cm}"
colormap = AVAILABLE_COLORMAPS.get(colormap_name)
if colormap is None:
colormap = NapariColormap(cm, name=colormap_name)
cms[idx] = colormap
Hi.
I've come across this issue myself and wasn't clear if there is a fix, or if this issue is due to me writing metadata incorrectly. Was hoping you could help.
I have written my high plex multichannel data to OME-ZARR format with ome-zarr-py
package write_image
function. I specify channel metadata under OMERO metadata, including each channel color
to be "FFFFFF".
On loading to napari via napari-ome-zarr, channel names and render settings load correctly. But each channel spawns its own version of 'unnamed colormap [##]'
Looking for a way to have every channel just load with the napari 'gray' colormap?
I am noticing that the OME-Zarr specifications have an option to have a "color" properties within the channel metadata. We use this property do define the colormap for when
napari-ome-zarr
opens up the dataset. However, it seems that doing this creates a ton of new colormaps within Napari with the titleunnamed
, and doesn't actually use a napari colormap.Is there a way to define metadata such that we use napari's inherent colormaps? I see that the
_reader.py
looks for a metadata key calledcolormap
which gets converted to a vispy colormap, but I am not entirely sure how to include this in the ome metadata within the zarr file or if this vispy colormap will correspond to one of napari's inherent maps and not create a new 'unnamed' one.Let me know if I can clarify anything here. Thanks for the help