vitessce / vitessce-python

Python API and Jupyter widget for Vitessce
https://vitessce.github.io/vitessce-python/
MIT License
35 stars 6 forks source link

Creating a configuration with multiple OME-Zarr using `MultiImageWrapper` fails #242

Open NHPatterson opened 1 year ago

NHPatterson commented 1 year ago

Hi all. Ran into a small issue trying to create a config with 2 OME-Zarrs (i'm using latest version on pypi). My code that worked for multiple OME-TIFFs doesn't work.

AttributeError with MultiImageWrapper with OmeZarrWrapper

import json

from vitessce import (
    Component as cm,
)
from vitessce import (
    MultiImageWrapper,
    OmeZarrWrapper,
    VitessceConfig,
)

vc = VitessceConfig(
    schema_version="1.0.15",
    name="example",
    description="example",
)

dataset = vc.add_dataset(name="Cells").add_object(
    MultiImageWrapper(
        image_wrappers=[
            OmeZarrWrapper(
                img_url="https://vitessce-data.storage.googleapis.com/0.0.33/main/human-lymph-node-10x-visium/human_lymph_node_10x_visium.ome.zarr",
                name="m2",
            ),
            OmeZarrWrapper(
                img_url="https://vitessce-data.storage.googleapis.com/0.0.33/main/human-lymph-node-10x-visium/human_lymph_node_10x_visium.ome.zarr",
                name="m1",
            ),
        ]
    )
)

spatial = vc.add_view(cm.SPATIAL, dataset=dataset)
lc = vc.add_view(cm.LAYER_CONTROLLER, dataset=dataset).set_props(
    disableChannelsIfRgbDetected=True
)

vc.layout(spatial | lc)

vc.to_dict()

Error traceback

Traceback (most recent call last):
  File "/Users/nhp/opt/miniconda3/envs/im-otf/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3378, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-9-55aaff81fab9>", line 41, in <module>
    vc.to_dict()
  File "/Users/nhp/opt/miniconda3/envs/im-otf/lib/python3.9/site-packages/vitessce/config.py", line 922, in to_dict
    "datasets": [d.to_dict(base_url) for d in self.config["datasets"]],
  File "/Users/nhp/opt/miniconda3/envs/im-otf/lib/python3.9/site-packages/vitessce/config.py", line 922, in <listcomp>
    "datasets": [d.to_dict(base_url) for d in self.config["datasets"]],
  File "/Users/nhp/opt/miniconda3/envs/im-otf/lib/python3.9/site-packages/vitessce/config.py", line 217, in to_dict
    obj_file_defs += obj.get_file_defs(base_url)
  File "/Users/nhp/opt/miniconda3/envs/im-otf/lib/python3.9/site-packages/vitessce/wrappers.py", line 77, in get_file_defs
    file_def = file_def_creator(base_url)
  File "/Users/nhp/opt/miniconda3/envs/im-otf/lib/python3.9/site-packages/vitessce/wrappers.py", line 196, in raster_file_def_creator
    image_json = image.make_image_def(dataset_uid, obj_i, base_url)
AttributeError: 'OmeZarrWrapper' object has no attribute 'make_image_def'

Adding as objects works but the viewer only shows first OME-Zarr

import json

from vitessce import (
    Component as cm,
)
from vitessce import (
    OmeZarrWrapper,
    VitessceConfig,
)

vc = VitessceConfig(
    schema_version="1.0.15",
    name="example",
    description="example",
)

dataset = (
    vc.add_dataset(name="Cells")
    .add_object(
        OmeZarrWrapper(
            img_url="https://vitessce-data.storage.googleapis.com/0.0.33/main/human-lymph-node-10x-visium/human_lymph_node_10x_visium.ome.zarr",
            name="m2",
        )
    )
    .add_object(
        OmeZarrWrapper(
            img_url="https://vitessce-data.storage.googleapis.com/0.0.33/main/human-lymph-node-10x-visium/human_lymph_node_10x_visium.ome.zarr",
            name="m1",
        )
    )
)

spatial = vc.add_view(cm.SPATIAL, dataset=dataset)
lc = vc.add_view(cm.LAYER_CONTROLLER, dataset=dataset).set_props(
    disableChannelsIfRgbDetected=True
)

vc.layout(spatial | lc)

vc.to_dict()

json.dump(
    vc.to_dict(),
    open(
        "example_vit_nomultiimage.json",
        "w",
    ),
    indent=1,
)

Config output

{
 "version": "1.0.15",
 "name": "example",
 "description": "example",
 "datasets": [
  {
   "uid": "A",
   "name": "Cells",
   "files": [
    {
     "fileType": "image.ome-zarr",
     "url": "https://vitessce-data.storage.googleapis.com/0.0.33/main/human-lymph-node-10x-visium/human_lymph_node_10x_visium.ome.zarr"
    },
    {
     "fileType": "image.ome-zarr",
     "url": "https://vitessce-data.storage.googleapis.com/0.0.33/main/human-lymph-node-10x-visium/human_lymph_node_10x_visium.ome.zarr"
    }
   ]
  }
 ],
 "coordinationSpace": {
  "dataset": {
   "A": "A"
  }
 },
 "layout": [
  {
   "component": "spatial",
   "coordinationScopes": {
    "dataset": "A"
   },
   "x": 0.0,
   "y": 0,
   "w": 6.0,
   "h": 12
  },
  {
   "component": "layerController",
   "coordinationScopes": {
    "dataset": "A"
   },
   "x": 6.0,
   "y": 0,
   "w": 6.0,
   "h": 12,
   "props": {
    "disableChannelsIfRgbDetected": true
   }
  }
 ],
 "initStrategy": "auto"
}

Maybe there's another routine to get a config with multiple OME-Zarrs?

Thanks!

keller-mark commented 1 year ago

Hi @NHPatterson - apologies for the delay. It is not a bug, when i added support for image.ome-zarr I did not initially implement a way to view multiple, with the intention to do so in a future update (using a different mechanism than the current image.raster.json), but that has taken me longer than expected. I just added more background here https://github.com/vitessce/vitessce/discussions/1502 about working on a solution to this that can be implemented more quickly.

NHPatterson commented 1 year ago

No worries, I see. I did manage to hack ome-zarr to the image.raster.json but it misses some features like correct scaling but it seems you have bigger solution planned that'll probably take care of it.

For reference:

      case ('ome-zarr'): {
      const loader = await viv.loadOmeZarr(url, { type: "multiscales" });
      const Channels = loader.metadata.omero.channels.map(channel => channel);
      const channels = Array.isArray(Channels)
        ? Channels.map((channel, i) => channel.label || `Channel ${i}`)
        : [Channels.label || `Channel ${0}`];
      return { ...loader, channels};