Coder's block - fast way of finding the cell that contains an XY coordinate

Hi all,

I have a list of XY coordinates from CytoMAP that have been, unfortunately, truncated/rounded in different ways depending on the number of decimal places - by MATLAB. Currently I am rounding QuPath’s XY coordinates for all cells and searching that list, which is noticeably slow at high numbers of cells.

What is the quickest way, per XY coordinate for a set of 100,000+ XY coordinates, to find the detection that contains it’s rounded XY coordinate (to avoid cycling through all of them)?
The assumption could be made that there will only be one detection overlapping those coordinates for the purposes of this script.

Thoughts

Not sure if I should go into JTS ROIs for this or something else (but how would I know which detection to use for an ROI?). Creating objects to check if they are “inside” seems like it would be very slow from other code I have written doing similar things. getObjectsForROI wouldn’t work well since I would have to create objects.

I would like to avoid cycling through all detections to see if each contains the point. Not sure if I am missing something obvious.

Also looking into dividing the cells up into tile-groups so that I am comparing the XY coordinates to a given set of cells instead of all of them.

In case it helps, these are the coordinates for the same cell, from QuPath and then returning from MATLAB.
image
image

Cheers,
Mike

The easiest way, which I think should be pretty fast, is to use PathObjectTools.getObjectsForLocation

This is what’s called whenever you double-click in the viewer.

If performance isn’t good enough, and especially if you don’t need to bother with z/t indices, you could construct a spatial cache using JTS and do a lot manually… but hopefully that won’t be necessary.

1 Like

Thanks, that works. For anyone else that might want to do something like this, the way the code ended up looking in my script was:

i

nt t = 0
int z = 0
    imageData = entry.readImageData()
    hierarchy = imageData.getHierarchy()
    pixelSize = imageData.getServer().getPixelCalibration().getAveragedPixelSizeMicrons()
//Stuff to get XY coordinates
       object = PathObjectTools.getObjectsForLocation(hierarchy, x/pixelSize, y/pixelSize,  t, z,-1).find{it.isDetection()}

Result is an object that is a detection and had that XY coordinate within it. If there are multiple detections for some reason, I guess it will pick the first one the “find” comes to.

QuPath’s handy dandy Log script time shows the improvement over a relatively smaller 32000 objects to already be:
INFO: Script run time: 15.12 seconds
vs
INFO: Script run time: 81.88 seconds

Thanks again! Time to update the posting.