How to use ImageJ to quantify fluorescent distribution?

Source: Knol (Liang Cai, postdoctoral fellow, San Francisco, CA)

Introduction

The following section describes the edge detection method to quantify protein localization based on fluorescent images. It is based on a custom built ImageJ macro, with a step-by-step work flow. Good luck!

 

Prepare files for the analysis

The file EdgeRatio.txt is the ImageJ macro written for this specific purpose, which is attached at the end of this page. This macro can also be download from my homepage - code section.

Before using the macro, one value in EdgeRatio.txt need to be adjusted. Looking into the file, and change the 787 to an appropriate value. With the demo-RGB-file.tif capture condition, 787 pixal equals to 50 micron.
// 787 pix == 50 um
xValues = ((i – realpair) * steppix) * 50 / 787;

Here is an example image demo-RGB-file.tif. (It was in the tif format. Due to the size limit, I uploaded it as png format. Please convert it back to RGB tif file in ImageJ.)

demo-rgb-file

Edge detection process

Open any file in RGB format in ImageJ, and run the macro EdgeRatio.txt by Plugins->Macros->Run…
step1
As shown above, a window pops up. Step pixal is the step the mask dilating or shrinking in each measurement. Total pixal distance is how far inside the cell will be measured. With the demo-RGB-file.tif, input 36 pixal will measure about 2.29 micron inside the cell.
OK to proceed.
step2
As shown above, ImageJ will open many windows automatically. So, this macro cannot be run in batch mode. The polygon selections tool is enabled. Outline the area of interested. Make sure enough space is left inside and outside of the cell. The yellow line show the ROI for lamellipodial measure, which covers the major protrusion on the right and avoid the ruffle in the middle. Convert the selection to mask by Edit->Selection->Create Mask.
step3
The wand tool is selected now. Using Image->Adjust->Threshold to set the image as  a binary image. Use the wand tool to select the outline of the cell, as shown below.

To archive a good outline for the cell edge, which is the criticle step in the whole process, adjusting thevalues in the Threshold windows helps. Only the region within the ROI needs to be preciese. It is OK to use the Paintbrush tool to smooth the regions outside the ROI to help the selection. Using the wand tool NOT thefreehand tool to generate the outline minimizes the bias. 

step4
As shown above, from this point, the macro starts running by itself, and many windows are open and close. DO NOT INTERRUPT! NO MOUSE MOVING OR KEYBOARD CLICK. The progression bar in ImageJ shows the status of each dilating/shrinking operation, which takes most of the calculation time.
step5
After a while, all the images are close and only the Results window left in ImageJ. This result table is stored as CVS format with a name end with .xls, which means it can be opened with Excel etc. No more operation is need in ImageJ. The content of Results window will be flushed when the macro starts running.

Check the result file

step6

In the xls file, RGB/rgb means the red, green and blue. 0/1/2 = r/g/b. Distance is the real distance in micron, with “-” means inside the cell. Intensity is the raw value of the channel, which is averaged over the edge within ROI. SemOfInt is the standard error of the mean of the raw value, which is calculated from the thousands point of the edge. PercInt is the percentage value of the intensity, with the maximal raw value as 1 and the minimal raw value as 0. The PercInt is the most consistent value between different cells. Group differnt cells and a new SEM can be calculated to show the varience between cells. B2g-Ratio is (raw value of blue channel) / (raw value of red channel), etc. Exact same microscopy setting is required for the ratio and raw value meanningful between different cells.

ImageJ macro for the analysis

save the following section as the EdgeRatio.txt file, which is the ImageJ macro for the analysis described above.

———————-
// Liang Cai created for barbed end assay 
// For RGB tif file 
//
// adjust 787 with your microscopy setting
// 
// measure R G B channel presented by 0 1 2 
// ratio Blue to Green, presented by 4 
// ratio Blue to Red, presented by 5 
// ratio Green to Red, presented by 6 
// 
// 2008-1-27, used for 100x epi GA GW raw value,  
// 
// 2007-08-19 add two more ratios 
// 
// 2006-11-16 new scale for 60x OCAR confocal 638==50 
// 
// cail9970@gmail.com 
// 2007.3.12 
// 
// Illustrated by “Expand/Shrink Selection” 
// Michael Schmid, version 05-Nov-2004 
 
macro “MeasureEdge-RGB” { 
    requires(“1.34m”); 
    run(“Clear Results”); 
   
// inputs for the macro 
    steppix = 2; // expand or shrink per pix during the measure 
    distance = 36; // total +/- distance from the edge, in pix 
 
    Dialog.create(“How to measure the edge”); 
    Dialog.addMessage(“To measure the edge of a cell:”); 
    Dialog.addMessage(” 1. select the region you want to analyze and create a mask”); 
    Dialog.addMessage(” 2. use threshold and wand tool to outline the cell and create another mask”); 
    Dialog.addMessage(” 3. use the excel to graph the result”); 
     
    Dialog.addNumber(“Step Pixal per Measure:”, steppix); 
    Dialog.addNumber(“Total Pixal Distance:”, distance); 
    Dialog.show(); 
    steppix = Dialog.getNumber(); 
    distance = Dialog.getNumber(); 
 
    if ((distance % steppix) > 0) { 
        exit(“Remainder must be 0!”); 
    } 
 
// initiate array 
    realpair = distance / steppix; 
    counts = realpair * 2 + 1; 
// realpair + 1 + 4 + one more 
    RealCount = minOf((realpair + 7),counts); 
 
    title = getTitle(); 
    RGB = newArray(“red”, “green”, “blue”); 
    yMin = newArray(255,255,255); 
    yMax = newArray(0,0,0); 
 
// creat data from shrinked/expanded mask, smaller to bigger, do 3 times for RGB 
// run(“Create Mask”); use other way to get Mask!! 
 
    selectWindow(title); 
    run(“RGB Split”); 
    rename(“blue”); 
    wait(140); 
    run(“Put Behind [tab]“); 
    rename(“green”); 
    wait(140); 
    run(“Put Behind [tab]“); 
    rename(“red”); 
    wait(140); 
    run(“Put Behind [tab]“);     
 
    run(“RGB Merge…”, “red=red green=green blue=blue keep”); 
    run(“Enhance Contrast”, “saturated=0.5″); 
 
setTool(2); 
 
    stepone = 0; 
    while (isOpen(“Mask”)!=true && stepone == 0) { 
        wait(1000); 
        showStatus(“Please Make Mask for ROI First”); 
    } 
    selectWindow(“Mask”); 
    rename(“ROI-red”); 
    run(“Duplicate…”, “title=ROI-green”); 
    run(“Duplicate…”, “title=ROI-blue”); 
    stepone = 1; 
 
    selectWindow(“RGB”); 
    run(“8-bit”); 
    run(“Enhance Contrast”, “saturated=0.5 normalize”); 
 
setTool(8); 
 
    while (isOpen(“Mask”)!=true && stepone == 1) { 
        wait(1000); 
        showStatus(“Please Make Mask First”); 
    } 
 
    selectWindow(“RGB”); 
    close(); 
 
 
    i = 0; 
    while (i < RealCount) { 
        selectWindow(“Mask”); 
        run(“Duplicate…”, “title=MaskRun”); 
        if ((i – realpair) > 0) { 
            selectWindow(“MaskRun”); 
            run(“Maximum…”, “radius=”+((i – realpair) * steppix)); 
            selectWindow(“MaskRun”); 
            run(“Outline”); 
        } 
        else if ((i – realpair) == 0) { 
            selectWindow(“MaskRun”); 
            run(“Outline”); 
        } 
        else { 
            selectWindow(“MaskRun”); 
            run(“Minimum…”, “radius=”+((realpair – i) * steppix)); 
            selectWindow(“MaskRun”); 
            run(“Outline”); 
        } 
 
        selectWindow(“MaskRun”); 
        rename(“MaskRun-red”); 
        run(“Duplicate…”, “title=MaskRun-green”); 
        run(“Duplicate…”, “title=MaskRun-blue”); 
     
        for(rgbcycle=0; rgbcycle<3; rgbcycle++) { 
            run(“Image Calculator…”, “image1=MaskRun-”+RGB[rgbcycle]+” operation=AND image2=”+RGB[rgbcycle]); 
            run(“Image Calculator…”, “image1=MaskRun-”+RGB[rgbcycle]+” operation=AND image2=ROI-”+RGB[rgbcycle]); 
            setThreshold(1, 255); 
            run(“Set Measurements…”, “area standard mean limit redirect=None decimal=2″); 
            selectWindow(“MaskRun-”+RGB[rgbcycle]); 
            run(“Measure”); 
 
            callSD = getResult(“StdDev”, (nResults – 1)); 
            callN = getResult(“Area”, (nResults – 1)); 
            SEM = callSD / sqrt(callN); 
 
            // 787 pix == 50 um 
            xValues = ((i – realpair) * steppix) * 50 / 787; 
            yValues = getResult(“Mean”, (nResults – 1)); 
 
            yMin[rgbcycle] = minOf(yMin[rgbcycle], yValues); 
            yMax[rgbcycle] = maxOf(yMax[rgbcycle], yValues); 
 
            setResult(“RGB-channel”, (nResults – 1), rgbcycle); 
            setResult(“Distance”, (nResults – 1), xValues); 
            setResult(“Intensity”, (nResults – 1), yValues); 
            setResult(“SemOfInt”, (nResults – 1), SEM); 
 
            close(); 
        } 
 
        i ++; 
        updateResults(); 
    } 
 
    selectWindow(“Mask”); 
    close(); 
    selectWindow(“ROI-red”); 
    close(); 
    selectWindow(“ROI-green”); 
    close(); 
    selectWindow(“ROI-blue”); 
    close(); 
 
    run(“RGB Merge…”, “red=red green=green blue=blue”); 
 
// ratio Blue to Green, presented by 4 
// ratio Blue to Red, presented by 5 
// ratio Green to Red, presented by 6 
 
    i = 0; 
    while (i < RealCount) { 
        for(j=0; j<3; j++) { 
            setResult(“PercInt”, (i*3+j), ((getResult(“Mean”, (i*3+j)) – yMin[j]) / (yMax[j] – yMin[j])) ); 
            setResult(“PercSEM”, (i*3+j), (getResult(“SemOfInt”, (i*3+j)) / (yMax[j] – yMin[j])) ); 
            setResult(“b2g-Ratio”, (i*3+j), (getResult(“Mean”, (i*3 + 2)) / getResult(“Mean”, (i*3 + 1))) ); 
            setResult(“b2r-Ratio”, (i*3+j), (getResult(“Mean”, (i*3 + 2)) / getResult(“Mean”, (i*3))) ); 
            setResult(“g2r-Ratio”, (i*3+j), (getResult(“Mean”, (i*3 + 1)) / getResult(“Mean”, (i*3))) ); 
        } 
        i ++; 
    } 
    updateResults(); 
 
    selectWindow(“Results”); 
    saveAs(“Measurements”, getDirectory(“current”)+”RatioE-”+ substring(title, 3, (lengthOf(title)-4)) +”.xls”); 
 
    wait(1000); 
    close(); 
}