Counting number of each annotation in pic

Sorry for such a trivial question, I’m new to javascript. I used classificator and now looking for some way to count how manny annotations of every type my image contains. I tried smth like that:
def viewer = getCurrentViewer()
def imageData = viewer.getImageData()
def hierarchy = imageData.getHierarchy()
var count = 0;
for (entry in hierarchy){
if (entry == ‘alveola’) count+=1;
}
print count

But it looks like hierarchy contains only number of objects and not info about them.
(If my problem is already answered, please link me to it, thanks.)

Hey @Dmitrii,

in which software are you executing that script?

Hey @haesleinhuepf . In QuPath built-in Script Editor.

1 Like

For the current image, this should do it

println getAnnotationObjects.size()

To quickly count all the annotations for every image in a script, there’s a recipe in the documentation:

Probably something like this.

Set classList = []
getAnnotationObjects().each{
    classList << it.getPathClass()
}
//print classList
for (aClass in classList){
println("Class " +aClass+" count: "+getAnnotationObjects().findAll{it.getPathClass() == aClass}.size())
}
1 Like

Sorry, I didn’t read closely enough… an alternative

getAnnotationObjects()
    .countBy { it.getPathClass() }
    .entrySet()
    .each { println "${it.getKey()}\t${it.getValue()}" }
2 Likes

@Research_Associate @petebankhead
Thank you very much for your help! Maybe you can also link me some tutorials in javascript ( especially associated with qupath and WSI processing )?

You’re welcome! But note that QuPath uses Groovy for scripting, not JavaScript :slight_smile:

I linked to the main documentation for QuPath above:

And here are the docs for Groovy:

Indeed. What is this black magic.

3 Likes

Here’s a less magical way of doing the same:

// Get a list of annotations
def annotations = getAnnotationObjects()

// Split the list into a map where keys are classifications and values are the number of annotations with the corresponding classification
def counts = annotations.countBy(annotation -> annotation.getPathClass() )

// Extract each entry of the map, which gives a way to access paired keys and values easily
def countEntries = counts.entrySet()

// Loop through each entry
for (entry in countEntries) {
    def pathClass = entry.getKey()
    def count = entry.getValue()
    // Create and print string giving the classification and count
    def output = pathClass.toString() + "\t" + count
    println(output)
}

Shortcuts I took in the earlier version are:

  • there is no need to create separate variables (using def) since I don’t need to store them – so I can just chain operations all together onto one line
  • for countBy, if I don’t specify a variable name corresponding to an item in the list (here, annotation) Groovy allows me to refer to the variable as it
  • each is basically another way to do a loop in Groovy (although best restricted to cases where the loop is a final step that doesn’t change anything elsewhere in the script)
  • Groovy doesn’t (always) care about including parentheses, so I can omit some of the ()
  • When passing a function as a parameter (e.g. to tell countBy or each what to do), Groovy traditionally does care about including the contents within {} – which defines a closure in Groovy parlance. However, Groovy 3.0 also accepts more recent Java lambda syntax, which is why annotations.countBy(annotation -> annotation.getPathClass()) is an acceptable alternative.
  • "${aVariable}" provides a way to put a variable into a string
1 Like