QuPath Scripting Help

Hey QuPath community,

I am starting my scripting journey to speed up some very simple tasks that would just be better if I could make this analysis fully automated. (sidenote: I have little programming experience)

What I have so far is a ROI generating script. I run this for the project then more them accordingly. After this step I have another script that runs the cell detection module.

The problem that I am having is that I can’t run the cell detection for the project because the ROI annotation isn’t selected. Is there an easy fix for this?
What I would also like to do is export all the data associated with the project once the analysis is done.

Here are my scripts:
ROI:

import qupath.lib.objects.PathObjects
import qupath.lib.roi.ROIs
import qupath.lib.regions.ImagePlane

int x = 0
int y = 0
def plane = ImagePlane.getPlane(x, y)
def roi = ROIs.createRectangleROI(0, 0, 20000, 8000, plane)
def annotation = PathObjects.createAnnotationObject(roi)
addObject(annotation)


Cell Detection:

def roi = getSelectedROI()
runPlugin('qupath.imagej.detect.cells.WatershedCellDetection', '{"detectionImageBrightfield": "Hematoxylin OD",  "requestedPixelSizeMicrons": 0.5,  "backgroundRadiusMicrons": 8.0,  "medianRadiusMicrons": 0.0,  "sigmaMicrons": 1.5,  "minAreaMicrons": 9.0,  "maxAreaMicrons": 120.0,  "threshold": 0.085,  "maxBackground": 2.0,  "watershedPostProcess": true,  "cellExpansionMicrons": 2.5,  "includeNuclei": true,  "smoothBoundaries": true,  "makeMeasurements": true}');
1 Like

Are you trying to make the ROI the entire image?

If so you can just use this command, which is pulled from the workflow tab"

createSelectAllObject(true);

It will create and select an annotation of the entire image. If you are creating a more specific ROI, I have a feeling that you can edit this command to just SelectAllObjects or something like that, in order to actually select the annotation you have previously made to run the script on. But, I defer to the experts for that, as I too have very little coding experience :slight_smile: good luck!

4 Likes

In addition to the previous point, there are some additional options here that include selecting all annotations, or selecting objects of a certain class.

https://gist.github.com/Svidro/8f9c06e2c8bcae214cdd7aa9afe57c50

2 Likes

As for data export, this is a general script that I use. It exports a rendered image (I use this to show what my classifier looked like), the general annotation data (so the summary measurements of the selected annotation, which in my case is the whole image), and the detection measurements. What’s nice is that you can just comment out or delete any of the three parts that you don’t need for a given project. Note that this is a pastiche of scripts I put together from my own workflows as well as posts on this forum, so credit is not all mine. Hope this helps!

/**
 * Script to export a rendered (RGB) image in QuPath v0.2.0.
 *
 * This is much easier if the image is currently open in the viewer,
 * then see https://qupath.readthedocs.io/en/latest/docs/advanced/exporting_images.html
 *
 * The purpose of this script is to support batch processing (Run -> Run for project (without save)),
 * while using the current viewer settings.
 *
 * Note: This was written for v0.2.0 only. The process may change in later versions.
 *
 * @author Pete Bankhead modified by David Nascari
 */

import qupath.imagej.tools.IJTools
import qupath.lib.gui.images.servers.RenderedImageServer
import qupath.lib.gui.viewer.overlays.HierarchyOverlay
import qupath.lib.regions.RegionRequest

import static qupath.lib.gui.scripting.QPEx.*

// It is important to define the downsample!
// This is required to determine annotation line thicknesses
double downsample = 2

// Add the output file path here
String path = buildFilePath(PROJECT_BASE_DIR, 'rendered', getProjectEntry().getImageName() + '.png')

// Request the current viewer for settings, and current image (which may be used in batch processing)
def viewer = getCurrentViewer()
def imageData = getCurrentImageData()

// Create a rendered server that includes a hierarchy overlay using the current display settings
def server = new RenderedImageServer.Builder(imageData)
    .downsamples(downsample)
    .layers(new HierarchyOverlay(viewer.getImageRegionStore(), viewer.getOverlayOptions(), imageData))
    .build()

// Write or display the rendered image
if (path != null) {
    mkdirs(new File(path).getParent())
    writeImage(server, path)
} else
    IJTools.convertToImagePlus(server, RegionRequest.createInstance(server)).getImage().show()
    print 'Image exported to ' + path
    
    def name2 = getProjectEntry().getImageName() + '.txt'
    def path2 = buildFilePath(PROJECT_BASE_DIR, 'annotation measurements')
    mkdirs(path2)
    path = buildFilePath(path2, name2)
    saveAnnotationMeasurements(path2)
    print 'Results exported to ' + path2

    def name1 = getProjectEntry().getImageName() + '.txt'
    def path1 = buildFilePath(PROJECT_BASE_DIR, 'detection measurements')
    mkdirs(path1)
    path = buildFilePath(path1, name1)
    saveDetectionMeasurements(path1)
    print 'Results exported to ' + path1

Note that there are some parameters you might want to mess around with based on your needs in the image export.

3 Likes

@davidnascari @Research_Associate Thank you so much for all your help! I used the selectAnnotations(); to solve it. Also thanks for the data export script! I’ll pass it on to someone more qualified to decipher all of that.

2 Likes