|
215 | 215 | }, |
216 | 216 | { |
217 | 217 | "cell_type": "code", |
218 | | - "execution_count": 31, |
| 218 | + "execution_count": null, |
219 | 219 | "metadata": {}, |
220 | | - "outputs": [ |
221 | | - { |
222 | | - "name": "stdout", |
223 | | - "output_type": "stream", |
224 | | - "text": [ |
225 | | - "\u001b[34mINFO \u001b[0m `dims` is specified redundantly: found also inside `data`. \n" |
226 | | - ] |
227 | | - }, |
228 | | - { |
229 | | - "name": "stderr", |
230 | | - "output_type": "stream", |
231 | | - "text": [ |
232 | | - "\u001b[36;20m[INFO] (spatialdata_xenium_explorer.core.images)\u001b[0m Adding image image:\n", |
233 | | - "<xarray.SpatialImage 'image' (c: 3, y: 43287, x: 22209)>\n", |
234 | | - "dask.array<rechunk-merge, shape=(3, 43287, 22209), dtype=uint8, chunksize=(1, 4096, 4096), chunktype=numpy.ndarray>\n", |
235 | | - "Coordinates:\n", |
236 | | - " * c (c) <U1 '0' '1' '2'\n", |
237 | | - " * y (y) float64 0.5 1.5 2.5 3.5 ... 4.328e+04 4.329e+04 4.329e+04\n", |
238 | | - " * x (x) float64 0.5 1.5 2.5 3.5 ... 2.221e+04 2.221e+04 2.221e+04\n", |
239 | | - "Attributes:\n", |
240 | | - " transform: {'global': Affine (x, y -> x, y)\\n [1.83698152e-03 6.44010...\n" |
241 | | - ] |
242 | | - }, |
243 | | - { |
244 | | - "ename": "KeyError", |
245 | | - "evalue": "'Image Xeniumranger_V1_hSkin_Melanoma_Add_on_FFPE_he_image already exists in the dataset.'", |
246 | | - "output_type": "error", |
247 | | - "traceback": [ |
248 | | - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", |
249 | | - "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", |
250 | | - "Cell \u001b[0;32mIn[31], line 6\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# where you exported the alignment file\u001b[39;00m\n\u001b[1;32m 4\u001b[0m alignment_matrix_path \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mXeniumranger_V1_hSkin_Melanoma_Add_on_FFPE_he_imagealignment.csv\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m----> 6\u001b[0m \u001b[43mspatialdata_xenium_explorer\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43malign\u001b[49m\u001b[43m(\u001b[49m\u001b[43msdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mh_and_e\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43malignment_matrix_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mimage_key\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mimage_key\u001b[49m\u001b[43m)\u001b[49m\n", |
251 | | - "File \u001b[0;32m~/dev/spatialdata_xenium_explorer/spatialdata_xenium_explorer/core/images.py:243\u001b[0m, in \u001b[0;36malign\u001b[0;34m(sdata, image, transformation_matrix_path, image_key, image_models_kwargs, overwrite)\u001b[0m\n\u001b[1;32m 234\u001b[0m image \u001b[38;5;241m=\u001b[39m Image2DModel\u001b[38;5;241m.\u001b[39mparse(\n\u001b[1;32m 235\u001b[0m image,\n\u001b[1;32m 236\u001b[0m dims\u001b[38;5;241m=\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mc\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124my\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mx\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 239\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mimage_models_kwargs,\n\u001b[1;32m 240\u001b[0m )\n\u001b[1;32m 242\u001b[0m log\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAdding image \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mimage\u001b[38;5;241m.\u001b[39mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m:\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00mimage\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 243\u001b[0m \u001b[43msdata\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43madd_image\u001b[49m\u001b[43m(\u001b[49m\u001b[43mimage_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mimage\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43moverwrite\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43moverwrite\u001b[49m\u001b[43m)\u001b[49m\n", |
252 | | - "File \u001b[0;32m~/Library/Caches/pypoetry/virtualenvs/spatialdata-xenium-explorer-yAxRBYoR-py3.9/lib/python3.9/site-packages/spatialdata/_core/spatialdata.py:710\u001b[0m, in \u001b[0;36mSpatialData.add_image\u001b[0;34m(self, name, image, storage_options, overwrite)\u001b[0m\n\u001b[1;32m 708\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_add_image_in_memory(name\u001b[38;5;241m=\u001b[39mname, image\u001b[38;5;241m=\u001b[39mimage, overwrite\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[1;32m 709\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 710\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_add_image_in_memory\u001b[49m\u001b[43m(\u001b[49m\u001b[43mname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mname\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mimage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mimage\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43moverwrite\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43moverwrite\u001b[49m\u001b[43m)\u001b[49m\n", |
253 | | - "File \u001b[0;32m~/Library/Caches/pypoetry/virtualenvs/spatialdata-xenium-explorer-yAxRBYoR-py3.9/lib/python3.9/site-packages/spatialdata/_core/spatialdata.py:288\u001b[0m, in \u001b[0;36mSpatialData._add_image_in_memory\u001b[0;34m(self, name, image, overwrite)\u001b[0m\n\u001b[1;32m 284\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_unique_element_names(\n\u001b[1;32m 285\u001b[0m \u001b[38;5;28mlist\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlabels\u001b[38;5;241m.\u001b[39mkeys()) \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mlist\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpoints\u001b[38;5;241m.\u001b[39mkeys()) \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mlist\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mshapes\u001b[38;5;241m.\u001b[39mkeys()) \u001b[38;5;241m+\u001b[39m [name]\n\u001b[1;32m 286\u001b[0m )\n\u001b[1;32m 287\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m name \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_images \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m overwrite:\n\u001b[0;32m--> 288\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mImage \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m already exists in the dataset.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 289\u001b[0m ndim \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlen\u001b[39m(get_axes_names(image))\n\u001b[1;32m 290\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ndim \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m3\u001b[39m:\n", |
254 | | - "\u001b[0;31mKeyError\u001b[0m: 'Image Xeniumranger_V1_hSkin_Melanoma_Add_on_FFPE_he_image already exists in the dataset.'" |
255 | | - ] |
256 | | - } |
257 | | - ], |
| 220 | + "outputs": [], |
258 | 221 | "source": [ |
259 | 222 | "image_key = \"morphology_mip\"\n", |
260 | 223 | "\n", |
|
306 | 269 | "cell_type": "markdown", |
307 | 270 | "metadata": {}, |
308 | 271 | "source": [ |
309 | | - "### Alignment from `SpatialData` to the Xenium Explorer" |
| 272 | + "### Alignment from `SpatialData` to the Xenium Explorer\n", |
| 273 | + "\n", |
| 274 | + "Now, we suppose you have already aligned your H&E image using `SpatialData`. Here, we detail how use the transformation inside the Xenium Explorer." |
310 | 275 | ] |
311 | 276 | }, |
312 | 277 | { |
|
319 | 284 | "import numpy as np" |
320 | 285 | ] |
321 | 286 | }, |
| 287 | + { |
| 288 | + "cell_type": "markdown", |
| 289 | + "metadata": {}, |
| 290 | + "source": [ |
| 291 | + "First, we get the transformation from the H&E image to the global coordinate system:" |
| 292 | + ] |
| 293 | + }, |
322 | 294 | { |
323 | 295 | "cell_type": "code", |
324 | 296 | "execution_count": 29, |
|
330 | 302 | "transformation = get_transformation(spatial_element, to_coordinate_system=\"global\")" |
331 | 303 | ] |
332 | 304 | }, |
| 305 | + { |
| 306 | + "cell_type": "markdown", |
| 307 | + "metadata": {}, |
| 308 | + "source": [ |
| 309 | + "If it is an affine transformation, we can create a `.csv` file representing the transformation:" |
| 310 | + ] |
| 311 | + }, |
333 | 312 | { |
334 | 313 | "cell_type": "code", |
335 | 314 | "execution_count": 30, |
336 | 315 | "metadata": {}, |
337 | 316 | "outputs": [], |
338 | 317 | "source": [ |
339 | | - "assert isinstance(transformation, Affine), \"The Xenium Explorer only supports Affine transformations\"\n", |
| 318 | + "assert isinstance(\n", |
| 319 | + " transformation, Affine\n", |
| 320 | + "), \"The Xenium Explorer only supports Affine transformations\"\n", |
340 | 321 | "\n", |
341 | 322 | "np.savetxt(\"alignment_matrix.csv\", transformation.matrix, delimiter=\",\")" |
342 | 323 | ] |
|
356 | 337 | "source": [ |
357 | 338 | "# 4. Update the cells on the Explorer\n", |
358 | 339 | "\n", |
359 | | - "### Update the cell categories" |
| 340 | + "### Update the cell categories\n", |
| 341 | + "\n", |
| 342 | + "Here, we run some Leiden clustering with `scanpy`. Then, we will update the Xenium Explorer files to display the spot clusters.\n", |
| 343 | + "\n", |
| 344 | + "More generally, you can add new cell categories, i.e. a column of `sdata.table.obs`, and the Xenium Explorer will show it after the instructions below.\n", |
| 345 | + "\n", |
| 346 | + "> Note that we only display categorical columns. If a column from `sdata.table.obs` contains continuous numerical values (e.g., `3.13, 7.89, ...`), it will not be transformed into a categorical variable, and therefore not shown in the Xenium Explorer. In this case, we recommend using `spatiadata_plot` as shown above." |
360 | 347 | ] |
361 | 348 | }, |
362 | 349 | { |
|
424 | 411 | "source": [ |
425 | 412 | "### Update a new segmentation\n", |
426 | 413 | "\n", |
427 | | - "In the case where you performed your own segmentation, you may want to update the explorer with your new cells.\n", |
| 414 | + "In the case where you performed your own segmentation, you may want to update the explorer with your new cells. You'll also need to update `sdata.table` to contain the transcript counts associated to your new cells.\n", |
428 | 415 | "\n", |
429 | 416 | "> Note that `mode=\"-it\"` signifies to create all files except the image and transcript file. Indeed, the two latter files doesn't need to be updated, they will remain the same." |
430 | 417 | ] |
|
445 | 432 | "outputs": [], |
446 | 433 | "source": [ |
447 | 434 | "# this is the key related to your new cell boundaries, i.e. sdata[shapes_key] is a pandas GeoDataFrame\n", |
448 | | - "shapes_key = \"new_shapes\"\n", |
449 | | - "\n", |
450 | | - "spatialdata.aggregate(...)" |
| 435 | + "shapes_key = \"new_shapes\"" |
| 436 | + ] |
| 437 | + }, |
| 438 | + { |
| 439 | + "cell_type": "markdown", |
| 440 | + "metadata": {}, |
| 441 | + "source": [ |
| 442 | + "Now, update all the files related to your new cells:" |
451 | 443 | ] |
452 | 444 | }, |
453 | 445 | { |
|
0 commit comments