Skip to content

Blobdetector gives incorrect rounds and channels for spots when run with no reference image and is_volume=False #2159

@shachafl

Description

@shachafl

Description

Spots results from starfish/core/spots/FindSpots/blob.py are saved with incorrect round and channels when using no reference image and "is_volume=False" (either a 2d data or 3d data that is processed as a set of 2d tiles).

Working on #2154 I also discovered a different issue with different results between "is_volume=True" and "is_volume=False" when no reference image is used. It is due to the way spots are merged from the same round/channel but different z slices:

# If not a volume, merge spots from the same round/channel but different z slices
if not self.is_volume:
merged_z_tables = defaultdict(pd.DataFrame) # type: ignore
for i in range(len(spot_attributes_list)):
spot_attributes_list[i][0].spot_attrs.data['z'] = \
spot_attributes_list[i][1]['z']
r = spot_attributes_list[i][1][Axes.ROUND]
ch = spot_attributes_list[i][1][Axes.CH]
merged_z_tables[(r, ch)] = pd.concat(
[merged_z_tables[(r, ch)], spot_attributes_list[i][0].spot_attrs.data])
new = []
r_chs = sorted([*merged_z_tables])
selectors = list(image_stack._iter_axes({Axes.ROUND, Axes.CH}))
for i, (r, ch) in enumerate(r_chs):
merged_z_tables[(r, ch)]['spot_id'] = range(len(merged_z_tables[(r, ch)]))
spot_attrs = SpotAttributes(merged_z_tables[(r, ch)].reset_index(drop=True))
new.append((PerImageSliceSpotResults(spot_attrs=spot_attrs, extras=None),
selectors[i]))
spot_attributes_list = new
results = SpotFindingResults(imagestack_coords=image_stack.xarray.coords,
log=image_stack.log,
spot_attributes_list=spot_attributes_list)

Bottom line, the {round,ch}I pairs are saved incorrectly ({0,1} should be {1,0}, and so on).

Steps/Code to Reproduce

Run the script examples/how_to/assess_spotfindingresults.py, without a reference image and once with "is_volume=True" and once with "is_volume=False".

# run blob detector on dots (reference image with every spot)
bd = FindSpots.BlobDetector(
    min_sigma=1,
    max_sigma=3,
    num_sigma=10,
    threshold=0.01,
    #is_volume=False,
    is_volume=True, ## DEBUG1 - True instead of False
    measurement_type='mean',
)
#spots = bd.run(image_stack=imgs, reference_image=dots)
spots = bd.run(image_stack=imgs)  ## DEBUG2 - No reference image

# Start Debugging
for r in range(imgs.num_rounds):
    for ch in range(imgs.num_chs):
        data=spots[{Axes.CH:ch, Axes.ROUND:r}].spot_attrs.data
        print(f"\nRound:{r}, Ch:{ch}")
        print(data.sort_values("intensity", ascending=False).head(5))
# End Debugging

Expected Results

The same results for "is_volume=True" and "is_volume=False" when the same data is presented as 2d (y,x) or 3d with a single z-plane (1,y,x), especially as we now squeeze the single z-plane and send blob_log() the same 2d data.

Actual Results

One example result for the case of "is_volume=True":

Round:0, Ch:1
     intensity  z    y    x  radius  spot_id
217   0.225376  0  938  428     2.0      217
13    0.223259  0  890  344     2.0       13
115   0.222446  0  158  979     2.0      115
36    0.221881  0  309  586     2.0       36
70    0.221012  0  446  212     3.0       70

One example result for the case of "is_volume=False":

Round:0, Ch:1
    intensity  z    y     x  radius  spot_id
0    0.196602  0  472  1174     2.0        0
1    0.188165  0  452  1093     2.0        1
15   0.186682  0  944   338     2.0       15
10   0.185512  0  549   782     2.0       10
34   0.184856  0    7   980     2.0       34

Metadata

Metadata

Labels

bugAn issue with an existing feature

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions