Groovy tutorial fo fiji plugin

Hello everyone,

I need some advices/help. I developp a small image analysis algorithm in python (3.7 and Numpy) with the idea to developp it in a Jython plugin before realising the limit of it (python 2.5, no cpython module supported so far and quite slow on pixel-to-pixel operations).
I would like to learn groovy, as i read it combines good thing from both python and java, but i didn’t found tutorial to start coding groovy project (just like the excellent one for jython made by @albertcardona ), I may have missed it though…
Do you have any ressources to share for groovy scripting ?

Thank you all and take care of your relatives and you

Julien

Hello @jdumont,

I don’t know something which is as good as @albertcardona’s jython scripts. But usually the translation from jython to groovy is not too difficult.

Personnally I use groovy when the project is not too big, because without an IDE you’ll get lost with the imports. Otherwise I’ll go to plain Java. If that’s useful for you, you can have a look at some groovy’s gists we did in our facility:

If you’s like to go for IJ2 plugins, there are groovy notebooks somewhere I believe but I can’t find them.

If you have specific groovy+FIJI questions, just ask and we can try to help.

Best,

Nicolas

2 Likes

Hello @NicoKiaru,

As a novice in programming, I expect my projects to be not very big ! And I am afraid that Java would be a bit too much for me, as I would start from nearly zero (still, if you have other great ressources to share that might change my mind, feel free to share :smiley: ).
Thank you very much for the gists, they look indeed promising and complete as starting points. But, for IJ2 plugins, to me, there is basically not much to do right ? A groovy script isn’t kinda good-to-go to be plugin ?

Be sure I’ll be there with many groovy questions.

Best,

Julien

2 Likes

Yes a groovy script with IJ2 scripts parameters can be sufficient for a lot of applications.

2 Likes

Hi @jdumont,
as far as I know, in the real world the limitations of jython have to do with iterating pixels in for loops. There are approaches to bypass this, one of them being invoking another scripting language that can give you java-level (and numpy-level) performance. Sometimes even within jython itself there are ways to speed operations up by avoiding looping over pixels.
What is the operation in question that you found is slowing down your script?
Best,
Albert

1 Like

Hi @albertcardona,

In my algorithm, I want to look at every pixel neighborhood in several directions, at several distances, in 3D. The script written as it is, in Python 3.7 + Numpy, iterates pixels in for loops. Here is the basic part of it :

for v in range(voxels):
    for r in range(rows):
        for c in range(cols):
            i = image[v, r, c]
            vox = v + offset_z
            row = r + offset_r
            col = c + offset_c
            j = image[vox, row, col]
            if 0 <= i < levels and 0 <= j < levels:
                P[i, j, element] += 1

which is very C-style, and can probably be optimized !

In this exemple, you can also note the P[i, j, element] matrix, which come from Numpy. What would be an equivalent in Jython ?

Thank you for your help

@jdumont all the tutorial notebooks here are written in Groovy (making use of the beakerx kernel for Jupyter):

(except one I should say: 6-ImageJ-with-Python-Kernel.ipynb)

3 Likes

Hi @jdumont,

The equivalent array would be an ImgLib2 n-dimensional image, in your case 3d. See my online jython Fiji tutorial to get started.

The way to access your neighborhoods from such ImgLib2 image (a RandomAccessibleInterval) would be using the classes in imglib2-roi package. Search the forum for “imglib2-roi” for example scripts, particularly with my name. Sorry I can’t help further presently.

Best,

Albert

2 Likes

Hello Julien -

As Albert pointed out, the biggest performance hit using jython
(python) (or other scripting languages) occurs when you have to
loop over pixels (or other low-level items in large data structures).

To the extent you can perform your computations in “bulk” on
images using built-in Fiji / ImageJ functionality, you’ll come out
ahead, because the pixel processing gets pushed down into
ImageJ’s java implementation.

Here’s a loop-free jython script based on the code you posted:

from ij import IJ
from ij import ImagePlus
from ij.plugin import ImageCalculator
from ij.process import StackConverter
from ij.process import StackStatistics

print  IJ.getFullVersion()

# size of 3d image (stack)
voxels = 256   # z
rows = 256     # y
columns = 256  # x

# assume that voxels contain 8-bit values
imgAll = IJ.createImage ('imgAll', '8-bit ramp', 256, 256, 256)
imgAll.show()

# assume offsets are all positive
offset_z = 10   # z
offset_r = 20   # y
offset_c = 30   # x

imgBase = ImagePlus ('imgBase', imgAll.getStack().crop (0, 0, 0, columns - offset_c, rows - offset_r, voxels - offset_z))
imgOffset = ImagePlus ('imgOffset', imgAll.getStack().crop (offset_c, offset_r, offset_z, columns - offset_c, rows - offset_r, voxels - offset_z))

imgBase.show()
imgOffset.show()

# create 2d 2^8 x 2^8 histogram as a 1d 2^16 histogram
StackConverter (imgBase).convertToGray16()
StackConverter (imgOffset).convertToGray16()
IJ.run (imgBase, 'Multiply...', 'value=256.0 stack')
imgHist = ImageCalculator().run ('Add create stack', imgBase, imgOffset)

imgHist.setTitle ('imgHist')
imgHist.show()

hist = StackStatistics (imgHist, 65536, 0.0, 65535.0).getHistogram()

# check histogram
print  'len (hist) =', len (hist)
histTot = 0
for  c in hist:
	histTot += c
print  'total count =', histTot
print  'sample counts:'
print  'hist[0] =', hist[0]
print  'hist[30] =', hist[30]
print  'hist[287] =', hist[287]
print  'hist[57598] =', hist[57598]
print  'hist[57855] =', hist[57855]
print  'hist[65535] =', hist[65535]

Here is the output:

1.52t99
len (hist) = 65536
total count = 13120656
sample counts:
hist[0] = 0
hist[30] = 58056
hist[287] = 58056
hist[57598] = 58056
hist[57855] = 58056
hist[65535] = 0

The idea is to implement your offset by aligning two properly
cropped copies of your 3d image (stack). Probably the goofiest
part of this scheme is to implement your 2d-histogram (P) as
a 1d-histogram, packing a pair of 8-bit histogram indices into a
single 16-bit index.

Fiji / ImageJ does have a bunch of functionality scattered
hither and yon, so it’s often possible to cobble something
like this together.

As a practical matter, if performance doesn’t really matter; I
would just write the loops in jython; if it matters some, this
approach could make sense; if it matters more, you would
probably want to go with a java plugin; and if it matters a lot,
stick with numpy or write a c++ tool. (Numpy’s internals are
written in c, so it’s likely to beat java.)

Thanks, mm

1 Like

Hello @mountain_man,

Thank you very much for your input, it’s quite a fancy way to solve it, I need to deep a bit in the code in order to be sure I get what you did, but based on the explanation you gave, it sounds clever and really interesting !
I came for groovy, and end up quite thrilled by the possibility of Jython I missed ! Unexpected but pleasant !

Thank you all again

Hello Julien -

As far as groovy vs. jython goes, they are very similar. They
are both reasonable scripting languages that have built-in
scripting-language-java bridges so you can access the
underlying Fiji / ImageJ classes without anybody having
had to write ImageJ-specific bindings.

My general advice is if you already know one of the scripting
languages supported by ImageJ, use that. If you’ll be learning
a new scripting language to script ImageJ, I would recommend
jython (which is an implementation of python, where the python
interpreter is implemented in java). It’s not that python is
necessarily a better language than groovy (or the other scripting
languages), but it’s very broadly used, and has a rich ecology, so
you’re more likely to get mileage out of learning it, independent
of ImageJ.

Having recommended jython, I should mention two important
limitations: It is currently python 2 rather than python 3; Also, it
does not support using python packages that are implemented
in c under the hood, so you can’t, for example, use numpy.

Lastly, if you’re not going to be programming much logic into
your scripts and will mostly be stringing together a handful
of ImageJ commands, the ImageJ Macro (IJM) language
can be convenient.

And of course, if you’re working with a script that someone
else has already written – maybe making some minor tweaks
to it – work with the language it’s written in. But if you’re rewriting
it or making major revisions, go with the language your most
familiar with, with jython as the default.

Thanks, mm

2 Likes