QuPath Measurement Maps Image Export Script

Hey QuPath community,

I am using the measurement maps to visualize the circularity of the nucleus in my region of interest. I’d like to export this using scripting but can’t figure out how to call the measurement maps command up to create this. I can do this manually using the export images - Rendered RGB (with overlays).

Is there a way to call this specific measurement map, visualize it on the ROI, and then export this?
I am also still having trouble exporting images with scripting in general but I am still looking into it and wont give up.

Any and all help is greatly appreciated! Thanks!

I think most exporting with the RGB overlay is most easily accomplished with an image open so that the script “knows” what you want to do as far as the color maps. Then, you need to use the correct server, much like the labeled image server.
The official documentation gives an example of writing out a rendered image using:
https://qupath.readthedocs.io/en/latest/docs/advanced/exporting_images.html#images-regions
This is probably the best way to handle what you are doing at the moment.
Here is a version that was edited for specific ROIs - in this case a TMA.

Alternatively:
Digging through my list here, I found:

2 Likes

@ahouston Something like this should be close:

import qupath.lib.gui.tools.MeasurementMapper
import qupath.lib.gui.images.servers.RenderedImageServer

// Define the color map name
String colorMapName = 'Magma'

// Load a color mapper
def colorMapper = MeasurementMapper.loadColorMappers().find {it.name == colorMapName}
println colorMapper

// Define measurement & display range
def name = "Nucleus: Circularity" // Set to null to reset
double minValue = 0.0
double maxValue = 1.0

// Request current viewer & objects
def viewer = getCurrentViewer()
def options = viewer.getOverlayOptions()
def detections = getDetectionObjects()

// Update the display
if (name) {
    print String.format('Setting measurement map: %s (%.2f - %.2f)', name, minValue, maxValue)
    def mapper = new MeasurementMapper(colorMapper, name, detections)
    mapper.setDisplayMinValue(minValue)
    mapper.setDisplayMaxValue(maxValue)
    options.setMeasurementMapper(mapper)
} else {
    print 'Resetting measurement map'
    options.setMeasurementMapper(null)
}

// Now export the rendered image
import qupath.imagej.tools.IJTools
import qupath.lib.gui.images.servers.RenderedImageServer
import qupath.lib.gui.viewer.overlays.HierarchyOverlay
import qupath.lib.regions.RegionRequest

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

// Add the output file path here
String path = buildFilePath(PROJECT_BASE_DIR, 'rendered')
mkdirs(path)

// Request the current viewer for settings, and current image (which may be used in batch processing)
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(null, options, imageData))
    .build()
    
// Write or display the rendered image
int count = 0
for (annotation in getAnnotationObjects()) {
    count++
    def imageName = getProjectEntry().getImageName() + count + '.png'
    def path2 = buildFilePath(path, imageName)
    def region = RegionRequest.createInstance(server.getPath(), downsample, annotation.getROI())
    writeImageRegion(server, region, path2)
}

It’s a bit ugly, since it’s really two scripts glued together and tweaked a little bit. The originals are

Be sure to look out for the name, colorMapName and downsample values, which probably will need to be changed.

This works using Run for project, but you might be able to drop the whole first half of the script if you set the measurement mapper in the viewer manually.

2 Likes

@petebankhead Here is the original post I was referencing

A million thanks Pete!!! Works perfectly!

1 Like