Detecting cells with difference of Gaussian using imglib2

In Schindelin et al. 2012 (the Fiji paper), figure 2a, we wrote a small jython script that detects cells by difference of gaussian on a stack of a Drosophila first instar brain where the nuclei of glial cells are labeled in the red channel. That 5-year-old script still runs (after adding all the now missing imports; they used to be imported automatically), and you can find it in my Fiji python scripting tutorial:

https://www.ini.uzh.ch/~acardona/fiji-tutorial/#find-peaks

Below is a modern version of the script using ImgLib2. The issue: it detects zero peaks, when 27 should be reported.

# A script to find cells by difference of Gaussian using imglib2.
# Uses as an example the "first-instar-brain.tif" RGB stack availalable
# from Fiji's "Open Samples" menu.

from ij import IJ
from net.imglib2.img.display.imagej import ImageJFunctions as IJF
from net.imglib2.view import Views
from net.imglib2.converter import Converters
from net.imglib2.algorithm.dog import DogDetection
from net.imglib2.type.numeric.real import DoubleType


# Fetch the "first-instar-brain.tif" file
#imp = IJ.openImage("http://downloads.imagej.net/fiji/snapshots/samples/first-instar-brain.zip")
imp = IJ.getImage()
cal = imp.getCalibration() # in microns

img = IJF.wrap(imp)

# Extract the red channel
red = Converters.argbChannel(img, 1)

# Create a variable of the correct type (UnsignedByteType) for the value-extended view
zero = red.randomAccess().get().createVariable()

# Run the difference of Gaussian
cell = 5.0 # microns in diameter
min_peak = 40.0 # min intensity for a peak to be considered
dog = DogDetection(Views.extendValue(red, zero), img,
                   [cal.pixelWidth, cal.pixelHeight, cal.pixelDepth],
                   cell / 2, cell,
                   DogDetection.ExtremaType.MAXIMA,
                   min_peak, False,
                   DoubleType())

peaks = dog.getPeaks()

# Should print 27, but prints zero!
print len(peaks)

What is wrong in the above script with the DoG detection?

Thanks.

1 Like

I think you’d have to detect MINIMA instead of MAXIMA here, as “gauss(img, cell/2) - gauss(img, cell)” results in local minima for peaks in your input image.

At least changing to DogDetection.ExtremaType.MINIMA gives me 43 peaks, and on first sight, those correspond well to the red spots.

print peaks
[(74,40,1), (133,89,1), (82,141,1), (229,206,1), (249,246,1), (47,70,6), (120,223,11), (191,144,12), (168,104,16), (115,134,17), (251,201,17), (213,133,20), (137,75,14), (150,107,14), (135,56,31), (99,209,32), (216,143,33), (245,193,25), (99,83,34), (176,215,36), (130,219,35), (59,91,38), (203,185,37), (92,209,37), (193,158,40), (245,189,40), (145,216,40), (123,67,41), (165,86,41), (244,175,39), (85,204,42), (196,211,42), (158,108,43), (165,203,43), (227,215,43), (61,160,46), (107,203,47), (117,100,50), (91,104,50), (162,144,50), (116,180,50), (124,195,50), (111,156,54)]

I can’t explain the mismatch in numbers though, lacking sufficient knowledge of the implementations.


Here’s a version of your script that uses script parameters to get the input image, and Ops to crop and extend it:

# @OpService ops
# @ImgPlus img

# A script to find cells by difference of Gaussian using imglib2.
# Uses as an example the "first-instar-brain.tif" RGB stack availalable
# from Fiji's "Open Samples" menu.

from net.imglib2.algorithm.dog import DogDetection
from net.imglib2.type.numeric.real import DoubleType

# Extract the red channel
interval = ops.run("create.img", [img.dimension(0), img.dimension(1), 1, img.dimension(3)], img.firstElement(), img.factory())
red = ops.run("transform.crop", img, interval)

# Create a variable of the correct type (UnsignedByteType) for the value-extended view
extended = ops.run("transform.extendZeroView", red)

# Run the difference of Gaussian
cell = 5.0 # microns in diameter
min_peak = 40.0 # min intensity for a peak to be considered

dog = DogDetection(extended, red,
                   [img.averageScale(0), img.averageScale(1), img.averageScale(3)],
                   cell / 2, cell,
                   DogDetection.ExtremaType.MINIMA,
                   min_peak, False,
                   DoubleType())

peaks = dog.getPeaks()

# Prints 43
print len(peaks)
print peaks

Thanks a lot for spotting this! Indeed I was surprised that the order of the small and large sigmas seemed to be inverted.

Likely this has to do with the fact that the old script scaled down the image to make it isotropic, loosing some information, whereas the new one runs on the raw red channel, needing only the calibration to be provided. Raising the min peak intensity value to 47 results in 29 maxima being found. Considering that the scaling was rather severe (4x on X and Y), it is most likely the root cause of the difference.

1 Like