Created
January 6, 2022 17:29
-
-
Save petebankhead/b0535ccf02fd3a4e0bb497a31944da74 to your computer and use it in GitHub Desktop.
QuPath-Convert nuclei to cells with measurements in QuPath v0.3.x
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
/** | |
* Convert detected nuclei to cells and add measurements. | |
* Written for v0.3.x to answer | |
* https://forum.image.sc/t/is-it-possible-to-modify-the-cell-expansion-parameter-after-cells-have-been-detected/61665 | |
* | |
* Because adding intensity measurements is especially awkward, this should be improved in a future version. | |
* | |
* Note that the cell measurements are *not* equivalent to QuPath's built-in cell detection. | |
* They are calculated in a different way and have different names. | |
* | |
* @author Pete Bankhead | |
*/ | |
// Convert nuclei to cells, with a fixed expansion (here 10 pixels) | |
def detections = getDetectionObjects().findAll {d -> !d.isCell()} | |
def cells = CellTools.detectionsToCells(detections, 10, -1) | |
removeObjects(detections, true) | |
addObjects(cells) | |
// Add measurements (in v0.3 - currently awkward, may be changed/improved in a later version!) | |
import qupath.lib.analysis.features.ObjectMeasurements | |
def imageData = getCurrentImageData() | |
def server = getServer(imageData) | |
clearCellMeasurements() | |
ObjectMeasurements.addShapeMeasurements(cells, server.getPixelCalibration()) | |
double downsample = server.getDownsampleForResolution(0) // May want to compute at a different resolution! | |
def measurements = ObjectMeasurements.Measurements.values() as List | |
def compartments = ObjectMeasurements.Compartments.values() as List | |
cells.parallelStream().forEach { cell -> | |
ObjectMeasurements.addIntensityMeasurements(server, cell, downsample, measurements, compartments) | |
} | |
fireHierarchyUpdate() | |
/** | |
* Get an ImageServer that applies color deconvolution, if needed | |
*/ | |
def getServer(imageData) { | |
def stains = imageData.getColorDeconvolutionStains() | |
if (stains == null) | |
return imageData.getServer() | |
def builder = new qupath.lib.images.servers.TransformedServerBuilder(imageData.getServer()) | |
def stainNumbers = [] | |
for (int s = 1; s <= 3; s++) { | |
if (!stains.getStain(s).isResidual()) | |
stainNumbers.add(s) | |
} | |
builder.deconvolveStains(stains, stainNumbers.stream().mapToInt(i -> i).toArray()); | |
return builder.build() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment