Adding ROI overlay on hyperstacks

Hello everyone!

I am trying to add an overlay of a selection created by a user on every 10 frames. I am testing this for now on the Mitosis image from FIJI. Steps followed are as follows:

  1. Open and display image. Ask the user to draw a ROI (at t=1)
  2. Get ROI from the user - add to overlay
  3. Jump to t=11, ask the user to adjust the same ROI by moving it around in the image.
  4. Get the new ROI and add to overlay.

In the end, display image with overlay on all channels, slices but t=1, t=11, t=21…

Sample code:

from ij import IJ 
from ij.gui import GenericDialog, NonBlockingGenericDialog, WaitForUserDialog, Overlay

# open image and display
imp = IJ.openImage("http://wsr.imagej.net/images/Spindly-GFP.zip");
# imp = IJ.getImage();
imp.show()
imp.killRoi(); 
imp.setT(1);

WaitForUserDialog("Action required", "Draw a rectangular ROI and press ok").show() 
roi = imp.getRoi();

ov = Overlay()

for t in xrange(1, imp.getNFrames() + 1, 10):
	imp.setT(t);
        
    # at t=1, set roi and add roi to overlay
	if t ==1:
		imp.setRoi(roi)

        # which function to use here?
        # goal: set roi on all Z, C but only on current T

#		roi.setPosition(0, 0, t);                          # overlay seen on last t stopped, all z, c
#		roi.setPosition(imp.getC(), imp.getSlice(), t);    # no overlay seen
		ov.add(roi)                                        # last roi drawn on all c, z, t
      
    # at t=11, 21, .. ask user to move roi 
    # get the new roi and add to overlay
	else:
		gd = NonBlockingGenericDialog("Action required at T=" + str(t))
		gd.addMessage("Move the ROI to your area of interest by clicking inside the rectangle")
		gd.addMessage("Addtionally, check the box if you want to stop here")
		gd.addMessage("Click ok")
		gd.addCheckbox("Stop here?", False)
		gd.showDialog()
		
		roi_new = imp.getRoi()
		imp.setRoi(roi_new)
       
        # same goal as above, set roi on all Z, C but only on current T
#		roi_new.setPosition(0, 0, t);                       # overlay seen on last t stopped, all z, c
#		roi.setPosition(imp.getC(), imp.getSlice(), t);     # no overlay seen
		ov.add(roi_new)                                     # last roi drawn on all c, z, t
	
		if gd.wasCanceled():
			pass

		# if box is checked, exit the loop
		if gd.getNextBoolean() == True:
			print("Exiting loop")
			break


print("Out of loop")

imp_final = imp.duplicate();
imp_final.setOverlay(ov)
imp_final.show()

Challenges

  • If I use just ov.add(roi) I see an overlay on all the C, Z, T but the ROI does not change even if the user changed it. It stays the same as the ROI on the last time point I stopped at for e.g. at T=31.
  • I was expecting that roi.setPosition(0, 0, t) and then ov.add(roi) should set the overlay to all C, Z but only to the current value of t. If I do this, I see an overlay in the final image only at t where I stopped and nothing on previous time-points. However, this overlay is on all C and Z.
  • Similarly, I felt that explicitly stating the position using roi.setPosition(imp.getC(), imp.getSlice(), t) should do the trick, this does not help as well.

Specs

FIJI ImageJ version 2.1.0/1.53c up-to-date, MacOS Catalina

Related topics:

Could anyone help me solve this mystery and point to the correct way to do this? Thanks!

1 Like

Hey @gayaJ,

I recently struggled at a similar point and concluded at some point that the setPosition method with three parameters is kind of obsolete. Would you mind trying it with one parameter - the slice position in the hyperstack?

Also feel free to check the code where I did this recently:
https://github.com/clij/assistant/blob/598cac69e02b18db7bfb6fcfd4a2a94e02ee5989/src/main/java/net/haesleinhuepf/clijx/assistant/annotation/AnnotationTool.java#L92-L93

Let us know if this helps!

Cheers,
Robert

Hey Robert!

Thanks for the heads-up. I think roi.setPosition(imp.getSlice()) is more suited for stacks and I am dealing with a hyperstack. Even then I gave it a try. I can see now an overlay only on z=1, t=1 and both channels only which is not what I want sadly.

I found the solution though :smiley: courtesy of a tip from @noreenw! So I set the position to (0, 0, t) so as to paste it to all z, c but to specific t and then clone the ROI before adding it to the overlay. This works, but I do not have much explanation on how and why it worked. I am sure someone has a better explanation for this behaviour.

Working code:

from ij import IJ 
from ij.gui import GenericDialog, NonBlockingGenericDialog, WaitForUserDialog, Overlay

# open image and display
imp = IJ.openImage("http://wsr.imagej.net/images/Spindly-GFP.zip");
#imp = IJ.getImage();
imp.show()
imp.killRoi(); 
imp.setT(1);

WaitForUserDialog("Action required", "Draw a rectangular ROI and press ok").show() 
roi = imp.getRoi();

ov = Overlay()

for t in xrange(1, imp.getNFrames() + 1, 10):
	imp.setT(t);
        
    # at t=1, set roi and add roi to overlay
	if t ==1:
		imp.setRoi(roi)

        # which function to use here?
        # goal: set roi on all Z, C but only on current T

#		roi.setPosition(0, 0, t);                          # overlay seen on last t stopped, all z, c
#		roi.setPosition(imp.getC(), imp.getSlice(), t);    # no overlay seen
#		roi.setPosition(imp.getSlice())                    # overlay seen on z=1, t=1 and all c
#		ov.add(roi)										   # last roi drawn on all c, z, t
 
		# this works
		roi.setPosition(0, 0, t);
		ov.add(roi.clone())                                        
      
    # at t=11, 21, .. ask user to move roi 
    # get the new roi and add to overlay
	else:
		gd = NonBlockingGenericDialog("Action required at T=" + str(t))
		gd.addMessage("Move the ROI to your area of interest by clicking inside the rectangle")
		gd.addMessage("Addtionally, check the box if you want to stop here")
		gd.addMessage("Click ok")
		gd.addCheckbox("Stop here?", False)
		gd.showDialog()
		
		roi_new = imp.getRoi()
		imp.setRoi(roi_new)
       
        # same goal as above, set roi on all Z, C but only on current T
        
#		roi_new.setPosition(0, 0, t);                       # overlay seen on last t stopped, all z, c
#		roi.setPosition(imp.getC(), imp.getSlice(), t);     # no overlay seen
#		roi.setPosition(imp.getSlice())						# overlay seen on z=1, t=1 and all c
#		ov.add(roi_new)                                     # last roi drawn on all c, z, t

		# this works
		roi_new.setPosition(0, 0, t);  
		ov.add(roi_new.clone())
		
		if gd.wasCanceled():
			pass

		# if box is checked, exit the loop
		if gd.getNextBoolean() == True:
			print("Exiting loop")
			break


print("Out of loop")

imp_final = imp.duplicate();
imp_final.setOverlay(ov)
imp_final.show()


2 Likes