scverse / scverse/spatialdata

Writing multiscale element to disk fails when configuring Dask to uses "processes"

Open
#1,024 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
394
Forks
95
Avg merge
4d 3h
Merged PRs (30d)
7

Description

When configuring dask to use "processes" instead of "threads", writing a multiscale element to disk fails. I get the error message:

File ~/VIB/harpy/.venv_harpy/lib/python3.12/site-packages/spatialdata/_core/spatialdata.py:1177, in SpatialData.write(self, file_path, overwrite, consolidate_metadata, update_sdata_path, sdata_formats)
   1174 store.close()
   1176 for element_type, element_name, element in self.gen_elements():
-> 1177     self._write_element(
   1178         element=element,
   1179         zarr_container_path=file_path,
...
--> 120 if group.metadata.zarr_format == 3 and len(multiscales := group.metadata.attributes["ome"]["multiscales"]) != 1:
    121     len_scales = len(multiscales)
    122     raise ValueError(f"The length of multiscales metadata should be 1, found the length to be {len_scales}")

KeyError: 'ome'

Minimal example to reproduce:

import os
from spatialdata.models import Image2DModel

from spatialdata.datasets import blobs

import dask

with dask.config.set(scheduler='processes'):

    sdata = blobs()
    sdata=sdata.subset( element_names=[ "blobs_image" ] )
    sdata.write(os.path.join( os.environ.get("TMPDIR"), "sdata.zarr" ), overwrite=True   ) # this works
    print( "done" )

    sdata = blobs()
    sdata=sdata.subset( element_names=[ "blobs_multiscale_image" ] )
    sdata.write(os.path.join( os.environ.get("TMPDIR"), "sdata.zarr" ), overwrite=True   )
# this fails with
#--> 120 if group.metadata.zarr_format == 3 and len(multiscales := group.metadata.attributes["ome"]["multiscales"]) != 1:
#    121     len_scales = len(multiscales)
#    122     raise ValueError(f"The length of multiscales metadata should be 1, found the length to be {len_scales}")

#KeyError: 'ome'

with dask.config.set(scheduler='threads'):

    sdata = blobs()
    sdata=sdata.subset( element_names=[ "blobs_image" ] )
    sdata.write(os.path.join( os.environ.get("TMPDIR"), "sdata.zarr" ), overwrite=True   )
    print( "done" )

    sdata = blobs()
    sdata=sdata.subset( element_names=[ "blobs_multiscale_image" ] )
    sdata.write(os.path.join( os.environ.get("TMPDIR"), "sdata.zarr" ), overwrite=True   )
    print("done")

I tested this on MacOS and CentOS, and got the same error message.

Working with spatialdata==0.6.0, spatial_image==1.2.3 and multiscale_spatial_image==2.0.3.

I also noticed, for images and labes, that the layer in the dask graph that starts with "from-zarr-" is no longer materialized when the spatialdata object is backed by a zarr store (zarr>=3). Probably this is unrelated to the current issue, but I found this a bit strange, since this was not the case in earlier versions of spatialdata(<0.5.0), see https://github.com/saeyslab/harpy/blob/609d639c7578a4c64c3eede4c974d4e90f982910/src/harpy/_tests/test_image/test_manager.py#L47

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the failure with the provided blobs() examples and Dask's processes scheduler, then inspect spatialdata/_core/spatialdata.py around SpatialData.write and the reported metadata check near line 120. Compare the processes and threads execution paths for multiscale images; done means the multiscale element writes successfully under processes without the KeyError, with regression coverage for the reproduced case.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.