Adding image to same slot for backed sdata
When writing an image to zarr with overwrite=True, I found some unexpected behaviour. Below I give a mimimal example to reproduce the issue.
This works, as expected. I can overwrite image layer 'image'.
import spatialdata
import numpy as np
sdata = spatialdata.SpatialData()
sdata.write( 'sdata.zarr' )
arr=np.random.rand( 1,100,100 )
spatialelement=spatialdata.models.Image2DModel.parse(
arr, dims=[ 'c' ,'y', 'x' ],
)
sdata.add_image( name="image", image=spatialelement , overwrite=True )
sdata.add_image( name="image", image=spatialelement , overwrite=True )
However, when I add some processing (e.g. multiplying by two) before replacing sdata["image" ]:
spatialelement=spatialdata.models.Image2DModel.parse(
sdata[ "image" ].data*2, dims=[ 'c' ,'y', 'x' ],
)
sdata.add_image( name="image", image=spatialelement , overwrite=True )
I get the error:
ValueError Traceback (most recent call last) in SpatialData.add_image(self, name, image, storage_options, overwrite) 659 target_path = os.path.realpath(os.path.join(self.path, "images", name)) 660 if target_path in files: --> 661 raise ValueError( 662 "Cannot add the image to the SpatialData object because it would overwrite an element that it is" 663 "using for backing. See more here: https://github.com/scverse/spatialdata/pull/138" 664 ) 665 self._add_image_in_memory(name=name, image=image, overwrite=overwrite) 666 # old code to support overwriting the backing file 667 # with tempfile.TemporaryDirectory() as tmpdir: 668 # store = parse_url(Path(tmpdir) / "data.zarr", mode="w").store (...) 692 # image = _read_multiscale(str(tgt_element_path), raster_type="image") 693 # self._add_image_in_memory(name=name, image=image, overwrite=True)
ValueError: Cannot add the image to the SpatialData object because it would overwrite an element that it isusing for backing. See more here: https://github.com/scverse/spatialdata/pull/138
However, if I do a persist(), I am allowed to overwrite:
spatialelement=spatialdata.models.Image2DModel.parse(
(sdata[ "image" ].data*2).persist(), dims=[ 'c' ,'y', 'x' ],
)
sdata.add_image( name="image", image=spatialelement , overwrite=True )
And I am also allowed to do this (typical scenario where you want to do some processing twice with e.g. different parameters etc.):
spatialelement=spatialdata.models.Image2DModel.parse(
sdata[ "image" ].data*2, dims=[ 'c' ,'y', 'x' ],
)
sdata.add_image( name="image2", image=spatialelement , overwrite=True )
spatialelement=spatialdata.models.Image2DModel.parse(
sdata[ "image" ].data*2, dims=[ 'c' ,'y', 'x' ],
)
sdata.add_image( name="image2", image=spatialelement , overwrite=True )
hi @ArneDefauw ,
thanks for opening this issue, it is being worked in #329 and should be merged soon, will ping you back here once it's ready for you to try it out.