Last active
April 25, 2023 10:44
-
-
Save lacan/543b389eca4b0b73f5f78d9a6a6d895c to your computer and use it in GitHub Desktop.
Revisions
-
lacan revised this gist
Apr 25, 2023 . 1 changed file with 5 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,6 @@ // Define Clusters based on distance and from cells with different classifications // This script works for images wehre multiple cell signals are segmented as detections // The detections must be children of annotations objects // And then a clustering step is used to get multi-classification cells // The clustering results are provided as circles withg name "Cluster" so you can filter from the original detections // Works in QuPAth 0.4.3 @@ -8,9 +9,11 @@ // @date 20230425 // Distance for nearest neighbour clustering, in microns def distance = 10 // START OF SCRIPT // Remove older clusters def oldClusters = getAllObjects().findAll { it.getROI() instanceof EllipseROI } removeObjects( oldClusters, false ) -
lacan created this gist
Apr 25, 2023 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,55 @@ // Define Clusters based on distance and from cells with different classifications // This script generally works for images wehre multiple cell signals are segmented as detections // And then a clustering step is used to get multi-classification cells // The clustering results are provided as circles withg name "Cluster" so you can filter from the original detections // Works in QuPAth 0.4.3 // // @author Olivier Burri // @date 20230425 // Distance for nearest neighgor clustering, in microns def distance = 10 // Remove older clusters def oldClusters = getAllObjects().findAll { it.getROI() instanceof EllipseROI } removeObjects( oldClusters, false ) // Work per annotation to keep hierarchy getAnnotationObjects().each{ annotation -> def cells = annotation.getChildObjects().findAll{ it.getPathClass() != getPathClass("Ignore*") } def delaunay = DelaunayTools.newBuilder( cells ) .calibration( getCurrentServer().getPixelCalibration() ) .centroids() .build() // Make clusters based on distance and make sure that you cannot cluster cells with the same class def clusters = delaunay.getClusters( DelaunayTools.centroidDistancePredicate( distance, true ).and( DelaunayTools.sameClassificationPredicate().negate() ) ) // Create the clusters on the dataset def averaged = clusters.collect{ current -> // Compute average position def meanX = current.collect{ it.getROI().getCentroidX() }.sum() / current.size() def meanY = current.collect{ it.getROI().getCentroidY() }.sum() / current.size() def roi = ROIs.createEllipseROI( meanX-distance/2, meanY-distance/2, distance, distance, null) // Get Path Class def pathClass = PathClass.fromCollection( current.collect{ it.getPathClass().getName() }.toUnique().toSorted() ) def object = PathObjects.createDetectionObject( roi, pathClass ) // Help identify this object for results export and filtering later. object.setName( "Cluster" ) return object } // Add them to the annotation annotation.addChildObjects( averaged ) } fireHierarchyUpdate() import qupath.lib.roi.EllipseROI