Last active
October 15, 2024 06:14
-
-
Save Svidro/33558ac3bd9f68a5ec2428f74550831f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Clean up bad objects | |
removal = getCellObjects().findAll{it.getPathClass().toString().contains("Trash")} | |
removeObjects(removal, true) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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