ROI save (in a macro) loses slice information; Image J ver1.53g

Sample image and/or code


/* 2020_12 by SD, BW
 *  
 *  I post a working subset of a macro to allow me to draw ROI lines & measure the underlying pixel intensities across two or more channels, and on differing slices for any .tif or .zvi image.  multichannel stack
 *  You will be prompted for:
 *  --  line width 
 *  --  the # of experimental interfaces to draw 
 *  An Intensity Results file will be named & automatically saved to your directory
 *  The ROIs will be named & automatically saved to your directory.  
 * */


imageToAnalyze = getImageID();                  
imageTitle=getInfo("image.filename"); 

print("   imageToAnalyze: "+imageToAnalyze, "   imageTitle: "+imageTitle);		// debug line

getDimensions(w, h, channels, slices, frames);
  print("   Channels: "+channels, "   Slices: "+slices, "   Frames: "+frames);		// debug line


// User input for pixel width to measure 

  lineWidth=5;				//  default line width
  Dialog.create("Select line width");
	//  Dialog.addString("Title:", title);      // not needed for this dialog
  Dialog.addChoice("Width (pixels):", newArray("1", "2", "3", "4", "5", "6", "7"));
  Dialog.show();
  lineWidth = Dialog.getChoice();
		print("   lineWidth: "+lineWidth);		// debug line
  
  setTool(5);  									//  Chooses the 'Line' tool 
  setTool('polyline');							//  Chooses the 'Segmented line' subset of the Line tool
  run("Line Width...", "line=lineWidth"); 		//  Feeds in user's choice of line width

// End User input pixel width to measure


//  User input, "How many measurements"?
 Interfaces=3;											// Default = 3 exp't'l interfaces
  Dialog.create("Select Number of interfaces to Measure on this slice");
  Dialog.addChoice("# of Exp't'l Interfaces:", newArray("1", "2", "3", "4", "5", "6", "7"));
  Dialog.show();
  Interfaces = Dialog.getChoice();						//  Feeds in user's choice of interface #
		print("   Experimental Interfaces: "+Interfaces);			// debug line

for (i=1; i <= Interfaces; i++) {						//  Loop to draw # of lines selected in dialog above by user

		beep();                                              // alert the user
		waitForUser("Trace interface #" +i, " \n Then close this dialog");  // wait for user action

 Roi.setName("exptlInterface" +i); 						//  Adjust exp't'l ROI name to # interface

  roiManager("Add");

}							//  End user measurements

  	/* Next snippet returns the z and timepoint position 
  	 *  in order to label the saved Results & ROI files 
  	 *  	in the functions called below.
  	 */
  	 
 	Stack.getPosition(channel, slice, frame);	 // This yields slice where background was taken;  Mistake: Why get info here?  
  	z=slice;
  	tp=frame;

  run("Clear Results");									//  Clear prior Results Table; preparing to store measured values.

 Dialog.create("Is image a tif or zvi?");
  Dialog.addChoice("ImageFormat", newArray("tif", "zvi"));
  Dialog.show();
  imageFormat = Dialog.getChoice();						//  Feeds in user's choice of format
		print("   ImageFormat is: "+imageFormat);			// debug line

		

measure_saveResults();					//  calls a function to measure & save each channel/each ROI (see below)
	saveROIManager(); 						//  calls a function to Save ROIs (see below)

function measure_saveResults() {		//  Function to measure each channel/each ROI and save results in image directory 
 
	path = getDirectory("image");
  	t = getTitle;
  			print("   path: "+path, "   t: "+t);					// debug line
	
if (endsWith(t, imageFormat)) 
    t = replace(t, imageFormat, "");
  t = t + "txt";										// give Results the image name; prepare to save a txt file
  t = "Intensity" +"_z" +z +"_tp" +tp +t;									//	precede filename with a string to identify ("Intensity")
  // t = "Intensity"  +t;

n = roiManager("count");
  for (i=0; i<n; i++) {						//  iterate through each ROI
      roiManager("select", i);
  
	c=channels;
//		print("   'c' Channel: "+c);					// debug line
//				print("   Channels: "+channels);		// debug line

	for (c=1; c <= channels; c++) {						//  Loop through each channel, set it, measure it; total # channels came from line 12 
		Stack.setChannel(c);	
		 roiManager("measure");							// dumps measurements into Results Table
		//roiManager("multi measure");
		print("   Measuring Channel: "+c);				// debug line

		}
 	 }

 	 /*
 *  This 'For Loop' adds informative ROI names to Results Labels ('exptlinterface1', etc...).
 */
	 for (i=0; i<nResults; i++) {
   		oldLabel = getResultLabel(i);
    	delimiter = indexOf(oldLabel, ":");
    	newLabel = substring(oldLabel, delimiter+1);
    	setResult("Label", i, newLabel);
  }

  selectWindow("Results");
  saveAs("text", path+t);								// save Results as a 'text' file in image directory
		print("   Results_datasave_path: "+path+t);			// debug line

print("   ImageFormat from measure_saveResults is: "+imageFormat);

} 


  function saveROIManager() {						//  Function to Save ROIs in image directory 
  path = getDirectory("image");						//  likely redundant; assigned 'path' variable already in line #76
 t = getTitle;
   print("   path: "+path, "   t: "+t);			// debug line

 //	print("   ImageFormat inside saveROIManager is: "+imageFormat);

  if (endsWith(t, imageFormat)) 						//  "tif" should be replaced by the returned variable, "imageFormat"; example in measure_saveResults function
    t = replace(t, imageFormat, "");
  	t = t + "zip";									// give ROI the image name; prepare to save as a zip file
  	t = "IntensityROIs"+"_z" +z +"_tp" +tp +t;							//	precede name of file with entered string ("IntensityROIs")

   	selectWindow("ROI Manager");
    roiManager("deselect");							// If an ROI is selected, only that ONE ROI will be saved; none selected --> all saved
 
 roiManager("save", path+t);
 		print("   ROI_datasave_path: "+path+t);			// debug line
  
}		

Background

Analysis goals

  • This macro was designed to extract quantitative info from a multi-channel stack in a “semi-automated” manner. The macros asks for certain User inputs; the user draws lines on image areas they wish to measure; the ROIs are stored, given informative names and then read, registering intensity values from each channel and each ROI. The Results table and the ROIs are automatically saved to respective files associated with the image. The scale of this analysis is not large at all; simple segmented lines, maybe 3 - 6 to be read per multichannel stack.

Challenges

With Image J version 1.53g, the ROIs no longer preserve slice information; the macro worked well in earlier versions of Image J, although I am not certain in which update the issue first arose. Reverting to version 1.51w allows ithe Macro to work perfectly (1.52 did not allow it to work, I recall).

I have read some discussions about difficulties with ROIs within Macros, but my noobie self has not found one that closely enough parallels my case for me to understand how to apply (or whether to apply) the suggestions made. Example: ROI Manager saving error

Please provide an image so we can run this macro.

testMacro.tif (3.0 MB). Thank you; apologies for not including initially. This is a two-channel, three slice image. I also uploaded the .txt file of saved Results Table, and the .zip file for a saved ROI set executed using the above macro with Image J 1.51w. Intensity_z3_tp1testMacro.txt (505 Bytes) IntensityROIs_z3_tp1testMacro.zip (696 Bytes)

I get a “No selection in line 52” error when I run this macro on the testMacro.tif image, on both ImageJ 1.53g and 1.51w.

I am sorry; I do not know why that happened for you. You are being very patient, I appreciate it. I will re-upload the macro and the .tif. I double checked and just ran them on 1.51w (version # screenshot attached), and again they properly produced the two attached files (a Results.txt file - named in a longer manner - and an ROI.zip file). In case, here is the sequence of events you should experience upon running the Macro. Dialog asks the user to: 1) “Select line Width” (pls choose some value from drop-down); 2) Next dialog: "Select the number of interfaces you wish draw (select, say, 2, from drop-down); 3) Next dialog: "Trace Interface #1; then close this dialog (pls do so - the segmented line should be activated); 4) If you selected ‘2’ interfaces, another dialog will appear: "Trace Interface #2; then close this dialog - feel free to switch z slice for interface #2; 5) Next dialog: Is the Image a .tif or a .zvi? (pls. choose .tif for this case). The ROI manager will open and show two named entries, the Results table will show the measurements (dependent on what was set in “Set Measurements”). Both of those files are saved to disk; examples shown here.

testMacro.tif (3.0 MB) IntensityROIs_z3_tp1testMacro.zip (470 Bytes) Intensity_z3_tp1testMacro.txt (345 Bytes)


/* 2020_12 by SD, BW
 *  
 *  A subset of a macro to draw ROI lines & measure the underlying pixel intensities across two or more channels.
 *  You will be prompted for:
 *  --  line width 
 *  --  the # of experimental interfaces to draw 
 *  An Intensity Results file will be named & automatically saved to your directory
 *  The ROIs will be named & automatically saved to your directory.  
 * */


imageToAnalyze = getImageID();                  
imageTitle=getInfo("image.filename"); 

print("   imageToAnalyze: "+imageToAnalyze, "   imageTitle: "+imageTitle);		// debug line

getDimensions(w, h, channels, slices, frames);
  print("   Channels: "+channels, "   Slices: "+slices, "   Frames: "+frames);		// debug line


// User input for pixel width to measure 

  lineWidth=5;				//  default line width
  Dialog.create("Select line width");
	//  Dialog.addString("Title:", title);      // not needed for this dialog
  Dialog.addChoice("Width (pixels):", newArray("1", "2", "3", "4", "5", "6", "7"));
  Dialog.show();
  lineWidth = Dialog.getChoice();
		print("   lineWidth: "+lineWidth);		// debug line
  
  setTool(5);  									//  Chooses the 'Line' tool 
  setTool('polyline');							//  Chooses the 'Segmented line' subset of the Line tool
  run("Line Width...", "line=lineWidth"); 		//  Feeds in user's choice of line width

// End User input pixel width to measure


//  User input, "How many measurements"?
 Interfaces=3;											// Default = 3 exp't'l interfaces
  Dialog.create("Select Number of interfaces to Measure on this slice");
  Dialog.addChoice("# of Exp't'l Interfaces:", newArray("1", "2", "3", "4", "5", "6", "7"));
  Dialog.show();
  Interfaces = Dialog.getChoice();						//  Feeds in user's choice of interface #
		print("   Experimental Interfaces: "+Interfaces);			// debug line

for (i=1; i <= Interfaces; i++) {						//  Loop to draw # of lines selected in dialog above by user

		beep();                                              // alert the user
		waitForUser("Trace interface #" +i, " \n Then close this dialog");  // wait for user action

 Roi.setName("exptlInterface" +i); 						//  Adjust exp't'l ROI name to # interface

  roiManager("Add");

}							//  End user measurements

  	/* Next snippet returns the z and timepoint position 
  	 *  in order to label the saved Results & ROI files 
  	 *  	in the functions called below.
  	 */
  	 
 	Stack.getPosition(channel, slice, frame);	 // This yields slice where background was taken;  Mistake: Why get info here?  
  	z=slice;
  	tp=frame;

  run("Clear Results");									//  Clear prior Results Table; preparing to store measured values.

 Dialog.create("Is image a tif or zvi?");
  Dialog.addChoice("ImageFormat", newArray("tif", "zvi"));
  Dialog.show();
  imageFormat = Dialog.getChoice();						//  Feeds in user's choice of format
		print("   ImageFormat is: "+imageFormat);			// debug line

		

measure_saveResults();					//  calls a function to measure & save each channel/each ROI (see below)
	saveROIManager(); 						//  calls a function to Save ROIs (see below)

function measure_saveResults() {		//  Function to measure each channel/each ROI and save results in image directory 
 
	path = getDirectory("image");
  	t = getTitle;
  			print("   path: "+path, "   t: "+t);					// debug line
	
if (endsWith(t, imageFormat)) 
    t = replace(t, imageFormat, "");
  t = t + "txt";										// give Results the image name; prepare to save a txt file
  t = "Intensity" +"_z" +z +"_tp" +tp +t;									//	precede filename with a string to identify ("Intensity")
  // t = "Intensity"  +t;

n = roiManager("count");
  for (i=0; i<n; i++) {						//  iterate through each ROI
      roiManager("select", i);
  
	c=channels;
//		print("   'c' Channel: "+c);					// debug line
//				print("   Channels: "+channels);		// debug line

	for (c=1; c <= channels; c++) {						//  Loop through each channel, set it, measure it; total # channels came from line 12 
		Stack.setChannel(c);	
		 roiManager("measure");							// dumps measurements into Results Table
		//roiManager("multi measure");
		print("   Measuring Channel: "+c);				// debug line

		}
 	 }

 	 /*
 *  This 'For Loop' adds informative ROI names to Results Labels ('exptlinterface1', etc...).
 */
	 for (i=0; i<nResults; i++) {
   		oldLabel = getResultLabel(i);
    	delimiter = indexOf(oldLabel, ":");
    	newLabel = substring(oldLabel, delimiter+1);
    	setResult("Label", i, newLabel);
  }

  selectWindow("Results");
  saveAs("text", path+t);								// save Results as a 'text' file in image directory
		print("   Results_datasave_path: "+path+t);			// debug line

print("   ImageFormat from measure_saveResults is: "+imageFormat);

} 


  function saveROIManager() {						//  Function to Save ROIs in image directory 
  path = getDirectory("image");						//  likely redundant; assigned 'path' variable already in line #76
 t = getTitle;
   print("   path: "+path, "   t: "+t);			// debug line

 //	print("   ImageFormat inside saveROIManager is: "+imageFormat);

  if (endsWith(t, imageFormat)) 						//  "tif" should be replaced by the returned variable, "imageFormat"; example in measure_saveResults function
    t = replace(t, imageFormat, "");
  	t = t + "zip";									// give ROI the image name; prepare to save as a zip file
  	t = "IntensityROIs"+"_z" +z +"_tp" +tp +t;							//	precede name of file with entered string ("IntensityROIs")

   	selectWindow("ROI Manager");
    roiManager("deselect");							// If an ROI is selected, only that ONE ROI will be saved; none selected --> all saved
 
 roiManager("save", path+t);
 		print("   ROI_datasave_path: "+path+t);			// debug line
  
}		
`type or paste code here`

Hi @sdinardo,

Add

  Stack.getPosition(channel, slice, frame); 
  Roi.setPosition(channel, slice, frame);

just before

roiManager("Add");

and your macro should work as expected.

Very much appreciated. Works now for us. Thank you for sticking with me. Since we intend for the Macro to measure ‘all’ channels on each roi, I edited the above to:

Stack.getPosition(channel, slice, frame); 
  Roi.setPosition(slice);

(I might need to edit ‘frame’ back in for time series images, but I’ll figure that out myself to be certain).