Export Delaunay tessellations for tumor and stroma

Hi everyone,

I am trying to analyze the shape features of tumor areas using QuPath’s Delaunay tessellation algorithm:

Analyze --> Spatial Analysis --> Delaunay cluster features 2D

This QuPath function works fine on multichannel Zeiss *.czi images with one Z-plane. However, I am not so much interested in the Delaunay measurements as such but more in the shape overlay, i.e., the tessellation object itself (the network of white lines in the picture above).

What QuPath does very nicely and what I just cannot replicate using other software (e.g., R) is limiting the Delaunay triangulation specifically to a specific class of cells (e.g., tumor cells, stroma). This gives complex shapes without “bridges” across the areas where cells of another class reside. This “bridge-free” version of the Delaunay pattern, as generated by QuPath, is what I am looking for.

Is the “graph” of the Delaunay tessellation accessible via scripting? Can it be exported to ImageJ? E.g., as a *.tiff or SVG? I have some (very, very) basic Groovy knowledge and a working IntelliJ installation.

Thank you!

Arnulf Mayer, University Medical Center Mainz


Hi @arnmayer,

Interesting question, to which the answer is currently both yes and no…

You can access the current Delaunay information using this:

def imageData = getCurrentImageData()
def connections = imageData.getProperty("OBJECT_CONNECTIONS")

where describe prints out what you can do with it. The only really useful bit here is

List getConnections(PathObject)

which allows you to get the immediate neighbors of an object, but that is really all.

However, this is temporary… the information is currently smuggled into the imageData properties because there was no other place to store it, but in a future version this command will be entirely replaced… precisely because there is a need to query the triangulation is much more interesting ways.

The new DelaunayTools class is the basis for its replacement, but I’m unlikely to be able to work on it much further until I have a research project that needs it. However, I’d be very interested to discuss what kind of functionality it should have to be as useful as possible.


Hi Pete,

thank you very much for your quick reply. The representation of the tumor cells as a “graph” would open up many possibilities for further analyses. We have explored fractal analysis recently (via ImageJ’s “fraclac”). I am interested in all kinds of spatial analyses which may be nice additions to QuPath’s repertoire. I will send you a manuscript via e-mail which contains some of the things I currently do.

Kind regards,



Hi @petebankhead this may be a naive question, but I tried your code snippet above and see the following:

qupath.opencv.features.DelaunayClusteringPlugin {"distanceThresholdMicrons": 10.0, "limitByClass": true, "addClusterMeasurements": true}

I can see from the java docs that getConnections works on a PathObject, but I am not seeing where in the hierarchy to access them. I am assuming it is here in the connections object but my script complains that it doesn’t respond to getConnections … do I need to cast it from Object? Am I missing a step?

Thanks again.

def detections = getDetectionObjects()

would get you a whole list of PathObjects that you can then do things with, e.g.

def imageData = getCurrentImageData()
def connections = imageData.getProperty("OBJECT_CONNECTIONS")

def detections = getDetectionObjects()
def firstDetection = detections[0]
print connections.getConnections(firstDetection)

will bring out the objects connected to the first in the list. But as described above and at Cluster mean centroids incorrect in qupath 0.2.1? the existing Delaunay command is… not in great shape, and will be replaced eventually.