Incorrect positioning of ROI when adding to ROI Manger via script

roi-manager
imagej
roi
groovy

#1

Hi everyone,

I have noticed that when you programmatically add an ROI that doesn’t have a position set to the ROI Manager, the current position of the active image is assumed to be the ROI position. The position of the ROI, however, seems to be somehow wrong or at least I can’t make a sense of it.

Here is an example Groovy script that shows the described behavior:

import ij.IJ;
import ij.gui.EllipseRoi;
import ij.plugin.frame.RoiManager;

/* Open sample image and set position */
imp = IJ.openImage("http://imagej.nih.gov/ij/images/confocal-series.zip");
imp.show();
imp.setPosition(2, 25, 0);

/* Create ROI without explictly setting position */
r = new EllipseRoi(20, 20, 40, 40, 1);

/* Add ROI to ROI Manager */
roiManager = RoiManager.getInstance();
if ( null == roiManager ) {
	roiManager = new RoiManager();
}
roiManager.addRoi(r);

/* Verify position of ROI */
rVerify = roiManager.getRoi(0);
println(rVerify.getCPosition()); // 0, should print 2
println(rVerify.getZPosition()); // 25
println(rVerify.getTPosition()); // 1, should print 1

Also, if I try to r.setPosition(x, y, z); to some other position, the position of the currently active image overrides. Does anyone know how to solve that issue without changing the position of the image?

Best,
Stefan


#2

Hi @stelfrich

I think the problem lies in your ImagePlus for some magical reason. If you use the HyperstackConverter on the image, it behaves as expected… So the test image you are using is somehow not opening as a ‘proper’ hyperstack and that’s why?

At least you have this as a hack for now but it will be nice to get to the bottom of this.

import ij.IJ;
import ij.gui.EllipseRoi;
import ij.plugin.frame.RoiManager;
import ij.plugin.HyperStackConverter
/* Open sample image and set position */
imp = IJ.openImage("http://imagej.nih.gov/ij/images/confocal-series.zip");
imp = HyperStackConverter.toHyperStack(imp, 2, 25, 1, "default", "Color");
imp.show();
imp.setPosition(2, 25, 0);

/* Create ROI without explictly setting position */
r = new EllipseRoi(20, 20, 40, 40, 1);

/* Add ROI to ROI Manager */
roiManager = RoiManager.getInstance();
if ( null == roiManager ) {
	roiManager = new RoiManager();
}
roiManager.addRoi(r);

/* Verify position of ROI */
rVerify = roiManager.getRoi(0);
println(rVerify.getCPosition()); // 2, should print 2
println(rVerify.getZPosition()); // 25
println(rVerify.getTPosition()); // 1, should print 1

#3

Thanks for looking into it @oburri! The magic part in your “hack” is going from a Composite to a regular color representation of the image. If the ImagePlus is shown as a composite, the channel is set to 0 as to imply the ROI is on all channels. That solves the first part!

Any ideas why r.setPosition(x, y, z) should not override, @oburri?

import ij.IJ;
import ij.gui.EllipseRoi;
import ij.plugin.frame.RoiManager;
import ij.plugin.HyperStackConverter;

/* Open sample image and set position */
imp = IJ.openImage("http://imagej.nih.gov/ij/images/confocal-series.zip");
imp.show();
imp.setDisplayMode(IJ.COLOR);
imp.setPosition(2, 25, 1);

/* Create ROI without explictly setting position */
r = new EllipseRoi(20, 20, 40, 40, 1);
r.setPosition(1, 1, 1);

/* Add ROI to ROI Manager */
roiManager = RoiManager.getInstance();
if ( null == roiManager ) {
	roiManager = new RoiManager();
}
roiManager.addRoi(r);

/* Verify position of ROI */
rVerify = roiManager.getRoi(0);
println(rVerify.getCPosition()); // 2, should print 1
println(rVerify.getZPosition()); // 25, should print 1
println(rVerify.getTPosition()); // 1, should print 1

#4

Seems the RoiManager goes to great lengths to update the imp position based on the ROI so that when the ROI is finally saved into the manager, the position is set from the image.

Roi roiCopy = (Roi)roi.clone();
roiCopy.setPosition(imp);

So if the channel is set to 0 for composites, then no matter what is done before, it will have the wrong channel position.


#5

So the gist is, that in order to add an ROI to the ROI Manager from a scripting language, you have to switch to the position on the active image. imp.setPositionWithoutUpdate(x, y, z) is your friend in that case. And roi.setPosition(x, y, z) only works well in combination with an Overlay.