-
-
Save NicoKiaru/f45f56e3ff2d1fb708821c110fbdee62 to your computer and use it in GitHub Desktop.
| /** | |
| * ABBA Script : performs a cell detection on the root node annotation | |
| * imported from ABBA and restores the child objects after the detection has been performed | |
| * To use and modify like you need / want | |
| * You need to have imported the regions before running this script. See https://gist.github.com/NicoKiaru/723d8e628a3bb03902bb3f0f2f0fa466 for instance | |
| * See https://biop.github.io/ijp-imagetoatlas/ | |
| * Author: Olivier Burri, Nicolas Chiaruttini, BIOP, EPFL | |
| * Date: 2022-01-26 | |
| */ | |
| // setImageType('FLUORESCENCE'); // if your image is fluorescent | |
| // If you just want to clear the detections and keep the previously ABBA imported annotations | |
| clearDetections() | |
| // or, if you want to reset and re-import all annotations from ABBA | |
| // clearAllObjects(); | |
| // qupath.ext.biop.abba.AtlasTools.loadWarpedAtlasAnnotations(getCurrentImageData(), "acronym", true); | |
| def project = getProject() | |
| // We want to run cell detection only once on the entire brain, which means we need to select the Root node. We can find it by name | |
| def root = getAnnotationObjects().find{ it.getName().equals( 'Root' ) } | |
| // Duplicate root node. It is a bit contrived but this is how you can copy an annotation | |
| def regionMeasured = PathObjectTools.transformObject( root, null, true ) | |
| // Temporary name | |
| regionMeasured.setName( "Measured Region" ) | |
| // Need to add it to the current hierarchy | |
| addObject( regionMeasured ) | |
| // So that we can select it | |
| setSelectedObject( regionMeasured ) | |
| // RUN CELL DETECTION | |
| // Modify the line below by inserting your cell detection plugin line | |
| // ********************************************************************* | |
| // ********************************************************************* | |
| runPlugin( 'qupath.imagej.detect.cells.WatershedCellDetection', | |
| '{"detectionImage": "FL CY3", "requestedPixelSizeMicrons": 2.0, "backgroundRadiusMicrons": 8.0, "medianRadiusMicrons": 0.0, "sigmaMicrons": 2.0, "minAreaMicrons": 20.0, "maxAreaMicrons": 400.0, "threshold": 200.0, "watershedPostProcess": true, "cellExpansionMicrons": 0.0, "includeNuclei": true, "smoothBoundaries": true, "makeMeasurements": true}') | |
| // ********************************************************************* | |
| // ********************************************************************* | |
| // We no longer need the object we used for detection. We remove it but keep the child objects, which are the cells | |
| removeObject( regionMeasured, true ) | |
| // We can now add the cells to the original root object | |
| def cells = getDetectionObjects() | |
| root.addPathObjects( cells ) | |
| // Update the view for the user | |
| fireHierarchyUpdate() | |
| // From here, the rest of the script adds to all cells their coordinates in the reference atlas | |
| // to their measurement list | |
| // Get ABBA transform file located in entry path | |
| def targetEntry = getProjectEntry() | |
| def targetEntryPath = targetEntry.getEntryPath() | |
| def fTransform = new File(targetEntryPath.toFile(), "ABBA-Transform-Adult Mouse Brain - Allen Brain Atlas V3p1.json" ) | |
| if ( !fTransform.exists() ) { | |
| logger.error( "ABBA transformation file not found for entry {}", targetEntry ) | |
| return | |
| } | |
| def pixelToCCFTransform = Warpy.getRealTransform( fTransform ).inverse() // Needs the inverse transform | |
| getDetectionObjects().forEach{ detection -> | |
| def ccfCoordinates = new RealPoint(3) | |
| def ml = detection.getMeasurementList() | |
| ccfCoordinates.setPosition( [detection.getROI().getCentroidX(),detection.getROI().getCentroidY(), 0] as double[] ) | |
| // The Z=0 pixel coordinate is automatically transformed to the right atlas position in Z thanks to the fact that the slice | |
| // position is already known by the transform | |
| // This applies the transform in place to cffCoordinates | |
| pixelToCCFTransform.apply(ccfCoordinates, ccfCoordinates) | |
| // Fianlly: Add the coordinates as measurements | |
| ml.addMeasurement("Allen CCFv3 X mm", ccfCoordinates.getDoublePosition(0) ) | |
| ml.addMeasurement("Allen CCFv3 Y mm", ccfCoordinates.getDoublePosition(1) ) | |
| ml.addMeasurement("Allen CCFv3 Z mm", ccfCoordinates.getDoublePosition(2) ) | |
| ml.addMeasurement("Count: Num Spots", 1 ) | |
| } | |
| // imports | |
| import qupath.ext.biop.warpy.* | |
| import net.imglib2.RealPoint | |
| import qupath.lib.measurements.MeasurementList | |
| import qupath.lib.objects.PathObjectTools | |
| import qupath.lib.objects.PathObjects | |
| import qupath.lib.objects.PathCellObject | |
| import qupath.lib.objects.PathObject | |
| import qupath.lib.objects.PathDetectionObject | |
| import qupath.lib.roi.ROIs | |
| import qupath.lib.regions.ImagePlane |
Hi, I found there are some mistakes in my coding.
1, during ABBA annotation importing: qupath.ext.biop.abba.AtlasTools.loadWarpedAtlasAnnotations(getCurrentImageData(), "acronym", false);, false should be changed to true
2, during cell detection: in my case, "ABBA-Transform-Adult Mouse Brain - Allen Brain Atlas V3.json" should be changed to "ABBA-Transform-Adult Mouse Brain - Allen Brain Atlas V3p1.json"
3, I by order ran the script 0,1,2 and happened to meet some problems, but i simple integrated all the script with some codes deleted, thing went more smooth.
My workflow code like this, basically they are based on NicoKiaru's scripts:
// imports
import qupath.ext.biop.warpy.*
import net.imglib2.RealPoint
import qupath.lib.measurements.MeasurementList
import qupath.lib.objects.PathObjectTools
// import annotation from ABBA
setImageType('FLUORESCENCE');
clearAllObjects();
qupath.ext.biop.abba.AtlasTools.loadWarpedAtlasAnnotations(getCurrentImageData(), "acronym", true);
// cell detection
clearDetections()
def project = getProject()
// We want to run cell detection only once on the entire brain, which means we need to select the Root node. We can find it by name
def root = getAnnotationObjects().find{ it.getName().equals( 'Root' ) }
// Duplicate root node. It is a bit contrived but this is how you can copy an annotation
def regionMeasured = PathObjectTools.transformObject( root, null, true )
// Temporary name
regionMeasured.setName( "Measured Region" )
// Need to add it to the current hierarchy
addObject( regionMeasured )
// So that we can select it
setSelectedObject( regionMeasured )
// RUN CELL DETECTION
// Modify the line below by inserting your cell detection plugin line
// *********************************************************************
// *********************************************************************
runPlugin( 'qupath.imagej.detect.cells.WatershedCellDetection',
'{"detectionImage": "Cy3", "requestedPixelSizeMicrons": 1.0, "backgroundRadiusMicrons": 8.0, "medianRadiusMicrons": 0.0, "sigmaMicrons": 2.0, "minAreaMicrons": 20.0, "maxAreaMicrons": 200.0, "threshold": 50.0, "watershedPostProcess": true, "cellExpansionMicrons": 10.0, "includeNuclei": True, "smoothBoundaries": true, "makeMeasurements": true}')
// *********************************************************************
// *********************************************************************
// re-loading annotation
qupath.ext.biop.abba.AtlasTools.loadWarpedAtlasAnnotations(getCurrentImageData(), "acronym", true);
// Get ABBA transform file located in entry path
def targetEntry = getProjectEntry()
def targetEntryPath = targetEntry.getEntryPath()
def fTransform = new File(targetEntryPath.toFile(), "ABBA-Transform-Adult Mouse Brain - Allen Brain Atlas V3p1.json" )
if ( !fTransform.exists() ) {
logger.error( "ABBA transformation file not found for entry {}", targetEntry )
return
}
def pixelToCCFTransform = Warpy.getRealTransform( fTransform ).inverse() // Needs the inverse transform
getDetectionObjects().forEach{ detection ->
def ccfCoordinates = new RealPoint(3)
def ml = detection.getMeasurementList()
ccfCoordinates.setPosition( [detection.getROI().getCentroidX(),detection.getROI().getCentroidY(), 0] as double[] )
// The Z=0 pixel coordinate is automatically transformed to the right atlas position in Z thanks to the fact that the slice
// position is already known by the transform
// This applies the transform in place to cffCoordinates
pixelToCCFTransform.apply(ccfCoordinates, ccfCoordinates)
// Fianlly: Add the coordinates as measurements
ml.addMeasurement("Allen CCFv3 X mm", ccfCoordinates.getDoublePosition(0) )
ml.addMeasurement("Allen CCFv3 Y mm", ccfCoordinates.getDoublePosition(1) )
ml.addMeasurement("Allen CCFv3 Z mm", ccfCoordinates.getDoublePosition(2) )
ml.addMeasurement("Count: Num Spots", 1 )
}
// To execute before:
// 0 - https://gist.github.com/NicoKiaru/723d8e628a3bb03902bb3f0f2f0fa466
// 1 - https://gist.github.com/NicoKiaru/f45f56e3ff2d1fb708821c110fbdee62
// save annotations
File directory = new File(buildFilePath(PROJECT_BASE_DIR,'export'));
directory.mkdirs();
def imageData = getCurrentImageData();
imageName = ServerTools.getDisplayableImageName(imageData.getServer())
def filename = imageName//.take(imageName.indexOf('.'))
saveMeasurements(
imageData,
PathDetectionObject.class,
buildFilePath(directory.toString(),filename + '.tsv'),
"Class",
"Allen CCFv3 X mm",
"Allen CCFv3 Y mm",
"Allen CCFv3 Z mm",
"Count: Num Spots"
);
import qupath.lib.objects.PathObjects
import qupath.lib.objects.PathObject
import qupath.lib.objects.PathDetectionObject
import qupath.lib.objects.PathCellObject
import qupath.lib.roi.ROIs
import qupath.lib.regions.ImagePlane
import qupath.lib.measurements.MeasurementList
import qupath.lib.objects.PathCellObject
Thanks a lot @AthiemoneZero , I'll update my script based on your modifications, indeed some parts are not up to date

It is really tricky somehow. I reopen my project, re-export on ABBA, and re-import using codes on the document:
setImageType('FLUORESCENCE'); clearAllObjects(); qupath.ext.biop.abba.AtlasTools.loadWarpedAtlasAnnotations(getCurrentImageData(), "acronym", false);The entry folder this time shows the ABBA files. Strangely
But this time it raise a new error:
This could be sovled by changing
falseintotruewithin this codequpath.ext.biop.abba.AtlasTools.loadWarpedAtlasAnnotations(getCurrentImageData(), "acronym", false);but again when going to run 'DetectCellsABBA.groovy' code, the bug is still here:
Indeed, the ABBA transformation file is on the folder.
