double dx = -50
double dy = 100
for (pathObject in getAllObjects()) {
if (pathObject.hasROI())
pathObject.setROI(pathObject.getROI().translate(dx, dy))
}
fireHierarchyUpdate()
import qupath.lib.objects.*
import qupath.lib.roi.*
def annotations = getAnnotationObjects()
for (j = 0; j < annotations.size; j++)
{
def roi = annotations[j].getROI()
def roiPoints = annotations[j].getROI().getPolygonPoints()
def roiPointsArx = roiPoints.x.toArray() //convert each point to an array
def roiPointsAry = roiPoints.y.toArray() //for x and y coordinates
//the centroid of the roi - which will be used to center the shape around (0,0)
double centroidX = roi.getCentroidX()
double centroidY = roi.getCentroidY()
double deg = -4
double degrees = Math.toRadians(deg) // sets the number of degrees to rotate
for (i= 0; i< roiPointsAry.length; i++)
{
// correct the center to 0
roiPointsArx[i] = roiPointsArx[i] - centroidX
roiPointsAry[i] = roiPointsAry[i] - centroidY
//Makes prime placeholders, which allows the calculations x'=xcos(theta)-ysin(theta), y'=ycos(theta)+xsin(theta) to be performed
double newPointX = roiPointsArx[i]
double newPointY = roiPointsAry[i]
// then rotate
roiPointsArx[i] = (newPointX * Math.cos(degrees)) - (newPointY * Math.sin(degrees))
roiPointsAry[i] = (newPointY * Math.cos(degrees)) + (newPointX * Math.sin(degrees))
// then move it back
roiPointsArx[i] = roiPointsArx[i] + centroidX
roiPointsAry[i] = roiPointsAry[i] + centroidY
}
// then to convert it back into an objectdef xFloat = roiPointsArx as float[]
def yFloat = roiPointsAry as float[]
def roiNew = new PolygonROI(xFloat, yFloat, -1, 0, 0)
def pathObjectNew = new PathAnnotationObject(roiNew)
addObject(pathObjectNew)
}
selectObjects { p -> p.getPathClass() == getPathClass("ToBeDeleted") && p.isAnnotation() };
An example of assigning classes at: https://groups.google.com/forum/#!searchin/qupath-users/PathClassFactory%7Csort:date/qupath-users/DIJHmk-ntB0/5eyiVG41BwAJ
Putting the measurements into each annotation could be done similar to https://groups.google.com/forum/#!searchin/qupath-users/getMeasurementList%7Csort:date/qupath-users/NJPNrNuxwHE/uw3lhUgTAAAJexcept with the detections swapped to annotations. This would be better if you already have classes assigned and do not want to mess with them. Just make the new measurement "Delete" and then 1 or 0.
def roiPointsArx = roiPoints.x.toArray() //convert each point to an array
def roiPointsAry = roiPoints.y.toArray() //for x and y coordinates
removeObjects(annotations, true)
Is it possible to calculate SIFT registration data between two images (same slide, different markers) and apply it to transform annotations and detections during the transfer from the source image to the other? I mean incorporating SIFT feature into your script involving interactive image alignment feature. It would be a game changer in multiplex chromogenic IHC studies.