Trouble with Jython, need to pass arguments & my keyListener forgets function definitions

trakem2
python
Tags: #<Tag:0x00007fb87e136aa8> #<Tag:0x00007fb87e136968>

#1

I’ve written a script for TrakEM2 in jython. It runs fine, then starts failing. It shouldn’t be doing this, but I have some ideas.

When I run the script, it spits out the following in the System Log:

console: Failed to install '': java.nio.charset.UnsupportedCharsetException: cp0

This is a known jython error. All I need to do is pass an argument to the jvm, but I can’t figure out how to do that, since it’s being launched by Fiji. Any ideas how to add a command line argument?

I’m running addKeyListener() on TrakEM2 using the example code on the jython scripting page. I can press keys about 20 times, then it starts writing to System Log:

NameError: global name 'doSomething' is not defined

doSomething is my effector function, as seen in the example code (Jython Scripting Examples). It’s obviously defined, because that’s the only way my script works at all. After working, jython forgets about this definition. It’s very odd. I’m hoping that by fixing the first error I might affect the second. It may also be possible that by adding the keylistener to every canvas that I’m somehow causing TrakEM2 or Fiji to fail because of unprocessed keystrokes. It’s very weird, and isn’t strictly speaking, a hard limit. In other words, I can sometimes press keys quite a bit without problems. Sometimes, it only works 10x before locking up. Usually it’s about 20x keypressing before failing.
Any ideas on what this is?


#2

Hi Guido,

the message at the system log is a known issue of Jython 2.7.0 [1] (as written by yourself). The first time I run a Jython script it is shown. All following calls of Jython scripts do not show the message. By now I noticed no negative effects.

When I run the key listener script in with Fiji, I can’t reproduce your problem. Maybe there is a side effect of the code you have added.


#3

Hi M-E:

I’ve attached my code below. If you open equal sized image stacks in TrakEM2 so that you have multiple stacks to select from, it will allow you to cycle through which stack you are currently viewing. It’s quite useful. However, it just starts failing to work after a while. I can see error messages, so I know the keyListener is still attached, but it, strangely, stops being able to find the function it’s supposed to call for the keylistener.

Once you get it loaded and run the script, press 6 to initialize, and 7 or 8 keys will cycle through one direction or the other.


#TrackEM2_Keylistener.py
from ini.trakem2.display import Display, Patch
from ij import IJ, ImagePlus, VirtualStack, WindowManager
from __builtin__ import len
from java.util import ArrayList
from java.awt.event import KeyEvent, KeyAdapter 


def TurnOnOne():
    "Turns on a single stack"
    layerPaths = []
    patchlist = ArrayList()
    layers = Display.getFront().getLayerSet().getLayers()
    for layer in layers:
        patches = layer.getDisplayables(Patch)
        for patch in patches:
            layerPaths.append(patch.getFilePath())
            patchlist.add(patch)
        

    layer_count = Display.getFront().getLayerSet().BOTTOM - Display.getFront().getLayerSet().TOP + 1
    #layer_count = 44
    patch_count = len(layerPaths)
    step = patch_count / layer_count
    dingdongoutput = "Step = "+str(step)+", Patch_count = "+str(patch_count)+", layer_count = "+str(layer_count)
    IJ.log(dingdongoutput)

    for i in range(0,patch_count-1):
        patch = patchlist[i]
        patch.visible = False

    dumdum = 0
    for i in range(0,patch_count-1):
        if (dumdum % step) == 0:
            patch = patchlist[i]
            patch.visible = True
        dumdum = dumdum + 1

def TurnOnNext():
    layerPaths = []
    patchlist = ArrayList()
    layers = Display.getFront().getLayerSet().getLayers()
    for layer in layers:
        patches = layer.getDisplayables(Patch)
        for patch in patches:
            layerPaths.append(patch.getFilePath())
            patchlist.add(patch)
        
    layer_count = Display.getFront().getLayerSet().BOTTOM - Display.getFront().getLayerSet().TOP + 1
    layer_count = 44
    patch_count = len(layerPaths)
    step = patch_count / layer_count
    # Find first instance of visible patch
    foundone = False
    found_at = 0
    for i in range(0,patch_count-1):
        patch = patchlist[i]
        if (patch.visible == True) and (not foundone):
            foundone = True
            found_at = i
    # Turn off everyone
    for i in range(0,patch_count-1):
        patch = patchlist[i]
        patch.visible = False
    # Turn on starting at found_at + 1 % layer_count going by step
    start_on = (found_at + 1) % step
    for i in range(start_on,patch_count-1,step):
        patch = patchlist[i]
        patch.visible = True

def TurnOnPrev():
    layerPaths = []
    patchlist = ArrayList()
    layers = Display.getFront().getLayerSet().getLayers()
    for layer in layers:
        patches = layer.getDisplayables(Patch)
        for patch in patches:
            layerPaths.append(patch.getFilePath())
            patchlist.add(patch)
        
    layer_count = Display.getFront().getLayerSet().BOTTOM - Display.getFront().getLayerSet().TOP + 1
    layer_count = 44
    patch_count = len(layerPaths)
    step = patch_count / layer_count
    # Find first instance of visible patch
    foundone = False
    found_at = 0
    for i in range(0,patch_count-1):
        patch = patchlist[i]
        if (patch.visible == True) and (not foundone):
            foundone = True
            found_at = i
    # Turn off everyone
    for i in range(0,patch_count-1):
        patch = patchlist[i]
        patch.visible = False
    # Turn on starting at found_at - 1 % layer_count going by step
    start_on = (found_at - 1) % step
    for i in range(start_on,patch_count-1,step):
        patch = patchlist[i]
        patch.visible = True


def doSomething(imp, keyEvent):
    """ A function to react to key being pressed on an image canvas. """
    #IJ.log("clicked keyCode " + str(keyEvent.getKeyCode()) + " on image " + str(imp) + " vs. " + KeyEvent.VK_7 + " or " + KeyEvent.VK_8)
    keyCode = keyEvent.getKeyCode() 
    if KeyEvent.VK_7 == keyCode:
        #IJ.log("clicked keyCode " + str(keyEvent.getKeyCode()) + " on image " + str(imp))
        TurnOnPrev()
 
    elif KeyEvent.VK_8 == keyCode:
        #IJ.log("clicked keyCode " + str(keyEvent.getKeyCode()) + " on image " + str(imp))
        TurnOnNext()

    elif KeyEvent.VK_6 == keyCode:
        TurnOnOne()

    # Prevent further propagation of the key event:
    keyEvent.consume()
 
class ListenToKey(KeyAdapter):
    def keyPressed(this, event):
        global doSomething
        imp = event.getSource().getImage()
        doSomething(imp, event)
  
listener = ListenToKey()
  
for imp in map(WindowManager.getImage, WindowManager.getIDList()):
    win = imp.getWindow()
    if win is None:
        continue
    canvas = win.getCanvas()
    # Remove existing key listeners
    kls = canvas.getKeyListeners()
    map(canvas.removeKeyListener, kls)
    # Add our key listener
    canvas.addKeyListener(listener)
    # Optionally re-add existing key listeners
    #map(canvas.addKeyListener, kls)