Scripts mostly taken from Pete, and also from the forums. For easy access and reference. | |
TOC | |
Remove detections outside annotations.groovy - Removes detections without a parent object. | |
Removing measurements by Weka file.groovy - Uses the results of Weka classification analysis of your training set | |
to select the "best" measurements plus any specific ones you want to keep. Then it removes the rest. Use this to clean up | |
large amounts measurements like LBP, Haralick, Smoothed etc. | |
Removing measurements by keyword.groovy - Variant of the above, but clean up your measurement lists by keyword. Useful for | |
removing ALL smoothed measurements as part of a script. | |
Remove objects by class name.groovy - Remove objects that have a class with a certain string in the name | |
Remove subcells after 0.2.0m5.groovy - collect and remove subcellular detections | |
Removing small annotation bits.groovy - Cleans up small tissue bits, though this can often be done by using better settings | |
during Simple Tissue Detection. Can be useful if your script fragments your annotations at a later point. | |
removing specific annotations.groovy - An example of deleting objects by creating a list, then removing the objects in the list. | |
Generally you will want to remove objects either by selecting them and using: | |
clearSelectedObjects(false); | |
or creating a list and using: | |
removeObjects(yourList,true) | |
True and false in the above statements indicate whether you also want to remove objects within the object you are deleting, | |
such as cells within an annotation. True indicates that you want to keep the contained objects, while false removes everything. |
//Remove all clusters 0.2.0m5+ | |
// def subcellular = getDetectionObjects().findAll {it.getParent()?.isDetection()} | |
//def subcellular2 = getCellObjects().collect({it.getChildObjects()}).flatten() | |
removeObjects(getDetectionObjects().findAll{it.getPathClass().toString().contains("Subcellular")},true) |
/* | |
* Identify annotations touching the image boundary | |
https://forum.image.sc/t/filter-out-annotations-touching-image-border/37570/2?u=research_associate | |
*/ | |
def server = getCurrentServer() | |
// To get the annotations | |
def annotations = getAnnotationObjects().findAll { touchingBoundary(server, it.getROI()) } | |
removeObjects(annotations, false) | |
// To select the annotations | |
//selectObjects {it.isAnnotation() && it.hasROI() && touchingBoundary(server, it.getROI())} | |
// Using full lambda to get the annotations (just a different syntax) | |
//def annotations2 = getAnnotationObjects().findAll(annotation -> touchingBoundary(server, annotation.getROI())) | |
boolean touchingBoundary(server, roi) { | |
return roi.getBoundsX() <= 0 || | |
roi.getBoundsY() <= 0 || | |
roi.getBoundsX() + roi.getBoundsWidth() >= server.getWidth()-1 || | |
roi.getBoundsY() + roi.getBoundsHeight() >= server.getHeight()-1 | |
} |
//Useful if you are trimming an annotation after having generated detections, and want a quick way to eliminate | |
//cells now outside of your annotated regions. | |
selectObjects{p -> (p.getLevel()==1) && (p.isAnnotation() == false)}; | |
clearSelectedObjects(false); |
//Clean up bad objects | |
removal = getCellObjects().findAll{it.getPathClass().toString().contains("Trash")} | |
removeObjects(removal, true) |
//Replace the text in it.contains("keyword") in order to remove all measurements that contain that text. | |
//This can be useful after Smoothing in order to remove some of the large numbers of measurements you probably do not need | |
import qupath.lib.classifiers.PathClassificationLabellingHelper | |
def toRemove = PathClassificationLabellingHelper.getAvailableFeatures(getDetectionObjects()).findAll { it.contains("keyword") } | |
print toRemove | |
//PathTileObject for SLICs, PathCellObject for cells, TMACoreObject for TMAs | |
removeMeasurements(qupath.lib.objects.PathTileObject, toRemove as String[]) | |
fireHierarchyUpdate() |
//V1.0 attempting to read in an arff file as Strings. | |
//Note that you may need to change pathCellObject to pathTileObject at the end | |
import qupath.lib.classifiers.PathClassificationLabellingHelper | |
File arff = new File('C:\\filePath\\fileName.arff') | |
def lines = arff.readLines() | |
def start = false | |
def variableList = [] | |
//create a list with elements that are your measurements from Weka | |
for (def i=0; i<lines.size()-1; i++){ | |
if (start == true){ | |
variableList.add(lines[i].trim()) | |
} | |
if (lines[i].contains("Selected attributes:")){ | |
start = true | |
} | |
} | |
def listTotal = [] | |
//convert hashlinkedset into list so that the subtractions on the next line does not error out | |
listTotal.addAll(0,PathClassificationLabellingHelper.getAvailableFeatures(getDetectionObjects())) | |
//Potentially keep some necessary measurements that are not used? | |
variableList.addAll(['Nucleus: Area', 'Cytoplasm: Eosin OD mean']) | |
//subtract the list of variables from the arff file from the list of variables you want to remove | |
listTotal.removeAll(variableList) | |
//PathTileObject for SLICs PathCellObject for cells | |
removeMeasurements(qupath.lib.objects.PathCellObject, listTotal as String[]) | |
fireHierarchyUpdate() | |
println("measurements removed") |
import qupath.lib.roi.* | |
import qupath.lib.objects.* | |
//Choose the area threshold below which the annotations will be deleted | |
def ANNOTATION_AREA_MICRONS = 5 | |
//PART 1 | |
//This section splits ALL annotations into contiguous areas, so that any pieces off on their own can be deleted. | |
//Use only Part 2 if you already have individual annotations. | |
annotationList = getAnnotationObjects() | |
for (selected in annotationList){ | |
if (!(selected.getROI() instanceof AreaROI)) { | |
print 'Selected object does not have an AreaROI!' | |
return | |
} | |
// Try to do split, and ensure holes are taken into consideration | |
def polygons = PathROIToolsAwt.splitAreaToPolygons(selected.getROI()) | |
def newPolygons = polygons[1].collect { | |
updated = it | |
for (hole in polygons[0]) | |
updated = PathROIToolsAwt.combineROIs(updated, hole, PathROIToolsAwt.CombineOp.SUBTRACT) | |
return updated | |
} | |
// Remove original annotation, add new ones | |
annotations = newPolygons.collect {new PathAnnotationObject(it)} | |
resetSelection() | |
removeObject(selected, true) | |
addObjects(annotations) | |
} | |
//PART2 | |
//This section | |
def server = getCurrentImageData().getServer() | |
double pixelWidth = server.getPixelWidthMicrons() | |
double pixelHeight = server.getPixelHeightMicrons() | |
def smallAnnotations = getAnnotationObjects().findAll {it.getROI().getScaledArea(pixelWidth, pixelHeight) < ANNOTATION_AREA_MICRONS} | |
removeObjects(smallAnnotations, true) | |
fireHierarchyUpdate() | |
//PART3 | |
//Merge annotations back into a single annotation if this is desired for data analysis. | |
//selectAnnotations() | |
//mergeSelectedAnnotations() |
//removing annotations of class 1 that do not have children of class 2 | |
//use of .any | |
// Define classes | |
class1 = getPathClass('class1') | |
class2 = getPathClass('class2') | |
// Get all the class1 annotations that don't contain a class2 object as a direct child | |
toRemove = getAnnotationObjects().findAll { | |
if (it.getPathClass() != class1) | |
return false | |
children = it.getChildObjects() | |
return !children.any {it.getPathClass() == class2} | |
} | |
// Remove annotations meeting that criteria | |
removeObjects(toRemove, true) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment