Last active
June 20, 2025 01:12
-
-
Save caner-ercan/806696a604bdb73ea6437dca1c863784 to your computer and use it in GitHub Desktop.
QuPath _ AI-TIL #QuPath
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 characters
| //0.2.0 version of https://forum.image.sc/t/assign-point-objects-to-different-rois-by-overlap/26905/2?u=research_associate | |
| // Convert points into detections, resolve the heirarchy so they are now child objects of any annotations. | |
| import qupath.lib.roi.EllipseROI; | |
| import qupath.lib.objects.PathDetectionObject | |
| points = getAnnotationObjects().findAll{it.getROI().isPoint() } | |
| print points[0].getROI() | |
| describe(points[0].getROI()) | |
| //Cycle through each points object (which is a collection of points) | |
| points.each{ | |
| //Cycle through all points within a points object | |
| pathClass = it.getPathClass() | |
| it.getROI().getAllPoints().each{ | |
| //for each point, create a circle on top of it that is "size" pixels in diameter | |
| x = it.getX() | |
| y = it.getY() | |
| size = 5 | |
| def roi = ROIs.createEllipseROI(x-size/2,y-size/2,size,size, ImagePlane.getDefaultPlane()) | |
| def aCell = new PathDetectionObject(roi, pathClass) | |
| addObject(aCell) | |
| } | |
| } | |
| print points[0].getROI() | |
| //remove points if desired. | |
| removeObjects(points, false) | |
| resolveHierarchy() |
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 characters
| folder = buildFilePath(PROJECT_BASE_DIR, "tsv") | |
| def checkDir = new File(folder) | |
| if(!checkDir.exists()) { | |
| checkDir.mkdir() | |
| } | |
| name= GeneralTools.getNameWithoutExtension(getProjectEntry().getImageName()) | |
| File fileName = new File(buildFilePath(folder,name+".tsv")) | |
| def points = [] | |
| selectAnnotations() | |
| anns = getSelectedObjects() | |
| for (ann in anns) { | |
| if(ann.getROI().getRoiName() == "Points") | |
| points.add(ann) | |
| } | |
| PointIO.writePoints(file = fileName, pathObjects = points) |
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 characters
| /* | |
| Purpose: | |
| This QuPath script import annotations from AI-sTIL's output CSV file. | |
| The output file must be copied into the following directory in Polyscope: | |
| '.../aitil/4_cell_class/CellPos/{image_name}_cellPos.csv' | |
| Works with any version of QuPath—until further notice (or disaster). | |
| Author: Caner Ercan | |
| */ | |
| // before running this code, be sure that AI_TIL output cell positions were not rounded. 'step4_cell_class/subpackages/cellPos.py' line: 41-42. | |
| // In addition, check if the output is downsampled (the fixed ratio is 16)[ same file, line 36] | |
| // Also you need to know pixel_size of your image | |
| import qupath.lib.geom.Point2 | |
| // def pixel_size = 0.5013 | |
| def pixelSize= getCurrentServer().getPixelCalibration().getAveragedPixelSize() | |
| def folder = "/Volumes/rsrch6/home/trans_mol_path/yuan_lab/TIER2/anaplasticThyroid_XiaoZhao/aitil/4_cell_class/CellPos" | |
| def plane = getCurrentViewer().getImagePlane() | |
| def imagename = getProjectEntry().getImageName() | |
| def fileName = buildFilePath(folder,imagename+'_cellPos.csv') | |
| def coords = [] | |
| def skipFirstLine = true | |
| clearAllObjects() | |
| // Read the TSV file line by line | |
| new File(fileName).eachLine { line -> | |
| if (skipFirstLine) { | |
| skipFirstLine = false | |
| return | |
| } | |
| print line | |
| // // Process each line here | |
| // | |
| def rowContent = line.split(',') | |
| // | |
| // | |
| double cx = (rowContent [2] as double) * 0.44 / pixelSize | |
| double cy = (rowContent[3] as double) * 0.44 / pixelSize | |
| // def coords = (cx,cy) | |
| // print coords | |
| def pointsROI = ROIs.createPointsROI(cx,cy, plane); | |
| def annotation = PathObjects.createAnnotationObject(pointsROI, getPathClass(rowContent[0]) ) | |
| // hierarchy.addPathObject(annotation, true) | |
| QP.addObject(annotation) | |
| } | |
| // there is a bug, I could not merge all the cells with one run. If you want to keep your cells seperately, deactivate the following part. May slow down the visualisation. Test it first. | |
| fireHierarchyUpdate() | |
| for (i = 0; i < 10; i++) { | |
| PathObjectTools.mergePointsForAllClasses(getCurrentHierarchy()) | |
| } | |
| //referenceFile.eachLine { line -> | |
| // def (name, reference) = line.split(/\t/) |
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 characters
| import org.apache.commons.io.FilenameUtils | |
| import qupath.lib.geom.Point2 | |
| def pathSingleton = getCurrentServer().getURIs()[0] | |
| def path = pathSingleton.getPath() | |
| selectAllObjects() | |
| def obj = getSelectedObjects() | |
| if (obj.empty){ | |
| print "importing cells" | |
| // | |
| def slideName = FilenameUtils.getName(path) | |
| def project_path = buildFilePath(PROJECT_BASE_DIR) | |
| def folder = new File(project_path) | |
| def parentFolderPath = folder.getParent() | |
| def fileName = buildFilePath(parentFolderPath, "output", "4_cell_class","CellPos", slideName+"_cellPos.csv") | |
| // def pixel_size = 0.5013 | |
| def pixelSize= getCurrentServer().getPixelCalibration().getAveragedPixelSize() | |
| //def folder = "/Volumes/rsrch6/home/trans_mol_path/yuan_lab/TIER2/anaplasticThyroid_XiaoZhao/aitil/4_cell_class/CellPos" | |
| def plane = getCurrentViewer().getImagePlane() | |
| def imagename = getProjectEntry().getImageName() | |
| //def fileName = buildFilePath(folder,imagename+'_cellPos.csv') | |
| def coords = [] | |
| def skipFirstLine = true | |
| //clearAllObjects() | |
| // Read the TSV file line by line | |
| new File(fileName).eachLine { line -> | |
| if (skipFirstLine) { | |
| skipFirstLine = false | |
| return | |
| } | |
| // print line | |
| // // Process each line here | |
| // | |
| def rowContent = line.split(',') | |
| // | |
| // | |
| double cx = (rowContent[1] as double) *16 *0.44 / pixelSize | |
| double cy = (rowContent[2] as double) *16 *0.44 / pixelSize | |
| // def coords = (cx,cy) | |
| // print coords | |
| def pointsROI = ROIs.createPointsROI(cx,cy, plane); | |
| def annotation = PathObjects.createDetectionObject(pointsROI, getPathClass(rowContent[0]) ) | |
| // hierarchy.addPathObject(annotation, true) | |
| QP.addObject(annotation) | |
| } | |
| // there is a bug, I could not merge all the cells with one run. If you want to keep your cells seperately, deactivate the following part. May slow down the visualisation. Test it first. | |
| //for (i = 0; i < 10; i++) { | |
| // PathObjectTools.mergePointsForAllClasses(getCurrentHierarchy()) | |
| //} | |
| fireHierarchyUpdate() | |
| }else { | |
| print "skipped "+ getCurrentImageName() | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment