Jython plugin crashed on global variables

python
Tags: #<Tag:0x00007fb8821f4fe0>

#1

Hello, folks,
This is my first topic at this forum, so please be merciful. I wrote a plugin using Jython and it happily worked on old ImageJ versions, but started to crash with newer versions. In the plugin, I select points in an image and save them as ROIs in a zip file. This utilizes a MouseListener class, so I use global variables iROI and xlist to keep the track of multiple ROIs. The plugin behaves normally for 4-7 clicks, and then crashes with a message global name 'updateROIs' is not defined.
This happens with some variability in the number of clicks. It seems that the system destroys my function updateROIs() while the program is running. Sometimes it crashes with error messages about global variables as well, like iROI.
Does anyone know what’s happening behind the curtains here? Or should I just re-write my code in Java and suffer a post-traumatic syndrome from Jython?
My full code is below, sorry for being long.

from ij import IJ
from ij.plugin.frame import RoiManager
from java.awt.event import MouseAdapter, KeyEvent, KeyAdapter
from ij.gui import GenericDialog, WaitForUserDialog, GenericDialog, Roi, OvalRoi, Toolbar, Overlay
from ij.io import SaveDialog

# create variables
iROI = 0
xlist = ylist = zlist = []

def reset():
    global iROI, xlist, ylist, zlist
    xlist = []
    ylist = []
    zlist = []
    manager.runCommand('Reset')
    manager.runCommand('Show All')
    iROI = 0
 
class ML(MouseAdapter):
    def mousePressed(self, keyEvent):
        updateROIs()
        
def updateROIs():
    global iROI, xlist, ylist, zlist
    iROI += 1
    canv = imp.getCanvas()
    p = canv.getCursorLoc()
    z = imp.getSlice()
    roi = OvalRoi(p.x - 5, p.y - 5, 10, 10)
    roi.setName('z' + str(z) + 'cell' + str(iROI))
    roi.setPosition(z)
    xlist.append(p.x)
    ylist.append(p.y)
    zlist.append(z)
    imp.setRoi(roi)
    manager.addRoi(roi)
    manager.runCommand('Draw')

# MAIN code         
imp = IJ.getImage()
IJ.setTool(Toolbar.RECTANGLE)
manager = RoiManager.getInstance()
if manager is None:
    manager = RoiManager()

#user defines parameter values:
reset()

#Listeners:
listener = ML()
win = imp.getWindow()
win.getCanvas().addMouseListener(listener)

#2

Welcome to the forum, @nvladimus!

Thanks to your great example code, I was able to just copy&paste it into the script editor and run it, but I wasn’t able to reproduce your issue. Everything worked fine with at least 100 clicks.

I was testing in an up-to-date Fiji installation with Java 8 on Windows 7. The jython-shaded.jar on my system is version 2.7.0 (search for jython with View all files in the advanced mode of the updater).

Which versions do you have?


Also, I’m not sure if it’s related, but there was recently another issue with callbacks in Jython reported by @radoslaw.ejsmont.


#3

Hello, Jan,
Thanks for reply. The callback issue you mentioned looks exactly like mine. I am using jars/jython-shaded-2.5.3.jar version, older than yours, but my FIJI thinks it is up-to-date :frowning: I followed the instructions in issue with callbacks in Jython as you pointed, replaced my old jars/scripting-jython-0.2.4.jar with the latest one, and it worked like a charm.
Many thanks!


#4

Are you running with Java 8 and have the Java-8 update site enabled?
(If in doubt, simply try with a newly downloaded Fiji. It comes with Java 8 nowadays.)


#5

I was running Java 8, but the update site was not configured to Java-8. Now I downloaded the brand-new Fiji, things work :slight_smile: Thanks!


#6

Hi there!

I had exactly same issue. It is related to garbage collector issues with Jython interpreter. Here is what i heard from Curtis Rueden:

This is a known issue when your Python code registers callbacks which survive the execution of the script itself.

There is some rather aggressive reference cleaning logic which tries to null things out as soon as the script execution completes. Without such logic, Jython scripts end up with huge memory leaks, since references within the script are retained permanently.

A while back, I briefly played around with removing the reference cleaning logic but then the memory leaks are back.

So in short: you have stumbled upon a mammoth bug in the SciJava Jython scripting support, for which I do not currently have a good solution, apart from “use a different script language”. Sorry.

But two weeks later - after he’s done some testing with new release of scripting-jython - the issue seemed to be resolved. I do not know if this version of scripting-jython in already on the update site, but you can just download it, delete old one from jars folder and drop in the new one.

You can find it here:

http://maven.imagej.net/service/local/artifact/maven/redirect?r=snapshots&g=org.scijava&a=scripting-jython&v=0.4.1-SNAPSHOT&e=jar

Also, you can find the whole bug discussion here on GitHub:

Hope it helps!


#7

Which also means the new “scripting-jython” is now on the update site!

Awesome!


#8

Hello Radoslaw,
I encounter a similar problem. When executing a jython script it randomly crashes and imageJ claims that imported libraries are not available. This also happens with the latest FiJi installation (June2017).
For example performing a channel split with ChannelSplitter can fail after several successful runs with the error

global name ChannelSplitter is not defined

My solution was to call the jython code from an imageJ1 macro

runMacro(‘your path to the jython script’)

Then it worked pretty well.

Antonio