saeyslab / napari-sparrow

Other
17 stars 0 forks source link

Calculate average pixel brightness per segmented object #130

Open lopollar opened 1 year ago

lopollar commented 1 year ago

I think there is a high negative correlation between the brightness of a cell and the amount of transcripts picked up in that cell. Of course we will have to correct for celltypes here, but still. So I would love to have a function that can calculate the brightness of a cell by using the masks. I am trying some code and it works, but is insanely slow.

So if anyone has an idea, please shoot!

lopollar commented 1 year ago

https://squidpy.readthedocs.io/en/stable/notebooks/examples/image/compute_segmentation_features.html

Somewhere hidden in the squidpy ducomentation I found something! I will try it out now

ArneDefauw commented 10 months ago

There is now support in sparrow for calculation of pixel intensities by using the masks.

Usage:

import napari_sparrow as nas

nas.tb.allocate_intensity(sdata, img_layer="raw_image", labels_layer="segmentation_mask", chunks=1024 )

It will calculate intensities for every channel in "raw_image", and save it as a sdata.table object.

Note that this will create a spatialdata table. Because spatialdata does not support multiple tables yet, this means that you have to back up a possible existing table elsewhere.

You can now also calculate calculate other features of the masks (using skimage):

nas.tb.add_regionprop_features( sdata, labels_layer="segmentation_mask" )

You can also calculate intensities of multiple masks, and append them to existing sdata.table.

Then you would do something like this:

# align label layers, so that overlapping masks have same label.

    sdata_multi_c = align_labels_layers(
        sdata_multi_c,
        labels_layer_1="masks_nuclear",
        labels_layer_2="masks_whole",
        output_labels_layer="masks_nuclear_aligned",
        output_shapes_layer=None,
        overwrite=True,
        chunks=256,
        depth=100,
    )

    assert "masks_nuclear_aligned" in sdata_multi_c.labels

    sdata_multi_c = allocate_intensity(
        sdata_multi_c, img_layer="raw_image", labels_layer="masks_whole", chunks=100
    )

    sdata_multi_c = allocate_intensity(
        sdata_multi_c, img_layer="raw_image", labels_layer="masks_nuclear_aligned", chunks=100, append=True
    )

    sdata_multi_c = add_regionprop_features(sdata_multi_c, labels_layer="masks_whole")

    sdata_multi_c = add_regionprop_features(sdata_multi_c, labels_layer="masks_nuclear_aligned")

Also see https://github.com/saeyslab/napari-sparrow/tree/main/src/napari_sparrow/_tests/test_table

Squidpy indeed supports calculation of these features, but computation there is not done lazy, and could lead to memory issues when images are big.

lopollar commented 10 months ago

''' It will calculate intensities for every channel in "raw_image", and save it as a sdata.table object.

''' For this first step, will it calculate the features for every cell? and it is an other object because not all cells are present in the anndata object? I don't think this is the best/cleanest solution to save it as an sdata table (at the moment). I would just save it as a separate object at the moment, and in the future as a table (or as features in the shapes layer? when they support saving those) These intensities and other features are calculated per cell, right? (I should have mentioned here that I worked on this too, but I am quite sure you did it better, I did use the skimage package too).

For the overlapping nuclei/cells, I had the following remarks:

For this reason I recommend to add a column to both segmentation masks (I add it in the table), that saves to which other segmentation mask they are mapping. I also added a cutoff parameter to state how much overlap is minimum to say cells are overlapping. In my case it was 50%.