Giter Club home page Giter Club logo

Comments (6)

manzt avatar manzt commented on June 13, 2024 2

Wow, cool!

How do I make it display in color mode, I guess that has to do with the "omero" key, right? What's the best way to pass that?

Omero key shouldn't be necessary. I believe if you set channel_axis = 0 the colors should work.

Another minor issue is that, if I zoom in too much it becomes blank, can I limit the zoom level?

Hmm I'm not sure about this. I have a PR I'm about to merge upgrading Viv (#126), and I wonder if that would vix the issue. In the run_vizarr function, you can set the url to the netlify deploy preview link and see if the upgrade fixes it.

BTW, would you consider having such feature in napari_lazy_openslide so it can work out of the box?

Yeah, definitely. I wonder if this functionality would be best implemented as a method on the OpenSideStore that returns another class wrapping the store (instead of inheriting the store). E.g.

from napari_lazy_openslide import OpenSlideStore

OpenSlideStore('./data.svs').as_ngff() # returns store transformer

EDIT: Also, @oeway, an as_ngff() method could add the additional axes metadata to the mulitscales metadata so that channel_axis does not need to be provided.

from vizarr.

manzt avatar manzt commented on June 13, 2024

Hi @oeway ! We currently don't support interleaved RGB/A images in the vizarr client. The last two dimensions of an array must be YX. However, we have added support for this in Viv, and I can look into adding that functionality client-side in vizarr.

I'm sorry, but as a work around on the python side, you could wrap the OpenslideStore in another zarr store that performs the translation of (y, x, c) to (c, y, x). You need to proxy requests for .zarray metadata to make the following changes:

  • shape: (y, x, 4) -> (4, y, x)
  • chunks (tilesize, tilesize, 4) -> (1, tilesize, tilesize).

Any zarr client will now request keys in the form "level/c.y.x" from the store. It gets tricky because the chunk shapes are different but in theory (I haven't tested this) it could look like:

from napari_lazy_openslide import OpenSlideStore
from zarr.util import json_dumps, json_loads
import numpy as np

def _parse_chunk_path(path: str):
    """Returns x,y chunk coords and pyramid level from string key"""
    level, ckey = path.split("/")
    c, y, x  = map(int, ckey.split("."))
    return c, x, y, int(level)

class Wrapper(OpenSlideStore):

  def __getitem__(self, key):
    if key in self._store: # metadata store for OpenSlideStore
       # key is for metadata
       res = self._store[key]
       if key.endswith('.zarray'):
         meta = json_loads(res)
         meta.shape = [meta.shape[2], meta.shape[0], meta.shape[1]]
         meta.chunks = [1, meta.chunks[0], meta.chunks[1]]
         return json_dumps(meta)
       else:
         # zgroup
         return res

      cidx, y, x, level = _parse_chunk_path(key)
      buf = store[f"{level}/{y}.{x}.0"] # could cache this result
      arr = np.frombuffer(buf, dtype='uint8').reshape(self.tilesize, self.tilesize, -1)
      data = arr[:, :, cidx] # cou
      return data.tobytes()

It gets a little tricky because the chunk shape of the original array is (tilesize, tilesize, 4) and the zarr array would need to map to (1, tilesize, tilesize).

from vizarr.

oeway avatar oeway commented on June 13, 2024

Hi @manzt Thanks for the detailed explanation!

I started to try the Wrapper code you wrote above, and here is a version with some fix, but still not working:

from napari_lazy_openslide import OpenSlideStore
from zarr.util import json_dumps, json_loads
import numpy as np

def _parse_chunk_path(path: str):
    """Returns x,y chunk coords and pyramid level from string key"""
    level, ckey = path.split("/")
    c, y, x  = map(int, ckey.split("."))
    return c, x, y, int(level)

class Wrapper(OpenSlideStore):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def __getitem__(self, key):
        if key in self._store: # metadata store for OpenSlideStore
            # key is for metadata
            res = self._store[key]
        print(self._store.keys())
        if key.endswith('.zarray'):
            meta = json_loads(res)
            meta["shape"] = [meta["shape"][2], meta["shape"][0], meta["shape"][1]]
            meta["chunks"] = [1, meta["chunks"][0], meta["chunks"][1]]
            return json_dumps(meta)
        elif key.endswith('.zgroup') or key.endswith('.zattrs'):
            # zgroup
            return res
        
        cidx, y, x, level = _parse_chunk_path(key)
        buf = self._store[f"{level}/{y}.{x}.0"] # <-------------------------Is this correct?
        arr = np.frombuffer(buf, dtype='uint8').reshape(self.tilesize, self.tilesize, -1)
        data = arr[:, :, cidx] # cou
        return data.tobytes()

You wrote store[...] in your previous code, I guess you mean self._store?
And the issue now is that the line buf = self._store[f"{level}/{y}.{x}.0"] generates error, for example: KeyError: '7/0.0.0'. And here are the keys in self._store: dict_keys(['.zgroup', '.zattrs', '0/.zarray', '1/.zarray', '2/.zarray', '3/.zarray', '4/.zarray', '5/.zarray', '6/.zarray', '7/.zarray', '8/.zarray', '9/.zarray', '10/.zarray']).

How should I access the array data with f"{level}/{y}.{x}.0" in this case?

from vizarr.

manzt avatar manzt commented on June 13, 2024

You wrote store[...] in your previous code, I guess you mean self._store?

Oh that's my mistake. The code snippet I shared I just typed here as an idea and didn't test at all.

self._store is just a dict containing the zarr metadata. You should call the parent class (OpenSlideStore) __getitem__ method.

def __getitem__(key):
  # ....
  buf = super().__getitem__(f"{level}/{y}.{x}.0")

from vizarr.

oeway avatar oeway commented on June 13, 2024

@manzt Thank you! It's working now! Awesome!
Screen Shot 2022-02-03 at 10 14 10 AM

For others who might be interested in this, here is the working version for me:

import numpy as np
from napari_lazy_openslide import OpenSlideStore
from zarr.util import json_dumps, json_loads

def _parse_chunk_path(path: str):
    """Returns x,y chunk coords and pyramid level from string key"""
    level, ckey = path.split("/")
    c, y, x  = map(int, ckey.split("."))
    return c, x, y, int(level)

class OpenSlideStoreWrapper(OpenSlideStore):

    def __getitem__(self, key):
        if key in self._store: # metadata store for OpenSlideStore
            # key is for metadata
            res = self._store[key]
        if key.endswith('.zarray'):
            meta = json_loads(res)
            meta["shape"] = [meta["shape"][2], meta["shape"][0], meta["shape"][1]]
            meta["chunks"] = [1, meta["chunks"][0], meta["chunks"][1]]
            return json_dumps(meta)
        elif key.endswith('.zgroup') or key.endswith('.zattrs'):
            # zgroup
            return res

        cidx, y, x, level = _parse_chunk_path(key)
        buf = super().__getitem__(f"{level}/{x}.{y}.0") # could cache this result
        arr = np.frombuffer(buf, dtype='uint8').reshape(self._tilesize, self._tilesize, -1)
        data = arr[:, :, cidx] # cou
        return data.tobytes()

How do I make it display in color mode, I guess that has to do with the "omero" key, right? What's the best way to pass that? Another minor issue is that, if I zoom in too much it becomes blank, can I limit the zoom level?

BTW, would you consider having such feature in napari_lazy_openslide so it can work out of the box?

from vizarr.

oeway avatar oeway commented on June 13, 2024

All works now, see a gif below:
ezgif-2-6fc3ab929f

The .as_ngff() method sounds awesome! Looking forward to it!

from vizarr.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.