Selecting SLIC Tiles

Is there any way to select all tiles generated by SLIC Superpixel segmentation?
There are detections, cells, annotations, TMA cores in the select menu but there is no option for tiles.

In v0.2.0-m9, this should do it:

selectObjects { it.isTile() }

And detections is the overall type, so as long as you aren’t avoiding other types of detections, that is your catch-all.

I have whole slide annotations and segmented million cells in it. I am making rectangle annotations in the whole slide annotation aiming the tumor zones infiltrated by immune cells.
I use SLIC tool+Add intensity/shape features/smoothing+RandomForestClassification of Tiles+Tiles to Annotation pipeline to make tumor/stroma annotation based on PanCK and I copy the tumor/stroma annotations to the other images of the slide stained with other markers (aiming immune cells).
I was struggling to automate the process due to being not able to select the tiles.
Thanks @petebankhead and @Research_Associate for your help. Script works perfectly in M9

2 Likes

Ah, sequential slice fun! They make for such interesting projects.

One more question;
Is there a way to automatically select the rectangle ROIs located in the whole section annotation?
Whole section annotation is made by pixel classifier.

It is actually not sequential slice, instead it is sequential staining. We use the same tissue section for staining with multiple markers consecutively. We stain with one marker, scan the slide and save the image and then remove the staining. After that use another marker on the same slide and repeat this process 10 times for 10 markers.

I would generally give the whole section annotation a class after it is created. Or the rectangle ROI a class (if none assinged the class = null) But I’m sure you can also get all annotations that are rectangles if you want.

Annotations = getAnnotationObjects().findAll{it.getPathClass() == null}

getCurrentHierarchy().getSelectionModel().setSelectedObjects(Annotations, null)

^-- assuming your pixel classifier generated a classified whole tissue annotation.

Ah right, sorry. That does make the overlap problem between images potentially a lot easier :slight_smile:

Edit: Fixed on account of brain-fart when scripting.

1 Like

I have one last problem regarding the composite classifier.
I trained individual images 20 times and I have been using those object classifiers for SLIC tile classification. However when I merge and make a composite object classifier, it classifies every single detection not only tiles. Is there a way to fix this?

When you use Train object classifier, you can set the Object filter (top drop-down menu) to define the kinds of object to which it applies. This allows you to switch between tiles or cells in the case that you have both on the same image.

What should happen is that if all your classifiers specify Tiles as the object filter, then the composite classifier should also be applied only to tiles.

I haven’t actually had time to generate data to confirm this works as intended… have you tried using the object filter + composite classifier to see if it does what you need?

2 Likes

That’s actually what I do for individual classifiers. I filter it for tiles. However when I merge them as a composite classifier, they don’t perform as tile classifiers, instead composite classifier classifies every single object within the annotation.

I’ve just tried this and I think it is working as expected, however it is important to note that all classifiers need to specify that they run on tiles only.

If any one of the classifiers within the composite specifies detections instead then the whole composite classifier will be applied to all detections.

The relevant bit of the code is here: https://github.com/qupath/qupath/blob/c5cc1895f5ff6ff94b2431b4b2ede7fad78b071f/qupath-core/src/main/java/qupath/lib/classifiers/object/CompositeClassifier.java#L84

You can open the classifier.json files in a text editor, and you should see a line somewhere inside that looks like

"filter": "TILES",

for each classifier.

That’s the default behavior anyway. By scripting, it is possible to override the object filter and provide the objects you want directly. Here’s an example that applies a classifier to tiles, regardless of what was specified when the classifier was created:

def imageData = getCurrentImageData()
def classifier = loadObjectClassifier('Other tiles')

def tiles = getDetectionObjects().findAll {it.isTile()}
classifier.classifyObjects(imageData, tiles, true)
fireHierarchyUpdate()
2 Likes