Qupath script with pixel classifier

Dear all,
I try to learn how to write a correct code for QuPath-0.2.3
I find how to train the pixel classifier with the RTrees.
I would like to apply this classifier in all my images in a project and export the data (µm2 for each class) and the map/image (red, green, gray etc…) with the class 1,2,3…

For the moment I wrote this script and run it for project.

  • Could you tell me if the script will run the pixel classifier everywhere or in selectAnnotations()
  • Could you help me to export the data?
  • If my image don’t have the good scale (how to set the scale ? pixel/µm)
def classifier = loadPixelClassifier('collagen');
selectAnnotations();
classifyDetectionsByCentroid("collagen");
addPixelClassifierMeasurements("collagen", "collagen");

resetSelection();
print "Done!";

Kind regards,

Quick runthrough:
First line is not necessary if you aren’t using the classifier variable.
Second line selects the annotations, meaning that the third and fourth lines will classify all detections within the annotation using that classifier, and also add measurements to the annotations.

Finally you unselect the annotations.

You can export the whole project’s data using Measurements->Export measurements, otherwise you can script specifically what you want.

If you want to export pictures, there are plenty of forum posts on that, but I would start here. You can either maintain scale, or export as png, or whatever you want.

1 Like

thank you !
But in the script if I use the run for project it will be directly in batch mode
How should I write to work in batch like in Fiji

input = getDirectory("choose the input directory"); 
list = getFileList(input);   
for (i=0; i<list.length; i++) {
	if (endsWith(list[i],".TIF")){
		inputPath= input + list[i];
run("Bio-Formats Importer", "open=inputPath color_mode=Default rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT");
imagesName = getTitle();

Like this I will be able to add at the end

import qupath.lib.gui.tools.MeasurementExporter
import qupath.lib.objects.PathCellObject

// Get the list of all images in the current project
def project = getProject()
def imagesToExport = project.getImageList()

// Separate each measurement value in the output file with a tab ("\t")
def separator = "\t"

// Choose the columns that will be included in the export
// Note: if 'columnsToInclude' is empty, all columns will be included
def columnsToInclude = new String[]{"Name", "Class", "Nucleus: Area"}

// Choose the type of objects that the export will process
// Other possibilities include:
//    1. PathAnnotationObject
//    2. PathDetectionObject
//    3. PathRootObject
// Note: import statements should then be modified accordingly
def exportType = PathCellObject.class

// Choose your *full* output path
def outputPath = "M:/measurements.tsv"
def outputFile = new File(outputPath)

// Create the measurementExporter and start the export
def exporter  = new MeasurementExporter()
                  .imageList(imagesToExport)            // Images from which measurements will be exported
                  .separator(separator)                 // Character that separates values
                  .includeOnlyColumns(columnsToInclude) // Columns are case-sensitive
                  .exportType(exportType)               // Type of objects to export
                  .exportMeasurements(outputFile)        // Start the export process

print "Done!"

AndI would like to export the the prediction like this inside the script. But I really can’t find how to do it.

kind regards,

For the image export, you need to look at the links and or search for posts about exporting the Overlay within QuPath. And at whatever downsample.
For example: Exporting image overlay v0.2.0-m5

The export is probably easier to run as a second script, or use the interface. It should only need to be run once per project, so doesn’t generally need to be scripted. You can approach things using the getProject() approach, but accessing things and saving them tend to get more complicated.

On the other hand, if you want one CSV file per image rather than a summary CSV file, just tack that measurement script onto the end of your per image script, and name the csv file after the image rather than calling it “measurements.”

def name = getProjectEntry().getImageName()

1 Like

Dear @Research_Associate
I found your answer from 2019. But This solutions work when we train the classifier.
I would like to save a picture for all my files inside a project.
But when I load a classifier and I apply it I can’t find how to see and export the prediction map.

Thank you for your time :wink:

@Alex.h Does this help?

It will likely need modification is you want to export predictions for multiple annotations.

Note there can be a difference between exporting the raw values of a prediction (e.g. as TIFF) and the RGB image shown in an overlay.

3 Likes

There is more information here about the prediction image

2 Likes

@petebankhead and @Research_Associate,
thank you for your answer. Usually I use the mask as a quality control to check the results. The RGB images are sufficient for me.

  1. Could I export without ROI because I applied the classifier everywhere?

2) Even If I run the script with an ROI the picture is only white (value = 0)
Did I made an error in my script ?


Edit ok I see what happens your script need the annotations to work properly. So I add

createAnnotationsFromPixelClassifier("Classifier", 10, 10, "DELETE_EXISTING")

But this method is very slow do you have any advice ?

The method I posted doesn’t require creating annotations. Here’s an adapted version (untested, might have typos!):

def imageData = getCurrentImageData()
def classifier = loadPixelClassifier('Classifier')

def predictionServer = PixelClassifierTools.createPixelClassificationServer(imageData, classifier)

def path = buildFilePath(PROJECT_BASE_DIR, 'prediction.tif')

def downsample = predictionServer.getDownsampleForResolution(0)
def request = RegionRequest.createInstance(predictionServer, downsample)
writeImageRegion(predictionServer, request, path)

This gives the raw values, but if your output is a classification – and you use ‘.png’ as the file extension – it should look like the RGB image in most software.

2 Likes

thank you for your time !
kind regards,

2 Likes

dear @petebankhead and @Research_Associate,
Could you tell me if it’s possible to export the probability map and if we can have a look or export the decision trees. To understand better how it choose between class 1 and 2.

Thank you

When you save the classifier, it includes a JSON representation of an OpenCV classifier. It can be opened in a text editor; it isn’t very readable, but could potentially be parsed elsewhere.

There is a Save prediction image option under the button when creating/applying a pixel classifier.

1 Like

Dear @petebankhead,
I would like to implement in batch when I use the script editor:

  • pixels classifier for project
  • export a .png with class 1, 2, 3 etc
  • export a .png with the probabilities

Thank you for the JSON representation

This is the closest:

The decision if the classifier outputs classes or probabilities is made when it’s created – there’s no easy way to output probabilities from a preexisting classifier created to output classes.

2 Likes

@petebankhead,
A huge thank you again for your time. I work in a microscopy platform and a lot of researcher like your software.

2 Likes

Dear @petebankhead, @Research_Associate
A researcher can’t find a way to use your script and receive this message. I think the image are on a server and the project locally. Z:\ is our petabyte.

WARN: Unable to write image
ERROR: IOException at line 10: Unable to write Z:\_SHARE_\Research\CAR\CAR\Oury\Lapin\Palme\Histologie\Hearts\Test quantif AR\prediction.tif!  No compatible writer found.
ERROR: qupath.lib.images.writers.ImageWriterTools.writeImageRegion(ImageWriterTools.java:127)
    qupath.lib.scripting.QP.writeImageRegion(QP.java:2409)
    qupath.lib.scripting.QP$writeImageRegion$1.callStatic(Unknown Source)
    org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:55)
    org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:217)
    org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:249)
    Script41.run(Script41.groovy:11)
    org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:317)
    org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:155)
    qupath.lib.gui.scripting.DefaultScriptEditor.executeScript(DefaultScriptEditor.java:926)
    qupath.lib.gui.scripting.DefaultScriptEditor.executeScript(DefaultScriptEditor.java:859)
    qupath.lib.gui.scripting.DefaultScriptEditor.executeScript(DefaultScriptEditor.java:782)
    qupath.lib.gui.scripting.DefaultScriptEditor$ProjectTask.call(DefaultScriptEditor.java:1428)
    qupath.lib.gui.scripting.DefaultScriptEditor$ProjectTask.call(DefaultScriptEditor.java:1375)
    javafx.concurrent.Task$TaskCallable.call(Task.java:1425)
    java.base/java.util.concurrent.FutureTask.run(Unknown Source)
    java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    java.base/java.util.concurrent.FutureTask.run(Unknown Source)
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.base/java.lang.Thread.run(Unknown Source)

Could you help me ?

Kind regards,

Dear all,
How can I transfer the qupath project locally ?

Once you have moved the image files, you can either break the path to the original files (rename the folder by one letter?), or edit the .qpproj file with a text editor, using find and replace. Breaking the path to the original files will cause QuPath to pop up a dialog when you open the project allowing you to point to the new location.

If you just want to move the project folder around, you should be able to zip it up or just move it, and then deal with the dialog “fixing” the image path after the folder has been moved.

1 Like

@petebankhead
I’m really sorry I had a bug with QuPath. I perform a pixel clasifier but qupath crash 3 times this weekend because my memory was full . I recieve a message from windows that the application stop to prevent loss. But I set Qupath with 32 Gb and I have 60 Gb available.
my data set = 22 files between 100Mo and 550 Mo in tiff

This is my script and it’s ok for 20 files but crash after. Should I need to clean the ram between the file or did I have a too big file in the project?

I set the maximum resolution for the classifier with the smallest pixels.

selectAnnotations();
classifyDetectionsByCentroid("collagen");
addPixelClassifierMeasurements("collagen", "collagen");

resetSelection();
print "Done!";