imagej / imagej-legacy

ImageJ+ImageJ2 compatibility layer
https://imagej.net/libs/imagej-legacy
BSD 2-Clause "Simplified" License
14 stars 24 forks source link

using @Parameter to get current image gets last opened image #81

Open carandraug opened 9 years ago

carandraug commented 9 years ago

Apparently this is a bug " the ImageJ2 legacy layer, responsible for keeping the ImageJ2 data structures in sync with ImageJ 1.x.". I'm completely at loss trying to find where it stems from, and am only reporting here after being told to do so on the mailing list.

Consider the following example plugin which should print an image data type:

import org.scijava.command.Command;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import org.scijava.plugin.Menu;
import org.scijava.ItemIO;

import net.imagej.Dataset;

@Plugin (
  type      = Command.class,
  headless  = true,
  menu      = {
    @Menu (label = "Image"),
    @Menu (label = "Print data type")
  }
)
public class
PrintDataType implements Command
{

  @Parameter (persist = false)
  private Dataset dataset;

  @Parameter (type = ItemIO.OUTPUT, persist = false)
  private String dtype;

  public void
  run ()
  {
    dtype = dataset.getTypeLabelShort ();
  }
}

It requires closing the text window after each call. I open the sample image "blobs" and the plugin will print "8-bit" (expected). Then I open the sample "CT" and it prints "16-bit" (expected). I then select the blobs image, run it again but get "16-bit" (that was a surprise, I guess it's choosing the last opened image). So I change the CT to 8-bit using "Edit > Type", run the plugin again but still get back "16-bit" (uh! I have no idea of what's going on).

Please, also note that running the same command on the same image will not print the data type again, it needs to be closed.

ctrueden commented 9 years ago

@carandraug described three different buggy behaviors on the mailing list thread:

  1. it was picking the last opened image instead of last active;
  2. it was giving the data type of the image when opened and not the current data type;
  3. running the same plugin on the same image would do nothing if the window was still open

My initial analysis (without having dug deeply into the code yet) is:

1) it was picking the last opened image instead of last active;

This is probably a simple bug where ImageJ1 activates an image and the ImageJ2 DisplayService is not notified to activate its corresponding linked ImageJ2 display. Likely easy to fix.

2) it was giving the data type of the image when opened and not the current data type;

This is a much more difficult problem: when an ImageJ1 image changes, the linked ImageJ2 must change to match. But "change" is a vague term—there are several sorts of changes. Pixel values changing is easy because the two data structures wrap the same primitive arrays by reference. But when the type changes, the IJ2 dataset must be rebuilt. So it seems likely that is not happening as expected here.

3) running the same plugin on the same image would do nothing if the window was still open

Probably related to one or both of the other issues above. Which image is active is out of sync between IJ1 and IJ2 at that point.

Relatedly, I want to draw your attention to #82, which is slated to actually remove support for this sort of workflow by default, until such a time as we can make the IJ1 :left_right_arrow: IJ2 syncing more performant and robust. Right now, it hoses up too many existing IJ1 workflows. So my advice—much as it pains me to say—is to hold off on creating these sorts of IJ2 Commands until the IJ2 API and ImageJ Legacy layer have matured further, which will likely be several more months. Until then, you can still use the @Parameter annotations with ImageJ1 data structures and it should work more smoothly.