Qupath toggle show/hide detections / annotations by scripting?

Hi guys,

I am using Qupath for analysis of multiple images. One of the analyses draws an annotation.
To quickly see the effect of the analyses, I am using a script to export a render of the viewer using a script I found online (or maybe even on this forum) to run through the results, as opening each image in Qupath one by one takes a lot of loading time.

However, as the analysis adds detections and annotations to the image, it is sometimes difficult to see the exact results. Therefore I would like to make two exports by script: one with only the source image (detections and annotations hidden) and one with the generated annotations in place.

When you are in the viewer, I can quickly hide/show annotations through the shortcuts “D” and “A”.
Can these functions also be reached through a script?
I am looking for something like viewer.showDetections = 'true' so that I can toggle annotations and detections for the rendered export

I’ve also tried looking in the QuPath source code to see if I could find a solution in there. However, I’m not familiar enough with coding to get a correct answer in that way.

Thanks in advance for your help!

Best,
Justin

//Exporting the images to view the results
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 = 5

// 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()

// Create a rendered server that includes a hierarchy overlay using the current display settings
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()

Hi @JSNL,

Can you use any of the recipes in the docs?

Basically, if you are happy writing the raw pixel values then you can use writeImage and avoid worrying about rendered images entirely.

For example, you can take what you have and add a line

writeImage(imageData.getServer(), path2)

assuming you’ve defined path2 as something different from path.

If you do need to export a rendered image as in your original question (e.g. because you have a fluorescence image and need to convert the channels to RGB) then you control the detections/annotations via an OverlayOptions object. Here’s a quite script that shows you how to access this and prints the available methods:

def overlayOptions = getCurrentViewer().getOverlayOptions()
print describe(overlayOptions)

However that might get a bit more complicated – writeImage should be easier.

3 Likes

Wow thanks Pete for both suggestions. This is really nice! and works.
I’ve never known there was a ‘describe’ function, that’s really handy also for other purposes.

On a related note, let’s say I want to hide annotations of a certain class in the rendered view.
Is it possible to show or hide a class from the script editor too? (just the way you can show/hide class in viewer by right-clicking the class in the ‘annotations’ tab?)

Best, Justin

1 Like

Glad it works! Hiding specific classes is done via the OverlayOptions as well, e.g.

def overlayOptions = getCurrentViewer().getOverlayOptions()
overlayOptions.hiddenClassesProperty().addAll(
    getPathClass('Tumor'),
    getPathClass('Stroma')    
)
3 Likes