Scripting Help for Creating and Deleting Annotations


I am interested in automating a SLIC based Object Classification Pipeline but am stuck on a few points.

I currently have annotated a training and test data set but would like to automate the tiling process to optimize different feature parameters. The pipeline that i have worked out manually that works the best is:

1)Place large annotation around all of the current annotations on the slide or on whole slide
2)Run SLIC
3) Run feature calculations (Intensity, Smoothed, Shape, Ect)
4)Delete the Large annotation created in step 1
5)Resolve Hierarchy to associate detections with the pre made annotations

I have this Groovy script made from the workflow/create script window which lacks step 1, 4, and 5 because it seems the workflow script creator does not capture exactly all the things i am doing manually.

runPlugin('qupath.imagej.superpixels.SLICSuperpixelsPlugin', '{...SLIC Params...}';
runPlugin('qupath.lib.algorithms.IntensityFeaturesPlugin', '{....Intensity feature params...}');
addShapeMeasurements("....shape params")
runPlugin('qupath.lib.plugins.objects.SmoothFeaturesPlugin', '{"...smooth params...');

Any help would be great!


Hi @rdbell3,

Would something like this work in your workflow?

// Create a full image annotation

// Run plugin
runPlugin('qupath.imagej.superpixels.SLICSuperpixelsPlugin', '{..}');

// Resolve Hierarchy

// Find parent annotation (level == 0), aka annotation created in step 1
def firstAnnotation = getAnnotationObjects().findAll{it.getLevel() == 1}

// Remove it
removeObjects(firstAnnotation, true)

Or alternatively, instead of creating a full image annotation, you can use the Thresholder to segment all your tissue in your slide (equivalent to the now deprecated Simple tissue detection), select it and run your plugin after.

1 Like

Thanks this works. What would be the command if i wanted to delete an annotation by class or by name?

Also, can i now select and delete all the tiles not in annotations? Ie the ones formally only associated with the now deleted “firstAnnotation”

@melvingelbard showed that here:

def firstAnnotation = getAnnotationObjects().findAll{it.getLevel() == 1}

Instead of getLevel you would use

def firstAnnotation = getAnnotationObjects().findAll{it.getPathClass() == getPathClass("Tumor")}

Or whatever else you might want. Once you have the objects defined, you remove them the same way as above.
Similarly, tiles could be removed with getDetectionObjects() instead of annotation objects using the same level logic (==1 for top, ==2 for one step down, etc).

Note that “outside” and the level will depend on whether you remove them before or after removing the outer annotation.

1 Like

Thanks this makes sense. Is there a easy way i can look up these commands and the arguments accepted by them? I have been looking through the github\lib but there is a lot to get through.

thanks again for all the help

I mostly use other scripts, there are a lot of them floating around. Alternatively, use the code itself on GitHub.

Also you can use CTRL+SPACEBAR to autocomplete within the QuPath scripting, or if you really want to get into it, set up IntelliJ to handle the scripting. Or use Eclipse and a setup like @Arjun.Vikram