DynamicCommand, CancelReason persistance

Hi Guys,

I tried the dynamicsCommand to make an interactive thresholding and meet a funny issue. When the code abort because it lacks an open image it gives the following cancellation error in a popup

An ImagePlus is required but none exist.

When rerunning the command afterward the same message always pops up independent whether an image is open or not. However the command works fine as long as no such error pops up. Below is a minimal code reproducing the issue on my machine (Window 7, compiled with eclipse and java sdk 1.8_074, compliance to 1.6 checked). Does anyone gets hints how I could solve that? Is there anything wrong in the code below.

import ij.IJ;
import ij.ImagePlus;
import net.imagej.ImageJ;

import org.scijava.command.Command;
import org.scijava.command.DynamicCommand;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;


@Plugin(type = Command.class, menuPath = "SCF>test IJ2 command>testCancelReason")
public class testCancelReason extends DynamicCommand {

    @Parameter ImagePlus imp;
    
    @Override
    public void run() {
        IJ.log("hello, image name is:"+ imp.getTitle());
    }
    
    @Override
    public void cancel(){
        IJ.log( getCancelReason() );
        if ( imp!=null )
            IJ.log("script is canceled but image name is:"+ imp.getTitle() );
        
    }
    
    public static void main(final String... args) throws Exception {
        // Launch ImageJ as usual.
        final ImageJ ij = net.imagej.Main.launch(args);

        // Launch the command without and with image open.
        ij.command().run(testCancelReason.class, true);
        ImagePlus imp = IJ.openImage("http://imagej.nih.gov/ij/images/blobs.gif");
        imp.show();
        ij.command().run(testCancelReason.class, true);
      
    }

}

I also got the following warning in ecclipse when executing the main. Did I miss something in plugin declaration?

[WARNING] 1 exceptions occurred during plugin discovery.

Thanks for your help :wink: !

Hello Benoit,

I don’t think your declarations are missing anything, so let’s tackle that exception. The first thing I would try to do is to clean and rebuild my project. I often get these kinds of warnings because I renamed or moved classes, and there’s outdated metadata laying around.

If that doesn’t help, I’d turn on debugging by adding to the LogService.setLevel(LogService.DEBUG) main method (before the calls to run). Then I’d run the main again to get more info about the warning.

On the other hand your problem might have something to do with the automatic prepopulation of your @Parameter fields. Once your ImagePlus has been assigned to null it won’t get populated on subsequent runs. Try adding option @Parameter(persist = false)

Regards,
Richard Domander

P.S. The ImagePlus class is a thing of the past, i.e. ImageJ1. You might run into some pesky legacy issues if you keep using that in ImageJ2 code. These days people usually go with ImgPlus. I’m sorry, but at the moment I can’t find how you open files with that.

Hi Richard,

Thanks for your advice. I just gave a try to the persist=false option but the plugin behavior is still the same. I also tried with a Dataset rather than an ImagePlus but without much success either.

P.S. as for my usage IJ1: that’s how I learned to use ImageJ and am now slowly trying to get up to speed with IJ2 API but there is still some way to go as you can see.

Could you paste / link your Dataset version of the code, please? I’m thinking of trying to duplicate the error and debugging on my computer.

I think your usage of ij.ImagePlus here is just fine. The IJ2 core data model is still in flux, so it makes sense to stay away from it for the moment. But using the SciJava module framework in general makes total sense—it is quite mature now.

Is there some reason you need DynamicCommand though? Why not just extend ContextCommand? Edit: Because DynamicCommand has the cancel() method which goes with Previewable.

I have noticed this on my machine lately as well. It is possible that this is a recently introduced bug—I have not had time to debug into what is going on yet. It is unlikely (<30% chance? :wink:) to be related to your problem, though.

What version of the pom-imagej are you using as parent? And/or what version of net.imagej:imagej etc. are you using as dependency? In particular, if your version of imagej-legacy is too old, then the “ImagePlus” parameter will not be autofilled from currently open images.

So, one thing that occurred to me: you need to be careful with usage of ij.* packages mixed with ImageJ2 calls, because ImageJ2 performs runtime patching on ImageJ 1.x classes to enhance them for various purposes (e.g., for headless mode). One easy way to “be careful” is to split out your initial creation of the SciJava application context from any code that references IJ1 classes directly.

To that end, here is a working (on my system) version of your command.

MyCancelableCommand.java

package myCancelableCommand;

import org.scijava.command.Command;
import org.scijava.command.DynamicCommand;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;

import ij.IJ;
import ij.ImagePlus;

@Plugin(type = Command.class,
	menuPath = "SCF>test IJ2 command>testCancelReason")
public class MyCancelableCommand extends DynamicCommand {

	@Parameter
	ImagePlus imp;

	@Override
	public void run() {
		IJ.log("hello, image name is:" + imp.getTitle());
	}

	@Override
	public void cancel() {
		IJ.log(getCancelReason());
		if (imp != null) IJ.log("script is canceled but image name is:" + imp
			.getTitle());

	}

}

TestMyCommand.java

package myCancelableCommand;

import ij.IJ;
import ij.ImagePlus;

import net.imagej.ImageJ;
import net.imagej.patcher.LegacyInjector;

public class TestMyCommand {

	static {
		// NB: Needed if you mix-and-match IJ1 and IJ2 in this class.
		// And even then: do not use IJ1 classes in the API!
		LegacyInjector.preinit();
	}

	public static void main(final String... args) throws Exception {
		// Launch ImageJ as usual.
		final ImageJ ij = net.imagej.Main.launch(args);

		// Show the user interface.
		ij.ui().showUI();

		// Open an image.
		ImagePlus blobs = IJ.openImage("http://imagej.nih.gov/ij/images/blobs.gif");
		blobs.show();
		// Alternately, use ImageJ2:
//		Object blobs = ij.io().open("http://imagej.nih.gov/ij/images/blobs.gif");
//		ij.ui().show(blobs);

		// Launch the command.
		ij.command().run(MyCancelableCommand.class, true);
	}

}

Hope it helps!

Hi Guys,

Thanks a lot for all you feedbacks.
@rimadoma, I just shared the code there. for the dataset version I just replaced the ImagePlus calls and parameter by dataset calls and parameter. however I did not change the main function.

@ctrueden, Regarding the use of DynamicCommand, I initially try to make a basic interactive threshold. For that purpose I needed the DynamicCommand to update a threshold parameter min and max attributes in the initializer. Everything worked fine except this cancellation issue which is why I tried to build a minimal example. This being said, I am still learning about the different type of commands and will have a look at the ContextCommand soon.

Ok, thanks

I use version 15.1.0 for the pom-imagej but I don’t specify any version for the dependencies. You can have look at the pom file

I try and give you some feedback. Thanks again.

1 Like

Hi @ctrueden,

Thanks again for the help.

I just tried the caller class you proposed earlier with the LegacyInjector.preinit(). Unfortunately the behavior is still the same as before.

If I call the command once (programatically or via the interface) with an image open it works. If call the command with no image open it returns me the expected message “An ImagePlus is required but none exist.”. Until now all is normal, but if after receiving the previous message, an image is open manually via the ui and the command is started then rather than returning the hello message it returns again “An ImagePlus is required but none exist.” and this despite the image is accessible in the plugin (I can print its name).

I also tried to replace all IJ1 call in the testCancelReason class by IJ2 call with no more success. I am a bit confused naw, could it be the manual interaction with the ui (that would use some IJ1 logic) that would create that unwanted behavior?

Are you using the File :arrow_forward: Open… command? Or some other plugin? I’d like to try to reproduce on my side if possible. But I’ll need an exact sequence of steps.

It might be a bug in the ImageJ Legacy component relating to how ImagePlus objects are handled. But again, I need to be able to reproduce in order to investigate further.

Hi Curtis,

I updated my code on gitlab
with the class present on gitlab here is what I do step by step

  • From eclipse I run the testCancelReason.java as java application. ImageJ opens, no image is open and when the command is ran a pop up shows with “An ImagePlus is required but none exist.”. The cancel function of the command write the same in the console window.

[INFO] A Dataset is required but none exist.

  • I validate the pop up window and open the blob image via the menu File>Open samples>Blobs.gif

  • I run the testCancelReason Command via the menu SCF>testIJ2Command>TestCancelReason. the popup show up again and now the console window has 2 new lines (also due to the cancel function of the command):

[INFO] A Dataset is required but none exist.
[INFO] script is canceled but image name is:blobs.gif

Thanks for the detailed instructions. I will take a look when I have time, and reply back with any findings.

Hi Guys,

The problem seem to be solved with the update of scijava-common to version to 2.56.0
I guess the behavior I described was closely related to that issue.

@hinerm :thumbsup: thanks you make my day!

Also to avoid confusion, in that particular command ImagePlus (IJ1) or Dataset (IJ2) seem to be interchangable.

Thanks all for your help and comments

3 Likes

Great, glad to hear that @hinerm fixed it. We will shoot to get that scijava-common 2.56.0 uploaded to the update site late this afternoon (U.S. time).

Edit: I uploaded scijava-common 2.56.0 to the Java-8 update site a little while ago, and all seems well. Please speak up if you notice continuing problems after updating.

1 Like

I 've just updated my Fiji installation and tried it. The cancellation now works like a charm.
Thanks a lot!

1 Like