Jython IJ.run("Scale...", "...") problem

Hi,
when running IJ.run("Scale...", "x=2 y=2 width=512 height=512 interpolation=Bilinear create") in jython and getting the width of the active image afterwards, the resulting width is sometimes the width of the input image instead the width of the scaled image. The script below should reproduce the issue.

from ij import IJ
for _ in range(100):
	imp = IJ.createImage("Ramp", "8-bit ramp", 256, 256, 1)
	imp.show()
	IJ.run("Scale...", "x=2 y=2 width=512 height=512 interpolation=Bilinear create")
	image = IJ.getImage()
	width = image.getWidth()
	print(width)	
	IJ.run("Close All")

The output of the print is sometimes 512 and sometimes 256.

Has anyone an idea why this is happening?

Thank you,
Volker

I can’t confirm your results on Win 10 (OpenJDK 13). I get always 512. Which OS are you using?

1 Like

Sorry,
I forgot to tell:

I’m running on

  • Ubuntu 18.04.4
  • Fiji ImageJ 2.0.0-rc-69/1.52t; java 1.8.0_172 [64 bit]

Hello Volker -

I also cannot reproduce this running on ubuntu 16.04 LTS.
I have tried both:
ImageJ 2.0.0-rc-69/1.52p; java 1.8.0_172 [64 bit]
and
ImageJ 2.0.0-rc-69/1.52u24; java 1.8.0_172 [64 bit]

Some speculation:

Even though I can’t reproduce it, this smells to me like it might
be some sort of gui race condition.

Thanks, mm

2 Likes

I can confirm no problems on MacOSX, too (OpenJDK 13).

I used ImageJ and my ImageJ plugin. Could reproduce the error on plain ImageJ?

1 Like

OK, thank you @mountain_man and @Bio7.

I thought it might be a problem of my fiji installation. So I just downloaded a new fiji and tried. It is still happening in the clean install.

Even though I can’t reproduce it, this smells to me like it might
be some sort of gui race condition.

Yes, it is not happening when I run it in batch-mode.

I tried with a fresh ImageJ1 1.52t and the problem is occurring there as well.

1 Like

Hi @volker,

What is the result if you replace your print statement with:


print(width, image)

?

Does it always list the same title? like in:
(512, img["Ramp-1" (-607), 8-bit, 512x512x1x1x1])

Also, I’ve never liked leaving both the scale AND the size on the rescale command. It’s harmlessy redundant until you decide to edit your code and forget to change both. Plus, it makes it harder to read.

Cheers,
Nico

1 Like

Hi @NicoDF,

yes I agree, leaving scale and size is not a good idea.

The image is the wrong one when the size is the wrong one. Here is part of the output:

(512, img["Ramp-1" (-535), 8-bit, 512x512x1x1x1])
(512, img["Ramp-1" (-537), 8-bit, 512x512x1x1x1])
(512, img["Ramp-1" (-539), 8-bit, 512x512x1x1x1])
(256, img["Ramp" (-540), 8-bit, 256x256x1x1x1])
(512, img["Ramp-1" (-543), 8-bit, 512x512x1x1x1])
(512, img["Ramp-1" (-545), 8-bit, 512x512x1x1x1])
(512, img["Ramp-1" (-547), 8-bit, 512x512x1x1x1])
(512, img["Ramp-1" (-549), 8-bit, 512x512x1x1x1])
(512, img["Ramp-1" (-551), 8-bit, 512x512x1x1x1])
(256, img["Ramp" (-552), 8-bit, 256x256x1x1x1])
(512, img["Ramp-1" (-555), 8-bit, 512x512x1x1x1])
(256, img["Ramp" (-556), 8-bit, 256x256x1x1x1])

Ok, that’s definitely a race condition, as pointed out by @mountain_man

Perhaps we should ping @ctrueden for some input, as I’m not sure where to start looking for a possible fix.

Thanks for checking!

Does anyone have an ubuntu 18.04 or above, or at least another linux system and can reproduce this. Maybe we should first see if it’s not just my system (although I do not see how) before we put more time into this.

I don’t have time to dig on the race condition, but there is also a signature IJ.run(ImagePlus imp, String command, String options) which lets you explicitly say which image to operate upon. That avoids potential issues on the imp.show() side. But it may be a bug on the IJ.run side, with the active image not becoming the scaled image quickly enough to beat the subsequent IJ.getImage() call. Potential workarounds include adding an IJ.wait(100) before IJ.getImage(), or using IJ.runPlugIn instead of IJ.run (IIRC, depending on the plugin, runPlugin returns the modified ImagePlus object?).

I invited @Wayne to join the discussion.

2 Likes

I tested the same script again on Ubuntu 19.10. Again with the same correct results (ImageJ).

Maybe I can reproduce your results if you point me to a fresh (reproducible) Linux installation.

Apropos could you reproduce your results with an ImageJ macro or Java plugin?

I tested in opensuse leap 15.1 and I get 512 every single time.
I do not use jyton, so I am not sure how to do this, but before the line:
image = IJ.getImage()
can you write in jyton the equivalent of the IJ macro language:
selectWindow("name");
so the when you get the the image in the next statement you are guaranteeing it is the right one?
Hope it helps!

Thanks @ctrueden,

I tried the workarounds you proposed/

IJ.run(ImagePlus imp, String command, String options)
doesn’t make a difference in this case

IJ.wait(100)
This is not working. It gives java.lang.IllegalMonitorStateException

IJ.runPlugIn
returns the plugin object the Resizer in this case.

Interpreter.batchMode=True before the IJ.run("Scale...", "...") and Interpreter.batchMode=False after it works. And if the image should be displayed J.getImage().show(). This works reliably.

1 Like

I updated my system to ubuntu 19.10 and the problem does not occur anymore.

I did not manage to reproduce it with macro or plugin. My feeling is that it also happened but much less frequently, but I can not prove it.

Hi @gabriel,
yes that was the first thing I tried. It does not work, because the window will not be there yet. I also tried to loop or sleep until the right image is there. It didn’t work either. Switching to batch-mode before the run ("Scale...", "...") and back afterwards works reliably.

1 Like

Use ImageProcessor.resize() to resize the images and your code will run faster and be more reliable. I will update the Scale command to record code that uses ip.resize().

for _ in range(100):
   imp = IJ.createImage("Ramp","8-bit ramp",256,256,1)
   ip = imp.getProcessor();
   ip.setInterpolationMethod(ImageProcessor.BILINEAR)
   ip2 = ip.resize(512,512);
   print(ip2.getWidth())

Update: Upgrade to the latest ImageJ daily build (1.52u28) and you will be able to use the new ImagePlus.resize(width,height,options) method that is going to be used for recording the “Scale” and “Resize” commands.

for _ in range(100):
   imp = IJ.createImage("Ramp", "8-bit ramp", 256, 256, 1)
   imp2 = imp.resize(512,512, "bilinear");
   print(imp2.getWidth())
2 Likes