scverse / spatialdata

An open and interoperable data framework for spatial omics data
https://spatialdata.scverse.org/
BSD 3-Clause "New" or "Revised" License
174 stars 34 forks source link

Error in `add_shapes()` function #524

Closed GuoshengMa closed 1 month ago

GuoshengMa commented 1 month ago

Hi @LucaMarconato ! A few days ago, following the instructions in the Use landmark annotations to align multiple -omics layers section, I successfully aligned the layers using data from visium and xenium. However, today I encountered an error when running the add_shapes() function following the same code.

Here is my code:

from spatialdata.models import ShapesModel

visium_landmarks = ShapesModel.parse(
    np.array(visium_sdata['visium_temp_points'].drop('z', axis=1)), geometry=0, radius=1000
)
visium_sdata.add_shapes("visium_temp_shape", visium_landmarks, overwrite=True)

xenium_landmarks = ShapesModel.parse(
    np.array(xenium_sdata['xenium_temp_points'].drop('z', axis=1)), geometry=0, radius=1000
)
xenium_sdata.add_shapes("xenium_temp_shape", xenium_landmarks, overwrite=True)

And here is the error:

RuntimeError                              Traceback (most recent call last)
Cell In[6], [line 6](vscode-notebook-cell:?execution_count=6&line=6)
      [1](vscode-notebook-cell:?execution_count=6&line=1) from spatialdata.models import ShapesModel
      [3](vscode-notebook-cell:?execution_count=6&line=3) visium_landmarks = ShapesModel.parse(
      [4](vscode-notebook-cell:?execution_count=6&line=4)     np.array(visium_sdata['visium_temp_points'].drop('z', axis=1)), geometry=0, radius=1000
      [5](vscode-notebook-cell:?execution_count=6&line=5) )
----> [6](vscode-notebook-cell:?execution_count=6&line=6) visium_sdata.add_shapes("visium_temp_shape", visium_landmarks, overwrite=True)
      [8](vscode-notebook-cell:?execution_count=6&line=8) xenium_landmarks = ShapesModel.parse(
      [9](vscode-notebook-cell:?execution_count=6&line=9)     np.array(xenium_sdata['xenium_temp_points'].drop('z', axis=1)), geometry=0, radius=[10](vscode-notebook-cell:?execution_count=6&line=10)00
     10 )
     [11](vscode-notebook-cell:?execution_count=6&line=11) xenium_sdata.add_shapes("xenium_temp_shape", xenium_landmarks, overwrite=True)

File [c:\Users\mgssu\anaconda3\envs\spatialData\Lib\site-packages\spatialdata\_core\spatialdata.py:1273](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_core/spatialdata.py:1273), in SpatialData.add_shapes(self, name, shapes, overwrite)
   [1267](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_core/spatialdata.py:1267) def add_shapes(
   [1268](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_core/spatialdata.py:1268)     self,
   [1269](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_core/spatialdata.py:1269)     name: str,
   [1270](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_core/spatialdata.py:1270)     shapes: GeoDataFrame,
   [1271](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_core/spatialdata.py:1271)     overwrite: bool = False,
   [1272](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_core/spatialdata.py:1272) ) -> None:
-> [1273](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_core/spatialdata.py:1273)     _error_message_add_element()

File [c:\Users\mgssu\anaconda3\envs\spatialData\Lib\site-packages\spatialdata\_utils.py:281](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_utils.py:281), in _error_message_add_element()
    [280](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_utils.py:280) def _error_message_add_element() -> None:
--> [281](file:///C:/Users/mgssu/anaconda3/envs/spatialData/Lib/site-packages/spatialdata/_utils.py:281)     raise RuntimeError(
...
    sdata.labels["labels_name"] = labels
    ...

The new syntax does not automatically updates the disk storage, so you need to call sdata.write() when the in-memory object is ready to be saved.
To save only a new specific element to an existing Zarr storage please use the functions write_image(), write_labels(), write_points(), write_shapes() and write_table(). We are going to make these calls more ergonomic in a follow up PR.

In these past few days, I encountered another error while using the polygon_query() function and resolved it based on the suggestions provided in #474. During this process, I updated spatialdata using pip install git+https://github.com/scverse/spatialdata. I'm not sure if this operation caused the error mentioned above.

LucaMarconato commented 1 month ago

Hi @GuoshengMa, thanks for reaching out. The error above is expected and of easy fix. In the latest release we refactored the IO system to separate the moment in which new elements are added in memory and the moment when they are saved to disk.

To add the new element in-memory you can now simply do sdata['labels_name'] = labels. If you also need to save it to disk you have two options:

  1. save the whole object with sdata.write('data.zarr')
  2. save only the new labels element. This functionality is not supported in main yet but is already implemented and working in this PR: https://github.com/scverse/spatialdata/pull/501

Last comment, I see you are using Windows and Xenium data; some users reported problems with Xenium and Steinbock data (and if the element name contain the character /), please check out also https://github.com/scverse/spatialdata-io/issues/129 if you have any problems of that kind.

GuoshengMa commented 1 month ago

Great! It works for me and below is my code:

from spatialdata.models import ShapesModel

visium_landmarks = ShapesModel.parse(
    np.array(visium_sdata['visium_temp_points'].drop('z', axis=1)), geometry=0, radius=1000
)
visium_sdata["visium_temp_shape"] = visium_landmarks