# New extension: OMEZarr - open OME-Zarr images directly in Slicer

**URL:** https://discourse.slicer.org/t/new-extension-omezarr-open-ome-zarr-images-directly-in-slicer/48238
**Category:** Development
**Tags:** feature, microscopy, file-export, file-import, extensions
**Created:** [September 23, 2026, 8:54am UTC](https://discourse.slicer.org/t/new-extension-omezarr-open-ome-zarr-images-directly-in-slicer/48238 "2026-09-23T08:54:19Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![vboussot](https://avatars.discourse-cdn.com/v4/letter/v/839c29/32.png) [@vboussot](https://discourse.slicer.org/u/vboussot)
#### Post date: [September 23, 2026, 8:54am UTC](https://discourse.slicer.org/t/new-extension-omezarr-open-ome-zarr-images-directly-in-slicer/48238/1 "2026-09-23T08:54:19Z")

</div>

Hi all,

We’re happy to announce **OMEZarr** , a new extension from [Fideus Labs](https://fideus.io/) that opens and saves OME-Zarr images. It is available in the Extensions Manager for Slicer 5.12.4 and the Preview release, on Linux, macOS and Windows.

OME-Zarr is a format increasingly used for large microscopy datasets: a folder of compressed chunks at several resolutions, stored on disk, on a web server or in the cloud. Until now, looking at one in Slicer meant converting it to NRRD or NIfTI first. Now you can:

- **Drag an `.ome.zarr` folder onto Slicer** , or open an `https://` or `s3://` address. No conversion.
- **Open datasets larger than RAM** and progressively refine the views at full resolution, or load a region of interest at any level.
- **Work with regular Slicer nodes.** Channels become volumes with their names and colours, labels become label maps or segmentations, time series become sequences. Segment Editor, registration and volume rendering work as usual.
- **Get the geometry right.** Spacing and units (µm, nm) are converted to mm, and the RFC-4 anatomical orientation becomes the IJK-to-RAS matrix.
- **Save back to OME-Zarr.** Volumes, label maps and segmentations are written as multiscale OME-Zarr, so the results open in napari, Fiji or Python.

Reading and writing go through [ngff-zarr](https://github.com/fideus-labs/ngff-zarr), which we maintain.

The video is recorded on a public two-photon image of GFP-labelled neurons in a marmoset cortex, streamed from S3. To try it right away, paste this in the Python console:

```python
slicer.util.loadNodeFromFile("s3://ome-zarr-scivis/v0.5/96x2/marmoset_neurons.ome.zarr", "OMEZarr")

```

Code and step-by-step tutorial: [GitHub - fideus-labs/SlicerOMEZarr: 3D Slicer extension to open OME-Zarr (OME-NGFF) images, built on ngff-zarr · GitHub](https://github.com/fideus-labs/SlicerOMEZarr)

Please give it a go and tell us what breaks, especially with your own datasets. Thanks to @lassoan for reviewing the extension and for the helpful feedback.

---

<div class="post-metadata">

### Author: ![muratmaga](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/muratmaga/32/3622_2.png) [@muratmaga](https://discourse.slicer.org/u/muratmaga)
#### Post date: [September 23, 2026, 4:07pm UTC](https://discourse.slicer.org/t/new-extension-omezarr-open-ome-zarr-images-directly-in-slicer/48238/2 "2026-09-23T16:07:15Z")

</div>

I am quite excited about this, thanks for implementing the ome-zarr support. When I tried the extension with you example on MacOS (5.12.4)

```auto
>>> slicer.util.loadNodeFromFile("s3://ome-zarr-scivis/v0.5/96x2/marmoset_neurons.ome.zarr", "OMEZarr")

Traceback (most recent call last):

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/_remote_reader.py", line 498, in open_remote_node

    arr = _run(lambda: AsyncArray.open(store._store, path))

          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/_remote_reader.py", line 100, in _run

    return asyncio.run_coroutine_threadsafe(_invoke(), _io_loop()).result()

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/concurrent/futures/_base.py", line 456, in result

    return self.__get_result()

           ^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result

    raise self._exception

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/_remote_reader.py", line 98, in _invoke

    return await factory()

           ^^^^^^^^^^^^^^^

zarrista.exceptions.ArrayCreateError: Generic S3 error: Error performing PUT http://169.254.169.254/latest/api/token in 2.635813709s, after 10 retries, max_retries: 10, retry_timeout: 180s - HTTP error: error sending request

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

  File "/Applications/Slicer.app/Contents/Extensions-34645/OMEZarr/lib/Slicer-5.12/qt-scripted-modules/OMEZarr.py", line 1575, in load

    nodes = OMEZarrLogic.loadImage(

            ^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/Extensions-34645/OMEZarr/lib/Slicer-5.12/qt-scripted-modules/OMEZarr.py", line 763, in loadImage

    multiscales = multiscales or cls.openMultiscales(path)

                                 ^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/Extensions-34645/OMEZarr/lib/Slicer-5.12/qt-scripted-modules/OMEZarr.py", line 378, in openMultiscales

    ngff_zarr.from_ome_zarr(source, storage_options=options) if options else ngff_zarr.from_ome_zarr(source)

                                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/from_ngff_zarr.py", line 264, in from_ome_zarr

    root = _open_root_node(store, version)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/from_ngff_zarr.py", line 158, in _open_root_node

    return _open_remote_root(store, version)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/from_ngff_zarr.py", line 141, in _open_remote_root

    node = open_remote_node(store)

           ^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/_remote_reader.py", line 504, in open_remote_node

    raise group_error from array_error

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/_remote_reader.py", line 493, in open_remote_node

    group = _run(lambda: AsyncGroup.open(store._store, path))

            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/_remote_reader.py", line 100, in _run

    return asyncio.run_coroutine_threadsafe(_invoke(), _io_loop()).result()

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/concurrent/futures/_base.py", line 456, in result

    return self.__get_result()

           ^^^^^^^^^^^^^^^^^^^

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result

    raise self._exception

  File "/Applications/Slicer.app/Contents/lib/Python/lib/python3.12/site-packages/ngff_zarr/_remote_reader.py", line 98, in _invoke

    return await factory()

           ^^^^^^^^^^^^^^^

zarrista.exceptions.GroupCreateError: Generic S3 error: Error performing PUT http://169.254.169.254/latest/api/token in 6.812037334s, after 10 retries, max_retries: 10, retry_timeout: 180s - HTTP error: error sending request

Traceback (most recent call last):

  File "<console>", line 1, in <module>

  File "/Applications/Slicer.app/Contents/bin/Python/slicer/util.py", line 913, in loadNodeFromFile

    raise RuntimeError(errorMessage)

RuntimeError: Failed to load node from file: s3://ome-zarr-scivis/v0.5/96x2/marmoset_neurons.ome.zarr

Error: Loading s3://ome-zarr-scivis/v0.5/96x2/marmoset_neurons.ome.zarr - Failed to read OME-Zarr: Generic S3 error: Error performing PUT http://169.254.169.254/latest/api/token in 6.812037334s, after 10 retries, max_retries: 10, retry_timeout: 180s - HTTP error: error sending request

```

---

<div class="post-metadata">

### Author: ![vboussot](https://avatars.discourse-cdn.com/v4/letter/v/839c29/32.png) [@vboussot](https://discourse.slicer.org/u/vboussot)
#### Post date: [September 23, 2026, 4:32pm UTC](https://discourse.slicer.org/t/new-extension-omezarr-open-ome-zarr-images-directly-in-slicer/48238/3 "2026-09-23T16:32:19Z")

</div>

Thanks for the report, the traceback pointed straight at it. The extension treated a `~/.aws/credentials` file as AWS credentials, but the S3 client it uses only reads environment variables, so it ended up asking the EC2 metadata service and failing.

Fixed in [fix: read public S3 stores anonymously even when an AWS credentials f… · fideus-labs/SlicerOMEZarr@eb3cbbf · GitHub](https://github.com/fideus-labs/SlicerOMEZarr/commit/eb3cbbf) , in tomorrow’s extension build. Until then, in the OME-Zarr module go to Settings → Remote storage options, enter `{"anon": true}`, and the example loads.

---

<div class="post-metadata">

### Author: ![muratmaga](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/muratmaga/32/3622_2.png) [@muratmaga](https://discourse.slicer.org/u/muratmaga)
#### Post date: [September 23, 2026, 4:35pm UTC](https://discourse.slicer.org/t/new-extension-omezarr-open-ome-zarr-images-directly-in-slicer/48238/4 "2026-09-23T16:35:24Z")

</div>

I was just about to post it, you beat me to it 🙂

A second suggestion: please consider writing **OME-Zarr 0.6** when a volume has a rotation. Right now the writer uses the 0.5 default, which can only store scale and translation. A volume with a rotated direction matrix, which is common in Slicer after reorienting, is quietly saved axis-aligned, so it no longer lines up with segmentations made on the original. ngff-zarr already supports 0.6 (RFC-5) affines. I tried a small patch locally:

- **Saving:** keep the per-level scale and translation as they are, and add the leftover rotation as an image-level affine, written as 0.6 only when needed.
- **Loading:** apply that affine when building IJK-to-RAS.

With that, an oblique uint16 volume round-trips exactly, and a `.seg.nrrd` made on the original lines up voxel for voxel. I’m happy to send it as a PR if that’s useful.

This extension is important for us. We are evaluating OME-Zarr as the source-volume format for MorphoDepot, so thanks again for putting it together.

---

<div class="post-metadata">

### Author: ![vboussot](https://avatars.discourse-cdn.com/v4/letter/v/839c29/32.png) [@vboussot](https://discourse.slicer.org/u/vboussot)
#### Post date: [September 23, 2026, 4:43pm UTC](https://discourse.slicer.org/t/new-extension-omezarr-open-ome-zarr-images-directly-in-slicer/48238/5 "2026-09-23T16:43:14Z")

</div>

You are right, thanks for checking it. A PR is very welcome. Great to hear about MorphoDepot.

---

<div class="post-metadata">

### Author: ![muratmaga](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/muratmaga/32/3622_2.png) [@muratmaga](https://discourse.slicer.org/u/muratmaga)
#### Post date: [September 23, 2026, 5:23pm UTC](https://discourse.slicer.org/t/new-extension-omezarr-open-ome-zarr-images-directly-in-slicer/48238/6 "2026-09-23T17:23:04Z")

</div>

PR is open [Keep oblique directions by writing an OME-Zarr 0.6 (RFC-5) affine by muratmaga · Pull Request #13 · fideus-labs/SlicerOMEZarr · GitHub](https://github.com/fideus-labs/SlicerOMEZarr/pull/13)
