Last active
October 15, 2024 06:03
-
-
Save Svidro/ffb6951e70187de5eb007290f61aea4a to your computer and use it in GitHub Desktop.
Creating objects in QuPath
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
Collections of scripts harvested mainly from Pete, but also picked up from the forums | |
TOC | |
Annotation subtraction example.groovy - An example of creating and subtracing ROIs through scripting | |
Create annotation of fixed size.groovy - see https://petebankhead.github.io/qupath/scripting/2018/03/09/script-create-fixed-size-region.html | |
Create object based on Viewer position.groovy - Creates an object at the Viewer position. In this case a rectangle. Useful if you want | |
to create the exact same size object multiple times and then move it to an area of interest for subsampling. | |
Creating a TMA from script.groovy - Creates a basic TMA, which you would need to then manually position. Easiest to start small and then | |
add rows and columns through the QuPath TMA menu. | |
Creating TMA annotations and set missing by area.groovy - Takes a grid, runs a tissue detection (edit this to your own), and then set | |
missing and delete annotations in any cores below a threshold. | |
TMA Dearrayer from a script.groovy - More options for the TMA dearrayer than through the GUI. Read through the script carefully. | |
Tumor invasion areas.groovy - Generates annotation bands from the surface of the tumor inward. Can be used on tumors on the | |
surface of the tissue (bordering whitespace), but check the link included in the script. | |
Use points to place cells.groovy - mark locations using the Points tool, then place cells of a given class/size on top of each point. | |
Zstack or Time series full image annotations.groovy - Go through all layers of a Z stack or time series and place a full image annotation | |
in each. | |
Zstack or time series annotation copy.groovy - Similar to previous, but take all current annotations, and copy them to ALL OTHER time | |
or Z frames. |
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
//Courtesy of Sara McArdle from the La Jolla Institute | |
//Create multiple bands within tissue, with the distance from the tissue surface (um) determined by the variables below | |
//Adjust class names within the script | |
//0.2.0 | |
double firstRadius = -750 | |
double secondRadius = -850 | |
import qupath.lib.roi.* | |
import qupath.lib.objects.* | |
def imageData = getCurrentImageData() | |
def hierarchy = imageData.getHierarchy() | |
//EDIT THIS LINE TO YOUR TISSUE DETECTION SETTINGS | |
//runPlugin('qupath.imagej.detect.tissue.SimpleTissueDetection2', '{"threshold": 155, "requestedPixelSizeMicrons": 20.0, "minAreaMicrons": 10000.0, "maxHoleAreaMicrons": 1000000.0, "darkBackground": false, "smoothImage": true, "medianCleanup": true, "dilateBoundaries": false, "smoothCoordinates": true, "excludeOnBoundary": false, "singleAnnotation": true}'); | |
selectAnnotations() | |
def outer=getAnnotationObjects().find{p -> (p.getLevel()==1) && (p.isAnnotation() == true)} | |
runPlugin('qupath.lib.plugins.objects.DilateAnnotationPlugin', '{"radiusMicrons": '+firstRadius+', "removeInterior": false, "constrainToParent": true}') | |
def middle=getAnnotationObjects().find{p -> (p.getLevel()==2) && (p.isAnnotation() == true)} | |
//Reselecting the outer object turns out to be very important before running the DilateAnnotationPlugin a second (or third) time. | |
getCurrentHierarchy().getSelectionModel().setSelectedObject(outer) | |
runPlugin('qupath.lib.plugins.objects.DilateAnnotationPlugin', '{"radiusMicrons": '+secondRadius+', "removeInterior": false, "constrainToParent": true}') | |
//write some stuff if you have more than 1 outer object for odd shapes | |
def inner=getAnnotationObjects().find{p -> (p.getLevel()==3) && (p.isAnnotation() == true)} | |
inner.setName("Medulla") | |
def toAdd = [] | |
def toRemove = [] | |
outerRing = PathROIToolsAwt.combineROIs(outer.getROI(), middle.getROI(), PathROIToolsAwt.CombineOp.SUBTRACT) | |
toRemove << middle | |
def orObject=new PathAnnotationObject(outerRing, outer.getPathClass()) | |
orObject.setName("Cortex") | |
toAdd << orObject | |
innerRing = PathROIToolsAwt.combineROIs(middle.getROI(), inner.getROI(), PathROIToolsAwt.CombineOp.SUBTRACT) | |
def irObject = new PathAnnotationObject(innerRing, outer.getPathClass()) | |
irObject.setName("Middle Zone") | |
toAdd << irObject | |
toRemove << outer | |
hierarchy.addPathObjects(toAdd,false) | |
hierarchy.removeObjects(toRemove,true) | |
print "Done" |
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
/** | |
* Create a region annotation with a fixed size in QuPath, based on the current viewer location. | |
* 0.1.2 | |
* @author Pete Bankhead | |
*/ | |
import qupath.lib.objects.PathAnnotationObject | |
import qupath.lib.objects.classes.PathClassFactory | |
import qupath.lib.roi.RectangleROI | |
import qupath.lib.scripting.QPEx | |
// Define the size of the region to create | |
double sizeMicrons = 200.0 | |
// Get main data structures | |
def imageData = QPEx.getCurrentImageData() | |
def server = imageData.getServer() | |
// Convert size in microns to pixels - QuPath ROIs are defined in pixel units of the full-resolution image | |
int sizePixels = Math.round(sizeMicrons / server.getAveragedPixelSizeMicrons()) | |
// Get the current viewer & the location of the pixel currently in the center | |
def viewer = QPEx.getCurrentViewer() | |
double cx = viewer.getCenterPixelX() | |
double cy = viewer.getCenterPixelY() | |
// Create a new Rectangle ROI | |
def roi = new RectangleROI(cx-sizePixels/2, cy-sizePixels/2, sizePixels, sizePixels) | |
// Create & new annotation & add it to the object hierarchy | |
def annotation = new PathAnnotationObject(roi, PathClassFactory.getPathClass("Region")) | |
imageData.getHierarchy().addPathObject(annotation, 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
//0.1.2 and 0.2.0 | |
import qupath.lib.roi.RectangleROI | |
import qupath.lib.objects.PathAnnotationObject | |
// Size in pixels at the base resolution | |
// note that the actual size will be one pixel larger in each dimension | |
int size = 255 | |
// Get center pixel | |
def viewer = getCurrentViewer() | |
int cx = viewer.getCenterPixelX() | |
int cy = viewer.getCenterPixelY() | |
// Create & add annotation | |
def roi = new RectangleROI(cx-size/2, cy-size/2, size, size) | |
def rgb = getColorRGB(50, 50, 200) | |
def pathClass = getPathClass('Other', rgb) | |
def annotation = new PathAnnotationObject(roi, pathClass) | |
addObject(annotation) |
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
//For those times when the automatic TMA dearrayer is having trouble picking up cores (too light/sparse) | |
// from https://github.com/qupath/qupath/issues/77 | |
//0.1.2, metadata would need to be changed for 0.2.0 | |
import qupath.lib.objects.TMACoreObject | |
import qupath.lib.objects.hierarchy.DefaultTMAGrid | |
// Enter the number of horizontal & vertical cores here | |
int numHorizontal = 12 | |
int numVertical = 9 | |
// Enter the core diameter, in millimetres | |
double diameterMM = 1.2 | |
// Convert diameter to pixels | |
double diameterPixels = (diameterMM * 1000) / getCurrentImageData().getServer().getAveragedPixelSizeMicrons() | |
// Get the current ROI | |
def roi = getSelectedROI() | |
// Create the cores | |
def cores = [] | |
double xSpacing = roi.getBoundsWidth() / numHorizontal | |
double ySpacing = roi.getBoundsHeight() / numVertical | |
for (int i = 0; i < numVertical; i++) { | |
for (int j = 0; j < numHorizontal; j++) { | |
double x = roi.getBoundsX() + xSpacing / 2 + xSpacing * j | |
double y = roi.getBoundsY() + ySpacing / 2 + ySpacing * i | |
cores << new TMACoreObject(x, y, diameterPixels, false) | |
} | |
} | |
// Create & set the grid | |
def tmaGrid = new DefaultTMAGrid(cores, numHorizontal) | |
getCurrentHierarchy().setTMAGrid(tmaGrid) |
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
//Set TMA cores where the tissue area is below a threshold to Missing so as to avoid inclusion in future calculations. | |
//0.1.2, but should work with 0.2.0 if the metadata section at the top is adjusted. | |
MINIMUM_AREA_um2 = 30000 | |
def imageData = getCurrentImageData() | |
def server = imageData.getServer() | |
def pixelSize = server.getPixelHeightMicrons() | |
getTMACoreList().each{ | |
it.setMissing(false) | |
} | |
selectTMACores(); | |
runPlugin('qupath.imagej.detect.tissue.SimpleTissueDetection2', '{"threshold": 233, "requestedPixelSizeMicrons": 10.0, "minAreaMicrons": 10000.0, "maxHoleAreaMicrons": 1000000.0, "darkBackground": false, "smoothImage": true, "medianCleanup": true, "dilateBoundaries": false, "smoothCoordinates": true, "excludeOnBoundary": false, "singleAnnotation": true}'); | |
//Potentially alter script to run off of mean intensity in core? | |
//runPlugin('qupath.lib.algorithms.IntensityFeaturesPlugin', '{"pixelSizeMicrons": 2.0, "region": "ROI", "tileSizeMicrons": 25.0, "colorOD": true, "colorStain1": false, "colorStain2": false, "colorStain3": false, "colorRed": false, "colorGreen": false, "colorBlue": false, "colorHue": false, "colorSaturation": false, "colorBrightness": false, "doMean": false, "doStdDev": false, "doMinMax": false, "doMedian": false, "doHaralick": false, "haralickDistance": 1, "haralickBins": 32}'); | |
getTMACoreList().each{ | |
it.setMissing(true) | |
list = it.getChildObjects() | |
println(list) | |
if ( list.size() > 0){ | |
double total = 0 | |
for (object in list) { | |
total = total+object.getROI().getArea() | |
} | |
total = total*pixelSize*pixelSize | |
println(it.getName()+ " list "+list.size()+ "total "+total) | |
if ( total > MINIMUM_AREA_um2 ){ | |
it.setMissing(false) | |
} else {removeObjects(list, true)} | |
} | |
} | |
fireHierarchyUpdate() | |
println("done") |
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
// https://forum.image.sc/t/nuclear-dab-disrupts-stardist-detection-of-haematoxylin-in-qupath/50156/2 | |
import qupath.opencv.ops.ImageOp | |
import qupath.opencv.tools.OpenCVTools | |
import org.bytedeco.opencv.opencv_core.Mat | |
import org.bytedeco.opencv.global.opencv_core | |
import static qupath.lib.gui.scripting.QPEx.* | |
import qupath.tensorflow.stardist.StarDist2D | |
import qupath.lib.images.servers.* | |
// Specify the model directory (you will need to change this!) | |
def pathModel = '/path/to/dsb2018_heavy_augment' | |
double originalPixelSize = getCurrentImageData().getServer().getPixelCalibration().getAveragedPixelSizeMicrons(); | |
def stardist = StarDist2D.builder(pathModel) | |
.threshold(0.5) // Probability (detection) threshold | |
.channels( | |
ColorTransforms.createColorDeconvolvedChannel(getCurrentImageData().getColorDeconvolutionStains(), 1), | |
ColorTransforms.createColorDeconvolvedChannel(getCurrentImageData().getColorDeconvolutionStains(), 2) | |
) // Select detection channel | |
.preprocess(new AddChannelsOp()) | |
.normalizePercentiles(1, 99) // Percentile normalization | |
.pixelSize(originalPixelSize) // Resolution for detection | |
.cellExpansion(3.0) // Approximate cells based upon nucleus expansion | |
.cellConstrainScale(1.5) // Constrain cell expansion using nucleus size | |
.measureShape() // Add shape measurements | |
.measureIntensity() // Add cell measurements (in all compartments) | |
.includeProbability(true) // Add probability as a measurement (enables later filtering) | |
.build() | |
// Run detection for the selected objects | |
def imageData = getCurrentImageData() | |
def pathObjects = getSelectedObjects() | |
if (pathObjects.isEmpty()) { | |
Dialogs.showErrorMessage("StarDist", "Please select a parent object!") | |
return | |
} | |
stardist.detectObjects(imageData, pathObjects) | |
println 'Done!' | |
class AddChannelsOp implements ImageOp { | |
@Override | |
public Mat apply(Mat input) { | |
def channels = OpenCVTools.splitChannels(input) | |
if (channels.size() == 1) | |
return input | |
def sum = opencv_core.add(channels[0], channels[1]) | |
for (int i = 2; i < channels.size(); i++) | |
sum = opencv_core.add(sum, channels[i]) | |
return sum.asMat() | |
} | |
} |
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
/* 0.2.3, https://forum.image.sc/t/tma-dearrayer-problem/48234/4 | |
* Run QuPath's TMA dearrayer at a different resolution. | |
* This can give a bit more control over the output if the original dearraying fails. | |
* | |
* @author Pete Bankhead | |
*/ | |
// Change this to adjust the resolution at which cores are detected | |
// Lower values mean the dearraying is done on a larger image (and will be slower) | |
double requestedPixelSize = 10 | |
// Adjust these for other detection parameters | |
double coreDiameter = 1200 | |
double roiScaleFactor = 1.05 | |
def horizontalLabels = 'A-J' | |
def verticalLabels = '1-16' | |
boolean horizontalLabelFirst = 100 | |
double densityThreshold = 0.05 | |
boolean isFluorescence = false | |
// Actually do the dearraying | |
import qupath.imagej.detect.dearray.TMADearrayerPluginIJ.Dearrayer | |
def dearrayer = new Dearrayer() | |
def server = getCurrentServer() | |
double downsample = requestedPixelSize / server.getPixelCalibration().getAveragedPixelSize() | |
double fullCoreDiameterPx = coreDiameter / server.getPixelCalibration().getAveragedPixelSize() | |
def request = RegionRequest.createInstance(server, downsample) | |
dearrayer.ip = IJTools.convertToImagePlus(server, request).getImage().getProcessor() | |
def tmaGrid = dearrayer.doDearraying( | |
fullCoreDiameterPx, | |
downsample, | |
densityThreshold, | |
roiScaleFactor, | |
isFluorescence, | |
PathObjectTools.parseTMALabelString(horizontalLabels), | |
PathObjectTools.parseTMALabelString(verticalLabels), | |
horizontalLabelFirst | |
) | |
getCurrentHierarchy().setTMAGrid(tmaGrid) | |
println 'Done! ' + println tmaGrid |
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
/** | |
* Script to help with annotating tumor regions, chopping increasing chunks into the tumor. | |
* SEE THREAD HERE FOR DESCRIPTION ON USE: | |
* Here, each of the margin regions is approximately 100 microns in width. | |
* Should work with both 1.2 and 0.2.0m2 due to code from Thomas Kilvaer found here: https://petebankhead.github.io/qupath/scripts/2018/08/08/three-regions.html | |
* | |
* @author Pete Bankhead | |
* @mangled by Svidro | |
*/ | |
import qupath.lib.common.GeneralTools | |
import qupath.lib.objects.PathAnnotationObject | |
import qupath.lib.objects.PathObject | |
import qupath.lib.roi.PathROIToolsAwt | |
import java.awt.Rectangle | |
import java.awt.geom.Area | |
//----- | |
// Some things you might want to change | |
// How much to expand each region | |
double expandMarginMicrons = 100.0 | |
// How many times you want to chop into your annotation. Edit color script around line 115 if you go over 5 | |
int howManyTimes = 4 | |
// Define the colors | |
// Inner layers are given scripted colors, but gretaer than 6 or 7 layers may require adjustments | |
def colorOuterMargin = getColorRGB(0, 200, 0) | |
// Choose whether to lock the annotations or not (it's generally a good idea to avoid accidentally moving them) | |
def lockAnnotations = true | |
//----- | |
// Extract the main info we need | |
def imageData = getCurrentImageData() | |
def hierarchy = imageData.getHierarchy() | |
def server = imageData.getServer() | |
// We need the pixel size | |
if (!server.hasPixelSizeMicrons()) { | |
print 'We need the pixel size information here!' | |
return | |
} | |
if (!GeneralTools.almostTheSame(server.getPixelWidthMicrons(), server.getPixelHeightMicrons(), 0.0001)) { | |
print 'Warning! The pixel width & height are different; the average of both will be used' | |
} | |
// Get annotation & detections | |
def annotations = getAnnotationObjects() | |
def selected = getSelectedObject() | |
if (selected == null || !selected.isAnnotation()) { | |
print 'Please select an annotation object!' | |
return | |
} | |
// We need one selected annotation as a starting point; if we have other annotations, they will constrain the output | |
annotations.remove(selected) | |
// If we have at most one other annotation, it represents the tissue | |
Area areaTissue | |
PathObject tissueAnnotation | |
if (annotations.isEmpty()) { | |
areaTissue = new Area(new Rectangle(0, 0, server.getWidth(), server.getHeight())) | |
} else if (annotations.size() == 1) { | |
tissueAnnotation = annotations.get(0) | |
areaTissue = PathROIToolsAwt.getArea(tissueAnnotation.getROI()) | |
} else { | |
print 'Sorry, this script only support one selected annotation for the tumor region, and at most one other annotation to constrain the expansion' | |
return | |
} | |
println("Working, give it some time") | |
// Calculate how much to expand | |
double expandPixels = expandMarginMicrons / server.getAveragedPixelSizeMicrons() | |
def roiOriginal = selected.getROI() | |
def areaTumor = PathROIToolsAwt.getArea(roiOriginal) | |
// Get the outer margin area | |
if (getQuPath().getBuildString().split()[1]<"0.2.0-m2"){ | |
def areaOuter = PathROIToolsAwt.shapeMorphology(areaTumor, expandPixels) | |
}else {areaOuter = PathROIToolsAwt.getArea(PathROIToolsAwt.roiMorphology(roiOriginal, expandPixels))} | |
areaOuter.subtract(areaTumor) | |
areaOuter.intersect(areaTissue) | |
def roiOuter = PathROIToolsAwt.getShapeROI(areaOuter, roiOriginal.getC(), roiOriginal.getZ(), roiOriginal.getT()) | |
def annotationOuter = new PathAnnotationObject(roiOuter) | |
annotationOuter.setName("Outer margin") | |
annotationOuter.setColorRGB(colorOuterMargin) | |
innerAnnotations = [] | |
innerAnnotations << annotationOuter | |
for (i=0; i<howManyTimes;i++){ | |
//select the current expansion, which the first time is outside of the tumor, then expand it and intersect it | |
currentArea = PathROIToolsAwt.getArea(innerAnnotations[innerAnnotations.size()-1].getROI()) | |
if (getQuPath().getBuildString().split()[1]<"0.2.0-m2"){ | |
areaExpansion = PathROIToolsAwt.shapeMorphology(currentArea, expandPixels) | |
}else {areaExpansion = PathROIToolsAwt.getArea(PathROIToolsAwt.roiMorphology(innerAnnotations[innerAnnotations.size()-1].getROI(), expandPixels))} | |
areaExpansion.intersect(areaTumor) | |
areaExpansion.intersect(areaTissue) | |
if(i>=1){ | |
for (k=1; k<=i;k++){ | |
areaExpansion.subtract(PathROIToolsAwt.getArea(innerAnnotations[innerAnnotations.size()-k].getROI())) | |
} | |
} | |
roiExpansion = PathROIToolsAwt.getShapeROI(areaExpansion, roiOriginal.getC(), roiOriginal.getZ(), roiOriginal.getT()) | |
j = i+1 | |
annotationExpansion = new PathAnnotationObject(roiExpansion) | |
int nameValue = j*expandMarginMicrons | |
annotationExpansion.setName("Inner margin "+nameValue+" microns") | |
annotationExpansion.setColorRGB(getColorRGB(20*i, 40*i, 200-30*i)) | |
innerAnnotations << annotationExpansion | |
} | |
// Add the annotations | |
hierarchy.getSelectionModel().clearSelection() | |
//hierarchy.removeObject(selected, true) | |
def annotationsToAdd = innerAnnotations; | |
annotationsToAdd.each {it.setLocked(lockAnnotations)} | |
if (tissueAnnotation == null) { | |
hierarchy.addPathObjects(annotationsToAdd, false) | |
} else { | |
tissueAnnotation.addPathObjects(annotationsToAdd) | |
hierarchy.fireHierarchyChangedEvent(this, tissueAnnotation) | |
if (lockAnnotations) | |
tissueAnnotation.setLocked(true) | |
} | |
println("Done! Wheeeee!") |
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
//0.1.2 only, create detections from points. | |
//See 0.2.3 below | |
import qupath.lib.roi.EllipseROI; | |
import qupath.lib.objects.PathDetectionObject | |
points = getAnnotationObjects().findAll{it.isPoint() } | |
//Cycle through each points object (which is a collection of points) | |
points.each{ | |
//Cycle through all points within a points object | |
it.getROI().getPointList().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 = new EllipseROI(x-size/2,y-size/2,size,size, 0,0,0) | |
pathClass = getPathClass("FakeCell") | |
def aCell = new PathDetectionObject(roi, pathClass) | |
addObject(aCell) | |
} | |
} | |
//remove points if desired. | |
removeObjects(points, false) | |
//0.2.3 version | |
import qupath.lib.objects.PathDetectionObject | |
points = getAnnotationObjects().findAll{it.getROI().isPoint() } | |
//Cycle through each points object (which is a collection of points) | |
points.each{ | |
plane = it.getROI().getImagePlane() | |
pathClass = it.getPathClass() | |
//Cycle through all points within a points object | |
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, plane) | |
//pathClass = getPathClass("FakeCell") | |
def aCell = new PathDetectionObject(roi, pathClass) | |
addObject(aCell) | |
} | |
} | |
resolveHierarchy() | |
//remove points if desired. | |
removeObjects(points, 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
//0.1.2 | |
//should work for Zstacks OR time series | |
//Copies ALL existing annotations to ALL other T or Z slices. Use getAnnotationObjects().findAll{it-> if(something)} to limit this | |
import qupath.lib.objects.PathAnnotationObject | |
import qupath.lib.roi.PathROIToolsAwt | |
hierarchy = getCurrentHierarchy() | |
def imageData = getCurrentImageData() | |
def server = imageData.getServer() | |
def xdist = server.getWidth() | |
def ydist = server.getHeight() | |
def annotations = getAnnotationObjects() | |
if (server.nZSlices() >0){ | |
0.upto(server.nZSlices()-1){ | |
for (annotation in annotations){ | |
def roi = annotation.getROI() | |
def shape = PathROIToolsAwt.getShape(roi) | |
// There is a method to create a ROI from a shape which allows us to (finally) set the Z (or T) | |
def roi2 = PathROIToolsAwt.getShapeROI(shape, -1, it, roi.getT(), 0.5) | |
// We can now make a new annotation | |
def annotation2 = new PathAnnotationObject(roi2) | |
// Add it to the current hierarchy. When we move in Z to the desired slice, we should see the annotation | |
if (roi2.getZ() != roi.getZ()) | |
hierarchy.addPathObject(annotation2, false); | |
} | |
} | |
} | |
if (server.nTimepoints() >1){ | |
0.upto(server.nTimepoints()-1){ | |
for (annotation in annotations){ | |
def roi = annotation.getROI() | |
def shape = PathROIToolsAwt.getShape(roi) | |
// There is a method to create a ROI from a shape which allows us to (finally) set the Z (or T) | |
def roi2 = PathROIToolsAwt.getShapeROI(shape, -1, roi.getZ(), it) | |
// We can now make a new annotation | |
def annotation2 = new PathAnnotationObject(roi2) | |
// Add it to the current hierarchy. When we move in T to the desired slice, we should see the annotation | |
if (roi2.getT() != roi.getT()) | |
hierarchy.addPathObject(annotation2, 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
//See below for 0.2.3 version | |
//0.1.2 | |
//should work for Zstacks OR time series | |
//Creates a full image annotation in each frame, which can then be used to generate detections. | |
import qupath.lib.roi.RectangleROI | |
import qupath.lib.objects.PathAnnotationObject | |
hierarchy = getCurrentHierarchy() | |
def imageData = getCurrentImageData() | |
def server = imageData.getServer() | |
def xdist = server.getWidth() | |
def ydist = server.getHeight() | |
clearAllObjects() | |
if (server.nZSlices() >0){ | |
0.upto(server.nZSlices()-1){ | |
frame = new PathAnnotationObject(new RectangleROI(0,0,xdist,ydist,-1,it,0)); | |
addObject(frame); | |
} | |
} | |
if (server.nTimepoints() >0){ | |
0.upto(server.nTimepoints()-1){ | |
frame = new PathAnnotationObject(new RectangleROI(0,0,xdist,ydist,-1,0,it)); | |
addObject(frame); | |
} | |
} | |
//0.2.3 version | |
//should work for Zstacks OR time series | |
//Creates a full image annotation in each frame, which can then be used to generate detections. | |
import qupath.lib.roi.RectangleROI | |
import qupath.lib.objects.PathAnnotationObject | |
hierarchy = getCurrentHierarchy() | |
def imageData = getCurrentImageData() | |
def server = imageData.getServer() | |
def xdist = server.getWidth() | |
def ydist = server.getHeight() | |
clearAllObjects() | |
if (server.nZSlices() >0){ | |
0.upto(server.nZSlices()-1){ | |
frame = PathObjects.createAnnotationObject(ROIs.createRectangleROI(0,0,xdist,ydist,ImagePlane.getPlane(it,0))); | |
addObject(frame); | |
} | |
} | |
if (server.nTimepoints() >0){ | |
0.upto(server.nTimepoints()-1){ | |
frame = PathObjects.createAnnotationObject(ROIs.createRectangleROI(0,0,xdist,ydist,ImagePlane.getPlane(0,it))); | |
addObject(frame); | |
} | |
} | |
selectAnnotations() | |
//cell detection here |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment