An experimental plugin to lazily load multiscale whole-slide tiff images with openslide and dask.
This napari plugin was generated with Cookiecutter using with @napari's cookiecutter-napari-plugin template.
Step 1.) Make sure you have OpenSlide installed. Download instructions here.
NOTE: Installation on macOS is easiest via Homebrew:
brew install openslide
. Up-to-date and multiplatform binaries foropenslide
are also avaiable viaconda
:conda install -c sdvillal openslide-python
Step 2.) Install napari-lazy-openslide
via pip
:
pip install napari-lazy-openslide
$ napari tumor_004.tif
By installing this package via pip
, the plugin should be recognized by napari
. The plugin
attempts to read image formats recognized by openslide
that are multiscale
(openslide.OpenSlide.level_count > 1
).
It should be noted that napari-lazy-openslide
is experimental and has primarily
been tested with CAMELYON16
and CAMELYON17
datasets, which can be
downloaded here.
The OpenSlideStore
class wraps an openslide.OpenSlide
object as a valid Zarr store.
The underlying openslide
image pyramid is translated to the Zarr multiscales extension,
where each level of the pyramid is a separate 3D zarr.Array
with shape (y, x, 4)
.
import dask.array as da
import zarr
from napari_lazy_openslide import OpenSlideStore
store = OpenSlideStore('tumor_004.tif')
grp = zarr.open(store, mode="r")
# The OpenSlideStore implements the multiscales extension
# https://forum.image.sc/t/multiscale-arrays-v0-1/37930
datasets = grp.attrs["multiscales"][0]["datasets"]
pyramid = [grp.get(d["path"]) for d in datasets]
print(pyramid)
# [
# <zarr.core.Array '/0' (23705, 29879, 4) uint8 read-only>,
# <zarr.core.Array '/1' (5926, 7469, 4) uint8 read-only>,
# <zarr.core.Array '/2' (2963, 3734, 4) uint8 read-only>,
# ]
pyramid = [da.from_zarr(store, component=d["path"]) for d in datasets]
print(pyramid)
# [
# dask.array<from-zarr, shape=(23705, 29879, 4), dtype=uint8, chunksize=(512, 512, 4), chunktype=numpy.ndarray>,
# dask.array<from-zarr, shape=(5926, 7469, 4), dtype=uint8, chunksize=(512, 512, 4), chunktype=numpy.ndarray>,
# dask.array<from-zarr, shape=(2963, 3734, 4), dtype=uint8, chunksize=(512, 512, 4), chunktype=numpy.ndarray>,
# ]
# Now you can use numpy-like indexing with openslide, reading data into memory lazily!
low_res = pyramid[-1][:]
region = pyramid[0][y_start:y_end, x_start:x_end]
Contributions are very welcome. Tests can be run with tox
, please ensure
the coverage at least stays the same before you submit a pull request.
If you encounter any problems, please file an issue along with a detailed description.