Export Coordinates of Nuclei Segmentation and the corresponding Label core-wise for TMA?

Hi all,

do I understand it correctly that this script from Pete

// Create an empty text file
def path = buildFilePath('C:/Users/~/Desktop/TMASingleCores', 'polygons.txt')
def file = new File(path)
file.text = ''

// Loop through all objects & write the points to the file
for (pathObject in getAllObjects()) {
    // Check for interrupt (Run -> Kill running script)
    if (Thread.interrupted())
    // Get the ROI
    def roi = pathObject.getROI()
    if (roi == null)
    // Write the points; but beware areas, and also ellipses!
    file << roi.getPolygonPoints() << System.lineSeparator()
print 'Done!'

exports the vertices of the segmentations, if these are all objects? Is it possible to export these coordinates core-wise for a TMA (A-1_objects.txt, …)?

And secondly, is there a way to also export the corresponding label, like: ‘Stroma’?

Good evening,

That script is run for objects (anything, tiles, cells, annotations, TMA cores) in getAllObjects(). You would need to modify the script based on some of the other TMA scripts. One example is at the bottom of his blog page, here.
Another example here shows cycling through TMA cores as well.

You would also need to use something like
core.getName() to add that into the buildFilePath function, which would need to be inside the per-core loop.

Label: It depends on which label you want. Have you segmented the tissue by stroma vs tumor, or just the cells? In that example, the cells would be
while the annotation class would be

You would need some kind of further structure within the text file to store that information, I would guess.

Added note, I haven’t actually played around with exporting coordinates, but I would test how it works with cells, since nuclei would not be connected to the cytoplasm. A string of coordinates that does not differentiate between the two could be difficult to use.

1 Like

Thank you for your detailed answer!
These scripts and tricks will definitely help me!

Trying the script of your first link, gets me this error:

ERROR: Error: startup failed:
Script1.groovy: 21: unable to resolve class qupath.lib.scripting.QPEx
 @ line 21, column 1.
   import qupath.lib.scripting.QPEx

1 error

ERROR: Script error
    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:311)
    at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:980)
    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:647)
    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:596)
    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:390)
    at groovy.lang.GroovyClassLoader.access$300(GroovyClassLoader.java:89)
    at groovy.lang.GroovyClassLoader$5.provide(GroovyClassLoader.java:330)
    at groovy.lang.GroovyClassLoader$5.provide(GroovyClassLoader.java:327)
    at org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache.getAndPut(ConcurrentCommonCache.java:147)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:325)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:309)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:251)
    at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.getScriptClass(GroovyScriptEngineImpl.java:331)
    at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:153)
    at qupath.lib.gui.scripting.DefaultScriptEditor.executeScript(DefaultScriptEditor.java:767)
    at qupath.lib.gui.scripting.DefaultScriptEditor.executeScript(DefaultScriptEditor.java:697)
    at qupath.lib.gui.scripting.DefaultScriptEditor.executeScript(DefaultScriptEditor.java:677)
    at qupath.lib.gui.scripting.DefaultScriptEditor$2.run(DefaultScriptEditor.java:1034)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)

Any idea how to fix this?

Not sure, but I am guessing it has to do with which version of QuPath you are running. Many scripts like this one were probably written prior to 0.2.0 (I am guessing you are using some variant of this?), and may not work without adjustments. In this case I would remove the line causing the error and also any places where you see “QPEx.” within the script.

1 Like

Yes, I have 0.2.0! Actually it worked, just to delete all ‘QPEx’ as you said. So its just an unnecessary prefix from older versions I guess.

1 Like

There’s an option in the script editor to ‘Include default bindings’ - if that’s checked, then you don’t need the import.

(The reason the old import doesn’t work is because the location of QPEx had to change… relying on the ‘default bindings’ avoids the problem of needing to modify the import statement according to QuPath version)

1 Like

Thanks for the explanation!