Macro to measure particles and save ROI on to original image

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Macro to measure particles and save ROI on to original image

eloiselockyer
I am trying to write an imageJ macro that will

1) Open and split an image into two channels
2) Perform particle analysis on each image and save measurements
3) Save the original image with the particle outlines overlayed

So far I have realised I need to first duplicate the original image so that the ROI can later be saved on top of this. However I at the moment I can't figure out how to rename this duplicated image so I can later select it for flattening:

dir=getDirectory("Choose a Directory");
print(dir);
greenDir=dir + "/Green/";
blueDir=dir + "/Blue/";
print(greenDir);
print(blueDir);
File.makeDirectory(greenDir);
File.makeDirectory(blueDir);
list = getFileList(dir);

for (i=0; i<list.length; i++) {
     if (endsWith(list[i], ".tif")){
               print(i + ": " + dir+list[i]);
             open(dir+list[i]);
             imgName=getTitle();
         baseNameEnd=indexOf(imgName, ".tif");
         baseName=substring(imgName, 0, baseNameEnd);

         run("Split Channels");

         selectWindow("C1-" + imgName);  
     run("Duplicate...", "title= imgName + "original");
     selectWindow("C1-" + imgName);
     setAutoThreshold("Default dark");
     //run("Threshold...");
     //setThreshold(1, 255);
     run("Convert to Mask");
     run("Analyze Particles...", "size=60-Infinity pixel show=Outlines display exclude   summarize   add");
     selectWindow(imgName + "original");
     roiManager("Show All without labels");
     run("Flatten");
     saveAs("Tiff", greenDir + baseName + "green.tif");
         close();

I know the error is in the run("Duplicate...", "title= imgName + "original"); line, but I don't know what's wrong with the code!

Reply | Threaded
Open this post in threaded view
|

Re: Macro to measure particles and save ROI on to original image

gnelson
Hi Eloiselockyer,

I think if you write

run("Duplicate...", "title=list[i]+_original");

it should work.  No spaces, and you can use the list of the directory images as you loop through them.  

Also, you can make it easier to navigate between images if you don't split the original image nad choose the channel to duplicate.  The example code below does a similar thing and works, but more simply (please excuse my crude coding!).  Rather than split the channels, it opens a multicahnnel image, and duplicates each channel one at a time (with the duplicate channels option).  It then thresholds the duplicate then counts particles (you can see I've commented out different thresholding methods to play around with the best one).  Found particles are then added to the ROI manager and the thresholded image renamed.  


//Assumes the image is a MIP'ed tif with PML in channel1, H2AX in channel2
//(although these can be the other way round and it doesn't matter too much except for labelling in results)
//and DAPI in channel3.  It looks for pure overlap and counts respective spots.
//All results get stored in a concatenating results file.
//Plus the mask images are stored (all 3 original images converted to masks plus the coloc maskin the 4th channel)
// so you can see what it did.

var tolerance = 30;
run("Set Measurements...", "area integrated limit display redirect=None decimal=3");

dir1 = getDirectory("Choose folder with tif files ");
list = getFileList(dir1);

setBatchMode(true);

// create folders for the tifs
        dir1parent = File.getParent(dir1);
        dir1name = File.getName(dir1);
        dir2 = dir1parent+File.separator+dir1name+"_masks";
        if (File.exists(dir2)==false) {
                                File.makeDirectory(dir2); // new directory for mask images
                }

for (i=0; i<list.length; i++) {
        showProgress(i+1, list.length);
        print("processing ... "+i+1+"/"+list.length+"\n         "+list[i]);
        filename = dir1 + list[i];
        if (endsWith(filename, "tif")) {
                path=dir1+list[i];
                run("Bio-Formats Importer", "open="+filename+" autoscale color_mode=Default view=Hyperstack stack_order=XYCZT");
                originalImage = getTitle();
                roiManager("Reset");
                selectWindow(originalImage);
                run("Duplicate...", "duplicate channels=1"); //Change this to the DAPI channel slice*******
// run("8-bit");
                setAutoThreshold("Moments dark");
                run("Threshold");
                run("Watershed");
// run("Entropy Threshold");
                run("Analyze Particles...", "size=120-2500 circularity=0.04-1.00 exclude add");
                rename("nuc");
//nuclei now added to ROI manager

//next find pml bodies
                selectWindow(originalImage);
                run("Duplicate...", "title=PML duplicate channels=3");
// run("8-bit");
                setAutoThreshold("Triangle dark");
                run("Threshold");
// rename("PML");

//next find h2ax foci
                selectWindow(originalImage);
                run("Duplicate...", "title=h2ax duplicate channels=2");
                wait(1000);
// run("8-bit");
                setAutoThreshold("MaxEntropy dark");
                run("Threshold");
// rename("h2ax");

//Next find colocalised PML-H2AX foci pixels
                imageCalculator("Multiply create", "h2ax","PML");
                selectWindow("Result of h2ax");
                rename(originalImage+":coloc");
                run("Grays");
                for(j=0; j<roiManager("count"); j++) {
                        roiManager("select", j);
                        run("Find Maxima...", "noise="+tolerance+" output=[Count]");
// run("Find Maxima...", "noise="+tolerance+" output=[Point Selection]");
                        run("Add Selection...");
                        }
// saveAs("Results", dir2+File.separator+originalImage+"_nuc_coloc.xls");

//next find H2AX foci per nuc
                selectWindow("h2ax");
                rename(originalImage+":h2ax");
                for(j=0; j<roiManager("count"); j++) {
                        roiManager("select", j);
                        run("Find Maxima...", "noise="+tolerance+" output=[Count]");
// run("Find Maxima...", "noise="+tolerance+" output=[Point Selection]");
                        run("Add Selection...");
                        }
                saveAs("Results", dir2+File.separator+originalImage+"_nuc_coloc_and_h2ax.xls"); //This is savign as it goes along in case it crashes
                selectWindow(originalImage+"h2ax");
                rename("h2ax");
                selectWindow(originalImage+"coloc");
                rename("coloc");
                selectWindow(originalImage);
                close();

                run("Merge Channels...", "c1=PML c2=h2ax c3=nuc c4=coloc create");
                rename("masks");

                saveAs("TIFF", dir2+File.separator+originalImage+"_colocmasks.tif");


        close();
        }
setBatchMode(false);
}

showMessage(" Well, I think we gave them a damn good thrashing there, what what??");

// macro
Reply | Threaded
Open this post in threaded view
|

Re: Macro to measure particles and save ROI on to original image

eloiselockyer
Thank you for your help, I ended up modifying my code last night to get it to work and this is what I have now:

dir=getDirectory("Choose a Directory");
print(dir);
greenDir=dir + "/Green/";
blueDir=dir + "/Blue/";
print(greenDir);
print(blueDir);
File.makeDirectory(greenDir);
File.makeDirectory(blueDir);
list = getFileList(dir);

for (i=0; i<list.length; i++) {
     if (endsWith(list[i], ".tif")){
               print(i + ": " + dir+list[i]);
             open(dir+list[i]);
             imgName=getTitle();
         baseNameEnd=indexOf(imgName, ".tif");
         baseName=substring(imgName, 0, baseNameEnd);

         run("Split Channels");
         roiManager("Reset");

         selectWindow("C1-" + imgName);  
         run("Duplicate...", "title=");
         saveAs("Tiff", greenDir + "originalgreen" + baseName);
         selectWindow("C1-" + imgName);
         setAutoThreshold("Default dark");
         //run("Threshold...");
         //setThreshold(1, 255);
         setOption("BlackBackground", false);
         run("Convert to Mask");
         run("Analyze Particles...", "size=60-Infinity pixel show=Outlines display exclude summarize add");
         selectWindow("originalgreen" + imgName);
         roiManager("Show All with labels");
         run("Flatten");
         saveAs("Tiff", greenDir + baseName + "overlaygreen.tif");
         close();
     }
}

for (i=0; i<list.length; i++) {
     if (endsWith(list[i], ".tif")){
               print(i + ": " + dir+list[i]);
             open(dir+list[i]);
             imgName=getTitle();
         baseNameEnd=indexOf(imgName, ".tif");
         baseName=substring(imgName, 0, baseNameEnd);

         run("Split Channels");
         roiManager("Reset");


         selectWindow("C2-" + imgName);
         run("Duplicate...", "title=");
         saveAs("Tiff", blueDir + "originalblue" + baseName);
         selectWindow("C2-" + imgName);
         //run("Threshold...");
         //setThreshold(23, 255);
         setOption("BlackBackground", false);
         run("Convert to Mask");
         run("Analyze Particles...", "size=60-Infinity pixel show=Outlines display exclude summarize add");
         selectWindow("originalblue" + imgName);
         roiManager("Show All with labels");
         run("Flatten");
         saveAs("Tiff", blueDir + baseName + "overlayblue.tif");
         run("Close All");
     }
}
Reply | Threaded
Open this post in threaded view
|

Re: Macro to measure particles and save ROI on to original image

Christine Labno-2
In reply to this post by eloiselockyer
Hi Eloise,

"I think if you write run("Duplicate...", "title=list[i]+_original"); it should work.  No spaces, and you can use the list of the directory images as you loop through them."  

Unfortunately this suggestion leads to an image named list[i]+_original and the macro breaks down just like in the original version.  Likewise run("Duplicate...", "title=imgName + 'original '"); doesn't work.  Adding text strings to variables after the Duplicate command is tricky, it doesn't work like adding text strings to variables in other commands (like selectWindow(imgName + "_original"); works, for example).  

The absolute easiest way to rename an image duplicate with the name you want is to add

rename(imgName + "original");  

on the line immediately after the Duplicate command, like this:

 run("Duplicate...", "title=");  <-- doesn't matter what title= because it will be replaced right away
   rename(imgName + "original");

That will get you what you want and keep your code intact.  

Also, if I may suggest, your strategy to strip off ".tiff" from your image name to get to the baseName variable also doesn't work as written.    

Replace this: baseNameEnd=indexOf(imgName, ".tif");
 
with this: baseNameEnd=lastIndexOf(imgName, ".");

and you should be good to go.  

Finally, because I know someone else will suggest this, you could work with image IDs instead of image names.  Every image or copy of an image has a unique ID, even if they have the same names.  Something like original=getImageID(); then duplicate, then copy=getImageID(); and then later selectImage(original);  or selectImage(copy);

Best,
Christine

--------------------------------------------
Christine Labno, Ph.D.
Asst. Technical Director
Light Microscopy Core
University of Chicago
Office of Shared Research Facilities
KCBD 1250 900 E. 57th St.
(773) 834-9040 (phone)

________________________________________
From: ImageJ Interest Group [[hidden email]] on behalf of eloiselockyer [[hidden email]]
Sent: Thursday, May 18, 2017 6:07 AM
To: [hidden email]
Subject: Macro to measure particles and save ROI on to original image

I am trying to write an imageJ macro that will

1) Open and split an image into two channels
2) Perform particle analysis on each image and save measurements
3) Save the original image with the particle outlines overlayed

So far I have realised I need to first duplicate the original image so that
the ROI can later be saved on top of this. However I at the moment I can't
figure out how to rename this duplicated image so I can later select it for
flattening:

dir=getDirectory("Choose a Directory");
print(dir);
greenDir=dir + "/Green/";
blueDir=dir + "/Blue/";
print(greenDir);
print(blueDir);
File.makeDirectory(greenDir);
File.makeDirectory(blueDir);
list = getFileList(dir);

for (i=0; i<list.length; i++) {
     if (endsWith(list[i], ".tif")){
               print(i + ": " + dir+list[i]);
             open(dir+list[i]);
             imgName=getTitle();
         baseNameEnd=indexOf(imgName, ".tif");
         baseName=substring(imgName, 0, baseNameEnd);

         run("Split Channels");

         selectWindow("C1-" + imgName);
     run("Duplicate...", "title= imgName + "original");
     selectWindow("C1-" + imgName);
     setAutoThreshold("Default dark");
     //run("Threshold...");
     //setThreshold(1, 255);
     run("Convert to Mask");
     run("Analyze Particles...", "size=60-Infinity pixel show=Outlines
display exclude   summarize   add");
     selectWindow(imgName + "original");
     roiManager("Show All without labels");
     run("Flatten");
     saveAs("Tiff", greenDir + baseName + "green.tif");
         close();

I know the error is in the run("Duplicate...", "title= imgName +
"original"); line, but I don't know what's wrong with the code!





--
View this message in context: http://imagej.1557.x6.nabble.com/Macro-to-measure-particles-and-save-ROI-on-to-original-image-tp5018747.html
Sent from the ImageJ mailing list archive at Nabble.com.

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Feature Request: FFT of image stack

John Oreopoulos
Hello,

I'd like to make the following ImageJ feature request: Would it be  
possible to modify the FFT command to prompt the user and ask if it  
wants to apply the FFT function to each frame in a stack (as opposed  
to just applying the FFT to the active frame of a stack)? I have a  
series of time-lapse imaging data where I'd like to analyze the FFT of  
each frame in the stack and do some filtering there, and subsequently  
inverse FFT the stack back to the image domain. Hoping Wayne can work  
his magic!

Sincerely,

John Oreopoulos

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Feature Request: FFT of image stack

Jerome Mutterer-3
Hi John,
The Process > FFT > Bandpass Filter... and Custom Filter... can process
Stacks.
If you want a different filter for each frame in the stack, you currently
cannot have a stack of FFT images, but you can do this a set of two macros:
A first macro loops the original slices, performs the FFT transform, and
copies the spectrum images in a new stack. You could then edit this stack.
For invert transform, a second macro loops through the original slices
again, retransform each slice, replace the FFT image with the edited
version, inverse transform, and copy this result to a results stack.

https://gist.github.com/mutterer/66f4b2385cef14ef1d088ad7d9070e94
https://gist.github.com/mutterer/9735d0beb1bc31f56de8ecc6e8d35995

The results are best viewed after synchronizing windows with
Analyze>Tools>Synchronize Windows.

Sincerely,

Jerome.


2017-05-19 23:49 GMT+02:00 John Oreopoulos <[hidden email]>:

> Hello,
>
> I'd like to make the following ImageJ feature request: Would it be
> possible to modify the FFT command to prompt the user and ask if it wants
> to apply the FFT function to each frame in a stack (as opposed to just
> applying the FFT to the active frame of a stack)? I have a series of
> time-lapse imaging data where I'd like to analyze the FFT of each frame in
> the stack and do some filtering there, and subsequently inverse FFT the
> stack back to the image domain. Hoping Wayne can work his magic!
>
> Sincerely,
>
> John Oreopoulos
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>



--
Jerome Mutterer
CNRS - Institut de biologie moléculaire des plantes
12, rue du Général Zimmer
67084 Strasbourg Cedex
www.ibmp.cnrs.fr

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Feature Request: FFT of image stack

Wayne Rasband-2
In reply to this post by John Oreopoulos
> On May 19, 2017, at 5:49 PM, John Oreopoulos <[hidden email]> wrote:
>
> Hello,
>
> I'd like to make the following ImageJ feature request: Would it be possible to modify the FFT command to prompt the user and ask if it wants to apply the FFT function to each frame in a stack (as opposed to just applying the FFT to the active frame of a stack)? I have a series of time-lapse imaging data where I'd like to analyze the FFT of each frame in the stack and do some filtering there, and subsequently inverse FFT the stack back to the image domain. Hoping Wayne can work his magic!

Upgrade to the latest daily build (1.51o20) and you can use simple macros to do FFTs and Inverse FFTs on the images in a stack. I included two macros. The first runs the “FFT” command on the images in the T1 Head sample stack, saving the output in a virtual stack. The second runs the “Inverse FFT” command on the virtual stack. You will need to modify the second line of the first macro so that ‘dir’ points to an empty folder.

-wayne

  macro "Stack FFT" {
     requires("1.51o");
     dir = "/Users/wayne/Downloads/FFT_Stack/";
     setBatchMode(true);
     run("T1 Head (2.4M, 16-bits)");
     for (i=1; i<=nSlices; i++) {
        setSlice(i);
        run("FFT");
        saveAs("TIFF", dir+"FFT of "+IJ.pad(i,4));
        close;
     }
     run("Image Sequence...", "open=&dir sort use");
     setBatchMode(false);
  }

 macro "Stack Inverse FFT" {
     stack = getImageID;
     setBatchMode(true);
     setSlice(2);
     n = nSlices;
     for (i=1; i<=n; i++) {
        selectImage(stack);
        setSlice(i);
        run("Inverse FFT");
      }
     run("Images to Stack", "title=[Inverse FFT] use");
     setBatchMode(false);
  }

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Feature Request: FFT of image stack

John Oreopoulos
Much thanks as usual!

John Oreopoulos

On May 22, 2017, at 10:45 PM, Wayne Rasband <[hidden email]> wrote:

>> On May 19, 2017, at 5:49 PM, John Oreopoulos <[hidden email]> wrote:
>>
>> Hello,
>>
>> I'd like to make the following ImageJ feature request: Would it be possible to modify the FFT command to prompt the user and ask if it wants to apply the FFT function to each frame in a stack (as opposed to just applying the FFT to the active frame of a stack)? I have a series of time-lapse imaging data where I'd like to analyze the FFT of each frame in the stack and do some filtering there, and subsequently inverse FFT the stack back to the image domain. Hoping Wayne can work his magic!
>
> Upgrade to the latest daily build (1.51o20) and you can use simple macros to do FFTs and Inverse FFTs on the images in a stack. I included two macros. The first runs the “FFT” command on the images in the T1 Head sample stack, saving the output in a virtual stack. The second runs the “Inverse FFT” command on the virtual stack. You will need to modify the second line of the first macro so that ‘dir’ points to an empty folder.
>
> -wayne
>
>  macro "Stack FFT" {
>     requires("1.51o");
>     dir = "/Users/wayne/Downloads/FFT_Stack/";
>     setBatchMode(true);
>     run("T1 Head (2.4M, 16-bits)");
>     for (i=1; i<=nSlices; i++) {
>        setSlice(i);
>        run("FFT");
>        saveAs("TIFF", dir+"FFT of "+IJ.pad(i,4));
>        close;
>     }
>     run("Image Sequence...", "open=&dir sort use");
>     setBatchMode(false);
>  }
>
> macro "Stack Inverse FFT" {
>     stack = getImageID;
>     setBatchMode(true);
>     setSlice(2);
>     n = nSlices;
>     for (i=1; i<=n; i++) {
>        selectImage(stack);
>        setSlice(i);
>        run("Inverse FFT");
>      }
>     run("Images to Stack", "title=[Inverse FFT] use");
>     setBatchMode(false);
>  }
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html