scverse / squidpy

Spatial Single Cell Analysis in Python
https://squidpy.readthedocs.io/en/stable/
BSD 3-Clause "New" or "Revised" License
440 stars 79 forks source link

Import H&E manual annotations #442

Closed nrclaudio closed 2 years ago

nrclaudio commented 2 years ago

Hi!

First of all, sorry if the question is too obvious but I haven't found an easy solution yet.

Is there a way to import a visium dataset for which there's been manual annotations in the H&E image? I see that we can do something similar with https://squidpy.readthedocs.io/en/stable/auto_examples/image/compute_custom_features.html#sphx-glr-auto-examples-image-compute-custom-features-py.

I thought about providing the expert annotations as an extra image layer. Then I'd create a custom function that gives a binary outcome to each spot depending on its manual annotation.

How should we import these annotations? as a standalone TIFF image that masks the regions of interest in the slide?

Thanks!

giovp commented 2 years ago

hi @nrclaudio , thanks a lot for the interest in Squidpy! This is a very interesting question for which we should provide an easy solution. For now, the way to go is the one you suggested.

  1. import the manual annotation in the image container as an additional (segmentation) layer. This layer must have same shape as the image, that is shape (H,W,). The unique annotation should be saved with the same integer per-pixel (with e.g. pixels that do not overlap an annotation to be 0). This is the standard for segmentation mask. You can have a look at this tutorial re how to import it correctly https://squidpy.readthedocs.io/en/stable/auto_tutorials/tutorial_mibitof.html . In this case, the segmentation masks are saved in anndata, and we want to assign them to the image container "segmentation" layer. You can play around with the data to understand shapes and dtype of the array in order to make it fit.
  2. implement a custom function that according to the segmentation mask, returns a value (e.g. the mask integer itself, or a pre-defined class). This should be straightforward. This could be something as simple as this:
    
    anno_mapping = {"tissue_anno_1":1, "tissue_anno_2":2,...}

def anno_fn(arr): """Compute mean of arr.""" import numpy as np unique, counts = np.unique(arr, return_counts=True) val = [k for k,v in anno_mapping.items() if v == unique[0]][0]

return val

sq.im.calculate_image_features( adata, img, features="custom", features_kwargs={"custom": {"func": anno_fn}}, key_added="custom_features", show_progress_bar=False, )


3. use `sq.im.calculate_image_features` making sure that you select as layer the segmentation layer. See here for the API https://squidpy.readthedocs.io/en/stable/api/squidpy.im.calculate_image_features.html#squidpy.im.calculate_image_features

let me know if that makes sense and you manage to make it to work, happy to follow up in case.
nrclaudio commented 2 years ago

Hi @giovp,

Thanks for the prompt answer and sorry for my not-so-prompt update.

Indeed, what you mention here seems like the right approach. I can't test it right now as I'm still waiting for the annotations. Thanks for the code snippet too!

I'll close this as it's been solved.

giovp commented 2 years ago

feel free to reopen if you can't manage or need further clarification