Histogram measurements qupath

Hi Qupathers,
I’m trying to recall data from histograms in a script e.g. measure>show detection measurements>show histograms>Cell: DAB OD min>Std.Dev
There doesn’t seem to be an option for exporting the summary data from qupath histograms
Thanks,
Alan

Background

  • What is the image about? Provide some background and/or a description of the image. Try to avoid field-specific “jargon”.

Analysis goals

  • What information are you interested in getting from this image?

Challenges

  • What stops you from proceeding?
  • What have you tried already?
  • Have you found any related forum topics? If so, cross-link them.
  • What software packages and/or plugins have you tried?

So I don’t think that’s directly possible no. You could calculate it directly with something like

def measurementName = 'Nucleus: DAB OD min'
def cells = getCellObjects()

def DAB_min_list = cells.collect { cell -> measurement(cell, measurementName ) } as double[]

def DAB_min_mean = (DAB_min_list.sum()/DAB_min_list.size()) 
   
def DAB_min_sd = 0
DAB_min_list.each{
    d -> DAB_min_sd += (d - DAB_min_mean)*(d - DAB_min_mean)
} 

def DAB_min_stdev = Math.sqrt(DAB_min_sd/DAB_min_list.size())

But as discussed here that’s not a great idea. Especially as my maths is very rusty (and my QuPath script skills aren’t much better).

With a lot of help from @petebankhead, I have a way where the maths isn’t being done manually so less prone to errors.

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics

def measurementName = 'Nucleus: DAB OD min'
def cells = getCellObjects()

def DAB_min_list = cells.collect { cell -> measurement(cell, measurementName) } as double[]

def stats = new DescriptiveStatistics(DAB_min_list)

DAB_min_list_stdev = stats.getStandardDeviation()
print(DAB_min_list_stdev)
3 Likes

Thanks very much indeed for this. It works well but I have an issue with the script I have made; //I’ve run a positive cell detection and want to get the stats on positive cells only, currently its printing the stats for all cells. Please can you correct the syntax if its not too much trouble?
Thanks,
Alan

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics
def cell_dab_od_mean = 'Cell: DAB OD mean'
def cells = getCellObjects()
def positive_cells = cells.findAll {Cell='Positive'}
//I've run a positive cell detection and want to get the stats on positive cells only, currently its printing the stats for all cells
def positive_cell_list = positive_cells.collect {cell -> measurement(cell, cell_dab_od_mean)} as double[]
def stats = new DescriptiveStatistics(positive_cell_list)
mean_dab = stats.getMean()
sd_dab = stats.getStandardDeviation()
dab_threshold = (mean_dab + sd_dab)
print (mean_dab)
print (sd_dab)
print (mean_dab + sd_dab)

Great, the below should work I think for using just positive cells.

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics

def cell_dab_od_mean = 'Cell: DAB OD mean'

positive_cells = getCellObjects().findAll{ cell -> cell.getPathClass() == getPathClass("Positive")}

def positive_cell_list = positive_cells.collect { positive_cells -> measurement(positive_cells, cell_dab_od_mean) } as double[]

def stats = new DescriptiveStatistics(positive_cell_list)

mean_dab = stats.getMean()
sd_dab = stats.getStandardDeviation()

dab_threshold = (mean_dab + sd_dab)

print (mean_dab)
print (sd_dab)
print (mean_dab + sd_dab)
1 Like

Awesome, thanks so much! Is it possible to do that same with annotations? I want to get intensity features for several annotions then do similar calculations…my code is not correct regarding annoations:
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics
selectAnnotations();
runPlugin(‘qupath.lib.algorithms.IntensityFeaturesPlugin’, ‘{“pixelSizeMicrons”: 2.0, “region”: “ROI”, “tileSizeMicrons”: 25.0, “colorOD”: false, “colorStain1”: false, “colorStain2”: true, “colorStain3”: false, “colorRed”: false, “colorGreen”: false, “colorBlue”: false, “colorHue”: false, “colorSaturation”: false, “colorBrightness”: false, “doMean”: true, “doStdDev”: false, “doMinMax”: false, “doMedian”: false, “doHaralick”: false, “haralickDistance”: 1, “haralickBins”: 32}’);
def annotation_mean_dab = ‘ROI: 2.00 µm per pixel: DAB: Mean’
my_annotations = getAnnotations().findAll()
//ERROR: MissingMethodException at line 5: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.getAnnotations() is applicable for argument types: () values:
def my_annotations_dab_list = annotations.collect {annotations -> measurement(annotations, annotation_mean_dab)} as double
def stats = new DescriptiveStatistics(my_annotations_dab_list)
my_annotations_mean_DAB = stats.getMean()
print (mean_dab)

If you want annotation objects, you use getAnnotationObjects(), in the same way that you used getCellObjects() above. Other options include getDetectionObjects() which is more general for non-annotations.

Thanks for this. Does that recall any objects inside an annotation or the annotation itself? I’m trying to recall intesity features run on annotations. Can’t seem to recall the data with this:

def annotation_mean_dab = ‘ROI: 2.00 µm per pixel: DAB: Mean’
my_annotations = getAnnotationObjects()
def my_annotations_dab_list = my_annotations.collect {my_annotations -> measurement(my_annotations, annotation_mean_dab)} as double
def stats = new DescriptiveStatistics(my_annotations_dab_list)
my_annotations_mean_DAB = stats.getMean()
print (my_annotations_dab_list)

Blockquote

You asked for the intensity features for annotations, so if you generated intensity features for your annotations, that is how you would cycle through them. Generating summary features “per annotation” would be something different.

If you want others to be able to use your code, I would recommend posting it “as code.”
image

OK I was wondering how to do that, thanks for your patience. Here is the full code and output

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics
selectAnnotations();
runPlugin('qupath.lib.algorithms.IntensityFeaturesPlugin', '{"pixelSizeMicrons": 2.0,  "region": "ROI",  "tileSizeMicrons": 25.0,  "colorOD": false,  "colorStain1": false,  "colorStain2": true,  "colorStain3": false,  "colorRed": false,  "colorGreen": false,  "colorBlue": false,  "colorHue": false,  "colorSaturation": false,  "colorBrightness": false,  "doMean": true,  "doStdDev": false,  "doMinMax": false,  "doMedian": false,  "doHaralick": false,  "haralickDistance": 1,  "haralickBins": 32}');
def annotation_mean_dab = 'ROI: 2.00 µm per pixel: DAB: Mean'
my_annotations = getAnnotationObjects()
def my_annotations_dab_list = my_annotations.collect {my_annotations -> measurement(my_annotations, annotation_mean_dab)} as double[]
def stats = new DescriptiveStatistics(my_annotations_dab_list)
my_annotations_mean_DAB = stats.getMean()
print (my_annotations_dab_list)
print (my_annotations_mean_DAB)
//OUTPUT
//INFO: Processing complete in 0.05 seconds
//INFO: Completed!
//INFO: [NaN, NaN]
//INFO: NaN

I copied the code exactly and it ran as expected for me with 3 or 4 annotations.


Something is probably not accurate as far as how your project is structured vs how we think it is structured.

Also, if you run this on an image that is not DAB, it will fail.

Awesome its working for me too. I copied the code from my own post and put back into the scripter in qupath - I think there may have been something wrong with the mu symbol.
Really appreciate your help :blush:

1 Like