Texture Analysis on ROIs from Analyze Particles

Hi all, I have many images of nuclei that contain foci of various sizes. Each image contains just one nucleus and I process the whole batch of images first by using a threshold and making the image binary then use analyze particles to extract information about the foci. Next up I would like to do texture analysis using the GLCM Texture plugin. Since Threshold creates a binary image, that won’t work since it removes the texture. Instead I suppose I will need to use the ROIs found from analyze particles and use them to define the features in the original/ unprocessed image and have GLCM analyze these ROIs. I’m not sure how to go about this, certainly not at the batch level since there are too many files to do one at a time. For example, here is an unprocessed image with the foci.

and I would like to analyze the texture of the objects within these regions (which are outputs of the threshold/analyze particles step):

@wustlmed
Hello there,
Not sure if i understood you completely…But you would like to run the GLCM plugin on a batch of images that have been thresholded? Is that right?
Best wishes,
Praveen

I’ve written a macro to do something similar…

In the big picture you want to…

Open original and define as “t” or other variable name
Threshold and analyze particles,
Save to Roi saving as roi+t
Then return to original process your GLCM on roi
Then clear Rois and start again.

My process are different, I have my originals in two folders and I have some QC steps coded in to make sure all the files are in both folders etc.

But see if this helps, I’ve tried to leave this generic and take out my specific process code, If I took too much out of the loops to be helpful let me know and I can get specific lines back.

// Macro code for batch processing a folder of .tif files, includes saving .tifs back into the 
// ORIGINAL folder with a modified version of the original image name

print("start directory loop");
dir = getDirectory("Choose input segment Directory");     
// prompts the user to select the folder to be processed,  you might only have one dir. 

list = getFileList(dir);                                    // gives ImageJ a list of all files in the folder to work through
print("number of files in dir1 Segments",list.length);      // optional prints the number of files in the folder


dir2 = getDirectory("Choose input Image Directory "); 	// promts user to select folder to be saved in
list2 = getFileList(dir2);                 				// gives ImageJ a list of all files in the folder to work through for directory2 
extension2 = ".tif";   									//defines file type  variable 

print("number of files in dir2 Image",list2.length);                 // optional prints the number of files in the folder


dir3= getDirectory("Choose output Directory"); //promts user to select folder on Images for Results

setBatchMode(true);               // runs up to 6 times faster, without showing images onscreen.  Turn off during troubleshooting steps??


dbugp = 1;         				  //verbose print for debug                                                                  

 

// Note that the above processes are outside the loop brackets {  }, 
// so they will only be called once at the beginning of the macro

//for my process I compared the lists in Dir1 and 2 I took that code out for simplicity.  
 
print("START...");

// main files loop
// (process every image until you get to the bottom of the list) 

for (f=0;  f<list.length; f++) {
        path = dir+list[f];          // creates the filepath for reading  Segmentation files
	if(dbugp>0) {             
     	// optional prints the path & file name to a log window
		print("Name of path reading file from dir1",path); 
	}

       
	showProgress(f, list.length);    
	// optional progress monitor displayed at top of Fiji
	
	if(!endsWith(path,"/")) {
	       open(path);
	}
	// if subdirectory, push down into it Still have to open Path
	
	        
	
	/*
	if (nImages>=1) {  // stop when there
	are no more open images */
	   
	
	t=getTitle();    // gets the name of the image being processed   
	
	//add your specific steps to create threshold and Roi  
	n=roiManager("count");
	print("ROI_number=" + n); 
	//roiManager("Rename",tt+"roi"+n);
	if(roiManager("count")>0) {
		roiManager("Save", dir3 + tt +"roi"+n +".zip");
	 	for(i=0; i<n; i++) {
			roiManager("Select",i);
	
			//Now open t again or return to original do you GLCM process 
	      }
	}
	
	roiManager("Deselect");
	roiManager("Delete");            
	// Closes a loop.  Note there are as many } as there are { in the code, and each } is on it's own line
}

                                    }
selectWindow("Results");
saveAs(dir3+"WantedFileName.txt");
selectWindow("Log");
saveAs(dir3+"runlog.txt");
  // END processing per image

3 Likes

Hi Praveen,

Thanks for the reply- Perhaps this explains better: I want to run the GLCM plugin on many individual ROIs. These ROIs are the blue foci you see in my image above- and get defined by the thresholding procedure. Unfortunately though GLCM is a texture analysis tool and so the binary output of the threshold is no good, each ROI is completely smooth. As such I would like to use the areas defined by the thresholding procedure to define an ROI in my original 8-bit image, but I’m not sure how to do this. The next step would probably be then to extract each of these ROIs so that GLCM can be run on each one.

@susan-sheehan

Thank you for the great reply! - I’ve been playing around trying to get it to work but I seem to be having some trouble. I keep getting the erro that “The list is empty” and the log says ROI_number=0. I think I must not be understanding the inputs correctly.

What I used is basically a folder containing the binary images above, the next input was the folder containing the raw images which needed texture analysis in the appropriate ROIs, and then I specified some separate output folder.

In general though what you’ve written seems to be on the right track. I will need to open a thresholded image, and based on what survives the cutoff generate ROIs. Then to use these ROIs on to specify regions in the original image that will be processed by GLCM.

Best,
M

@wustlmed
Hello,
Ok, so here is what you can try. First get all the ROI you want to measure in your images by choosing a threshold. Then restore the ROI on your original image (blue). Then you may choose which ROI you want to measure on the image and then run the GLCM plugin. You would have to do this for each ROI though. Here is a screenshot.

1 Like

If you moved the Binary Images into a separate folder, are you still running the analyze particles on them? you will need to do that in order to generate ROIS

In your case, I think I wouldn’t make a folder for the binary Images that seems like more work and manual interaction than needed

Try this work flow and let me know if you get errors (and your code)

Define input folder
Define output folder
Open Original
duplicate
On one copy
Threshold and analyze partices
Save the Roi’s for QC later
Select other copy
Run GLCM
Select ROI and get measurements
Close loop
Clear Rois
Return to start of list and repeat for all Images in folder
Save results
I find it really helpful to save the summary and log as well (I also add print statements in as a simple QC step) then If I have questions later its easy to track what you did and repeat, its also why I have the Rois

@Praveen Thanks! I didn’t know the ROI manager could store them in such a way. Do you know if there is a a way to analyze all the particles in the ROI manager? I have +8000 foci and so doing each one at a time would be challenging.

Hi Susan,

Thanks for the reply again, I think I understand my mistake from above. I was using the thresholded images as input 1. From your code posted above are you using the ROIs saved in the ROI manager, is that what you mean by “segment directory”. So dir = the ROI list from roi manager, then dir2= the blue/unprocessed images and dir3 = output? I guess I’'m confused because in your code you also have indicated that there is an area to add steps to create a threshold and ROI. after t=get title () so I’m not clear at what point in processing your inputs are. I have separate files containing raw images, thresholded images, and then the analyze particle images and the corresponding measurements and ROIs.

What praveen posted above was very helpful, and I can now run GLCM on the generated ROIs in the ROI manager, the only problem is that with several thousand ROIs saved, clicking on each one is very slow. Am I correct in guessing that if I got your code to work, the loop specifying counts in the ROI manager actually cycles through the different ROIs generated?

you are correct, if you can get a working macro you will be able to point the computer to an input folder and an output folder and walk away and do something else while it processes all the Files/Images in the input folder. I like to have my input folders only have Images in them, but you can specify to say only look at .tiff Images in a specific folder.

In your case, I would modify the code to only have 2 directories, (Dir1- input and Dir2-output). I am doing some fairly complicated segmentation which gets inputs from Ilastik (Although I think I could use trainable wiki segmentation, although I haven’t played with that since I learned about it after I invested time into learning Ilastik and my work flow is not too cumbersome). That is unrelated but possibly for general future knowledge.

I personally still feel like a novice as far as writing macro’s go etc. but If you post your code here, I will try to help, the overall process sounds like what I have working. Additionally, Someone else might be able to help… One key piece of information when using ROIs and the ROI manager with a looping macro is that the Roi manager is general so you need to clear the roi manager between starting on a new Image or the ROI from Image 1 will be applied to Image 2 as well as the ROI for Image 2.

Great, in that case I will keep working on this avenue to automatically run GLCM on the ROIs. I started thinking that given what you posted above it would be good to have 3 directories. 1= input of the thesholded images since I already have that done. I will run analyze particles on these to generate ROIs which get stored in the ROI manager. dir2=the raw images before they were thresholded. I hope to overlap the ROIs on these images to then run the GLCM on those outlined features. and finally dir3= output.

I’m definitely very much a novice, many many steps below you, so thank you for the help so far. Based on your initial code I have come to the following below. I get an error in line 58 each time it runs though so no results yet. I basically changed the directories that I input and run analyze particles inside the loop to hopefully generate the ROIs and store them. I tried the record macro tool in order to get a process of how to then apply those ROIs overlaid onto a new image but had no luck, nothing records. The best I could find was manually going to Image>Overlay>from ROI manager. Then hopefully getting those to cycle

Here is the code:

// Macro code for batch processing a folder of .tif files, includes saving .tifs back into the 
// ORIGINAL folder with a modified version of the original image name

print("start directory loop");
dir = getDirectory("Choose input segment Directory, the thresholded image folder");     
// analyze particles will be run on these thresholded images to generate ROIs. 

list = getFileList(dir);                                    // gives ImageJ a list of all files in the folder to work through
print("number of files in dir1 Segments",list.length);      // optional prints the number of files in the folder


dir2 = getDirectory("Choose input Image Directory, the raw images "); 	// promts user to select folder to be saved in
list2 = getFileList(dir2);                 				// gives ImageJ a list of all files in the folder to work through for directory2 
extension2 = ".tif";   									//defines file type  variable 

print("number of files in dir2 Image",list2.length);                 // optional prints the number of files in the folder


dir3= getDirectory("Choose output Directory"); //promts user to select folder on Images for Results

setBatchMode(true);               // runs up to 6 times faster, without showing images onscreen.  Turn off during troubleshooting steps??


dbugp = 1;         				  //verbose print for debug                                                                  

 

// Note that the above processes are outside the loop brackets {  }, 
// so they will only be called once at the beginning of the macro

//for my process I compared the lists in Dir1 and 2 I took that code out for simplicity.  
 
print("START...");

// main files loop
// (process every image until you get to the bottom of the list) 

for (f=0;  f<list.length; f++) {
        path = dir+list[f];          // creates the filepath for reading  Segmentation files
	if(dbugp>0) {             
     	// optional prints the path & file name to a log window
		print("Name of path reading file from dir1",path); 
	}

       
	showProgress(f, list.length);    
	// optional progress monitor displayed at top of Fiji
	
	if(!endsWith(path,"/")) {
	       open(path);
	}
	// if subdirectory, push down into it Still have to open Path
	
	        
	
	/*
	if (nImages>=1) {  // stop when there
	are no more open images */
	   
	
	t=getTitle();    // gets the name of the image being processed   
	
	//add your specific steps to create threshold and Roi 
	run("Analyze Particles...", "display exclude include summarize add in_situ"); 
   // I think here what you are doing is using the ROIs found from analyze particles
	n=roiManager("count");
	print("ROI_number=" + n); 
	//roiManager("Rename",tt+"roi"+n);
	if(roiManager("count")>0) {
		roiManager("Save", dir3 + tt +"roi"+n +".zip");
	 	for(i=0; i<n; i++) {
			roiManager("Select",i);
	
			//Now open t again or return to original do you GLCM process 
              run("GLCM Texture", "enter=1 select=[0 degrees] angular contrast correlation inverse entropy");
              
	      }
	}
	
	roiManager("Deselect");
	roiManager("Delete");            
	// Closes a loop.  Note there are as many } as there are { in the code, and each } is on it's own line
}

                                    }
selectWindow("Results");
saveAs(dir3+"WantedFileName.txt");
selectWindow("Log");
saveAs(dir3+"runlog.txt");
  // END processing per image

and this is the error I get

getTitle()	*	"14d flight H2AX new 050515_4_Series007_NoLA_c1.tif" ( This is my thresholded image)
dir	*	"C:\Users\..... " (location of thresholded image)
list	*	array[2]
dir2	*	"C:\Users\....."(location of raw image)
list2	*	array[3]
extension2	*	".tif"
dir3	*	"C:\Users\..."(output location)
dbugp	*	1
f	*	0
path	*	"C:\Users\...." Location of thresholded images again. 
t	*	"14d flight H2AX new 050515_4_Series007_NoLA_c1.tif"
n	*	58

@wustlmed
Have not found out a way to analyse all the ROI in one go. But like you mentioned in your latest post, if there a macro to do that it would make things much easier for you. But ill try my best :slight_smile:

Line 58 seems to be a commented out line with a loop, what if you take this out… Does the error have any info as to what type of information it provides? How far does your log get?

Hi, Sorry for the delay, I’ve been out of town. Thanks for your continued help though, I appreciate it very much. So I ran it again and got an error in line 70. It seems to have identified the ROIs at least by doing analyze particles, but no texture analysis and no looping through other images.

The error reads
Undefined variable in line 70, RoiManager (“save",dir3+<tt>+"roi"+"n"+"zip").

In the log, it reads the following:

start directory loop
number of files in dir1 Segments 2
number of files in dir2 Image 3
START...
Name of path reading file from dir1 C:\Users\........tif
ROI_number=52

In looking at line 70, I suppose that what is going on is saving the ROIs in the Manager so that they can be recalled on the raw image for texture analysis. If you look above, at line 68 though it uses the same variables with no problem - roi, tt, and n - and the dir3 is defined in the beginning as the output file so I’m not sure where to go from here.

There’s indeed no variable tt defined anywhere in your code. If you want to use the current image title, you might want to use t here.

That line is commented out by the two slashes at the start of the line (//). The syntax highlighting of the script editor is useful to detect this kind of errors and generally make code more readable.

Please have a look at the macro language documentation and try to understand what’s going on in your code.

Hi Jan,

Thanks for the reply, I took a look at the documentation and it was helpful, had a lot of basic info in there which I certainly needed.

I removed the “t”, and an extraneous } bracket that generated an error in line 86. Now the code runs without errors but it seems to not be generating the appropriate results.

I ran the code on two test images which were threholded and according to the summary, about 50 ROIs were found in each image as I expected.
The Results table however displays a single result of texture analysis- suggesting it runs on just one of the ROIs. I’m not sure why this occurs as the GLCM analysis comes after the ROI manager cycling through ROIs. Any input you have on this would be appreciated as I’m still trying to work out the basics of this.

There is a line in the code in the Roi manager where your selecting only the first roi

Hi all,
sorry for reviving such an old topic, but I am exactly at this position now, and it seems there was no answer to the last wustlmed’s statement.
Indeed the result of the code is only the last GLCM analysis from the last roi object. While, i can see that during the analysis in the “results” all the individual objects are being analyzed, but ultimately its so fast that one can not store/use them, but the last one.)
How can I make so that it save the results for each individual roi object separately?
Thank you!!