// This makes the pop up at the beginning with instructions
// Unordered lists, headers, and text modifiers
showMessage("1/1", "" + "
General Instructions
" + "Install featureJ derivatives:
" + "- For ImageJ (http://www.imagescience.org/meijering/software/featurej/)" + "
- For FIJI: >HELP >UPDATE >Manage update sitesCHECK ImageScience(http://sites.imagej.net/ImageScience/) >CLOSE and >APPLY CHANGES" + "
Image Folder:
" + "- Image names can only be numbers (e.g. 1.tif) and not start with Zero (e.g. 01.tif is not allowed)" + "
- Image folder must ONLY contain images to be analysed" + "
- Images must be (RGB) and can be of diverse dimensions or formats"+"
- Image Folder located on a shared drive can lead to errors"+"
"+""+""+"General Comments:
" + "" + "- Only runs on Windows and not on MAC (but can be run in virtual Windows on MAC)" + "
- When run in virtual windows on a Mac, the processing power should be reduced to avoid glitches during the detection parameter setting step. The analysis itself can be run in full power mode."+"
- Once the analysis is in autorun mode, do not interfere with ImageJ or ideally do not touch the computer until you see the 'Analysis complete' message."+"
");
// All of the images are sorted within these following loops
//For automatically defining the ROI, we have two variable that can be easily changed to any number user wants, which are enlarge size and reduce size of the ROI
enlargeROI = 60;
reduceROI = -90;
run("Set Measurements...", "area mean integrated redirect=None decimal=5");
/*Dialog.create("Selection of Type of Study");
Dialog.addChoice("Type of Study",newArray("Study with the Whole Image","Study with the Graph","Study by Drawing your own Graph","Study with Two Tubules Channels"));
Dialog.show();*/
//ImageSort section
//----------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------
//Arrays made for later use.
stringy = getDirectory("Choose a Directory");
FileList = getFileList(stringy);
FutureList = getFileList(stringy);
tempArray = getFileList(stringy);
StringyList = getFileList(stringy);
q = FileList.length;
//loop that turns letters to numbers
for (k1 = 0; k1 < q; k1++) {
a = split(FileList[k1], ".");
FutureList[k1] = parseInt(a[0]);
tempArray[k1] = a[1];
}
//loop that sorts array
for (i = 0; i < q; i++) {
for (j = i + 1; j < q; j++) {
if (FutureList[i] > FutureList[j]) {
temp = FutureList[i];
FutureList[i] = FutureList[j];
FutureList[j] = temp;
}
}
}
//loop that turns numbers back to letters
for (p = 0; p < q; p++) {
number = d2s(FutureList[p], 0);
StringyList[p] = number + "." + tempArray[p];
}
tubuleaverage = newArray(q); //stores image Mean pixel inten
tubulesortaverage = newArray(q); //to be sorted
j = 1; //counter variable for result sorting to be done at the end
setBackgroundColor(0, 255, 255);
setForegroundColor(253, 253, 253);
//----------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------
//========================
//=========================
//USER INPUT
//obtain color of tubules
tubulecolor = getString("enter the color of your tubules(r,b,g): //", "r");
//===========================
//============================
//loop opens images and tracks down their individual statistics
//===========================================================
//this loop is for tubule intensities
for (i = 0; i < q; i++) {
setBackgroundColor(0, 255, 255);
setForegroundColor(253, 253, 253);
open(stringy + StringyList[i]);
wait(25);
run("Set Scale...", "distance=0 known=0 pixel=1 unit=pixel");
rename("image2");
selectWindow("image2");
run("Split Channels");
if (tubulecolor == "r") {
close();
close();
}
if (tubulecolor == "g") {
close();
close("\\Others");
}
if (tubulecolor == "b") {
close("\\Others");
}
getRawStatistics(nPixels, Mean, min, max, std, histogram);
tubuleaverage[i] = Mean;
tubulesortaverage[i] = Mean;
close();
}
//values are then searched for the max.
highestvalue = tubulesortaverage[q - 1];
mediantubulevalue = tubulesortaverage[floor(q / 2)];
print("Highest value of tubules " + highestvalue);
print("Median value of tubules " + mediantubulevalue);
Myhighindex = 0;
//this loop finds the index of the highest value for tubules
//and the index for the median value for the tubules
for (i = 0; i < q; i++) {
if (tubuleaverage[i] == highestvalue) {
Myhighindex = i;
}
if (tubuleaverage[i] == mediantubulevalue) {
MyMedTubuleIndex = i;
}
}
absolutehigh = Myhighindex;
//prints values just to check in the log
Array.print(StringyList);
Dialog.create("Select method of identifying reference image for defining tubule detection parameters");
Dialog.addCheckbox(" Highest tubule channel signal intensity (default) ",true);
Dialog.addCheckbox(" Medium tubule channel signal intensity",false);
Dialog.show();
highindex = Dialog.getCheckbox();
medindex = Dialog.getCheckbox();
if (medindex) Myhighindex = MyMedTubuleIndex;
//purpose: Obtain Tubule sensitivity value
//--------------------------
//---------------------------
//we open the medium tubule image.
open(stringy + StringyList[Myhighindex]);
wait(25);
run("Set Scale...", "distance=0 known=0 pixel=1 unit=pixel");
rename("image2");
selectWindow("image2");
run("Split Channels");
if (tubulecolor == "r") {
close();
close();
}
if (tubulecolor == "g") {
close();
close("\\Others");
}
if (tubulecolor == "b") {
close("\\Others");
}
rename("image2");
selectWindow("image2");
wait(25);
run("Duplicate...", "title=GFP");
wait(25);
selectWindow("GFP");
wait(25);
run("Duplicate...", "title=GFP2");
wait(25);
selectWindow("GFP");
close();
selectWindow("GFP2");
run("Duplicate...", "title=GFP3");
wait(25);
selectWindow("GFP3");
getRawStatistics(nPixels, Mean, min, max, std, histogram);
run("Close");
wait(25);
selectWindow("GFP2");
//user selected area in order to input tubule detection parameters.
makeRectangle(0, 0, 400, 400);
waitForUser("Please place this box over an area with representative tubules intensities you want to detect, you can change its size if you wish, Click OK when done.");
run("Duplicate...", "title=faintTubules");
close("\\Others");
roiManager("reset");
//---------------------------------------------------------------
//--------------------------------------------------------------
//user input repeating while loop to find THRESHY!
//--------------------------------------------------------------
//initial tubule parameters
Threshy = 5;
MinTubuleLength = 1;
Continue = false; //while loop condition
while (Continue == false) {
//----------------------------------------------------------
//this is to destroy all of the holes, holes are thresholded and created into an ROI
//----------------------------------------------------------
//----------------------------------------------------------
wait(25);
run("Duplicate...", "title=HoleKiller");
wait(25);
getRawStatistics(nPixels, Mean, min, max, std, histogram);
getDimensions(width, height, channels, slices, frames);
run("Threshold...");
setAutoThreshold("Default dark");
setThreshold(0, 1.25 * Mean);
setOption("BlackBackground", false);
run("Convert to Mask");
run("Create Selection");
if (selectionType() != -1) {
roiManager("Add"); //roi of holes
BoxHoles = roiManager("count") - 1;
} else {
BoxHoles = -1;
}
selectWindow("HoleKiller");
close();
//-----------------------------------------------------
//-------------------------------------------------------
smooth = 0.4;
//calculates derivitive in x direction
run("FeatureJ Derivatives", "x-order=1 y-order=0 z-order=0 smoothing=smooth");
rename("GradientX");
wait(25);
//Zero's out the holes area
//Because we are dealing with a 32 bit image, its kind of difficult
// to simply set a pixel to a value. As a result, I guess a value
// and check to see what value it corresponds to on the derivitive image
//I then loop until that value converges to a small number, and use this
//value to essentially zero the holes.
if (BoxHoles > -1) {
roiManager("Select", BoxHoles);
getRawStatistics(nPixels, Mean, min, max, std, histogram);
getDimensions(width, height, channels, slices, frames);
xx = 128;
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
makeRectangle(0, 0, 1, 1);
run("Fill", "slice");
while (abs(getPixel(0, 0)) > 0.5) {
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
makeRectangle(0, 0, 1, 1);
run("Fill", "slice");
if (getPixel(0, 0) > 0) {
xx = xx - 1;
} else {
xx = xx + 1;
}
counter = counter + 1;
}
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
roiManager("Select", BoxHoles);
wait(25);
run("Fill", "slice");
}
//Here, the gradient image is inverted using nested for loops.
//This is done to make thresholding easier later on.
getDimensions(width, height, channels, slices, frames);
for (ii = 0; ii < width; ii++) {
for (jj = 0; jj < height; jj++) {
currentvalue = getPixel(ii, jj);
setPixel(ii, jj, 1 / currentvalue);
}
}
wait(25);
//This is the thresholding step
getRawStatistics(nPixels, Mean, min, max, std, histogram);
run("Threshold...");
setAutoThreshold("Default dark");
setThreshold(-1 / Threshy, 1 / Threshy);
wait(50);
run("Convert to Mask");
wait(50);
run("Make Binary");
wait(50);
run("Create Selection");
if (selectionType() != -1) {
roiManager("Add"); //roi[0]Tubules in X
BoxTubulesInX = roiManager("count") - 1;
} else {
BoxTubulesInX = -1;
}
selectWindow("GradientX");
close();
//The process is repeated for the y-direction.
run("FeatureJ Derivatives", "x-order=0 y-order=1 z-order=0 smoothing=smooth");
wait(25);
rename("GradientY");
wait(25);
if (BoxHoles > -1) {
roiManager("Select", BoxHoles);
getRawStatistics(nPixels, Mean, min, max, std, histogram);
getDimensions(width, height, channels, slices, frames);
xx = 128;
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
makeRectangle(0, 0, 1, 1);
run("Fill", "slice");
while (abs(getPixel(0, 0)) > 0.5) {
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
makeRectangle(0, 0, 1, 1);
run("Fill", "slice");
if (getPixel(0, 0) > 0) {
xx = xx - 1;
} else {
xx = xx + 1;
}
counter = counter + 1;
}
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
roiManager("Select", BoxHoles);
wait(25);
run("Fill", "slice");
}
getDimensions(width, height, channels, slices, frames);
for (ii = 0; ii < width; ii++) {
for (jj = 0; jj < height; jj++) {
currentvalue = getPixel(ii, jj);
setPixel(ii, jj, 1 / currentvalue);
}
}
wait(25);
run("Threshold...");
setAutoThreshold("Default dark");
setThreshold(-1 / Threshy, 1 / Threshy);
run("Convert to Mask");
wait(50);
run("Make Binary");
wait(50);
run("Create Selection");
if (selectionType() != -1) {
roiManager("Add"); //roi[1]Tubules in Y
BoxTubulesInY = roiManager("count") - 1;
} else {
BoxTubulesInY = -1;
}
selectWindow("GradientY");
close();
selectWindow("faintTubules");
getDimensions(width, height, channels, slices, frames);
newImage("Skeleton", "8-bit white", width, height, 1);
setForegroundColor(0, 0, 0);
setBackgroundColor(0, 0, 0);
//Now, we take the detection from the x and y directions and overlay them
if (BoxTubulesInX > -1 && BoxTubulesInY > -1) {
roiManager("Select", BoxTubulesInX);
run("Fill", "slice");
roiManager("Select", BoxTubulesInY);
run("Fill", "slice");
}
run("Create Selection");
//this enlarge step is done to clear holes in the center if any.
run("Enlarge...", "enlarge=1");
run("Enlarge...", "enlarge=-1");
if (selectionType() != -1) {
roiManager("Add"); //roi[2] blob tubules
BoxBlobTubules = roiManager("count") - 1;
} else {
BoxBlobTubules = -1;
}
selectWindow("Skeleton");
if (BoxBlobTubules > -1) {
roiManager("Select", BoxBlobTubules);
run("Fill", "slice");
}
//Here, the blobs are skeletonized and then trimmed based on the minimum tubule length
run("Make Binary");
run("Analyze Particles...", "size=MinTubuleLength show=Masks");
//gets rid of tubules of length size
run("Create Selection");
if (selectionType() != -1) {
roiManager("Add"); //roi[3] skeletonized tubulez
BoxSkeletonizedTubules = roiManager("count") - 1;
} else {
BoxSkeletonizedTubules = -1;
}
selectWindow("Skeleton");
close();
wait(25);
selectWindow("faintTubules");
//Here the skeletonized tubules are overlayed to the image
close("\\Others");
run("Duplicate...", "title=test");
selectWindow("faintTubules");
if (BoxSkeletonizedTubules > -1) {
wait(500);
roiManager("Select", BoxSkeletonizedTubules);
wait(500);
selectWindow("test");
wait(500);
selectWindow("faintTubules");
wait(500);
selectWindow("test");
wait(500);
selectWindow("faintTubules");
}
//Here the user input for the tubule detection parameters occurs.
Dialog.create("Tubule Detection Parameters");
Dialog.addNumber("Tubule Detection Sensitivity, (larger # = less sensitive)", Threshy);
Dialog.addNumber("Minimum Tubule Length [pixel]", MinTubuleLength);
Dialog.addCheckbox("Check to accept settings", false);
Dialog.show();
Threshy = Dialog.getNumber();
MinTubuleLength = Dialog.getNumber();;
Continue = Dialog.getCheckbox();
print("Threshy is now " + Threshy);
if (BoxSkeletonizedTubules > 0) {
roiManager("select", BoxSkeletonizedTubules);
roiManager("Delete");
}
roiManager("reset");
}
close("\\Others");
close();
//--------------------------------------------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------
//Now that the parameters are all defined, the program will loop through and analyze all the images.
run("Set Measurements...", "area mean integrated redirect=None decimal=5");
//makes checkpictures folder
myDir = stringy + "Traced Images" + File.separator;
File.makeDirectory(myDir);
if (!File.exists(myDir))
exit("Unable to create directory");
j = 1; //counter variable for result
setBackgroundColor(0, 255, 255);
setForegroundColor(253, 253, 253);
for (i = 0; i < q; i++) {
setBackgroundColor(0, 255, 255);
setForegroundColor(253, 253, 253);
open(stringy + StringyList[i]);
wait(25);
run("Set Scale...", "distance=0 known=0 pixel=1 unit=pixel");
rename("image2");
selectWindow("image2");
run("Split Channels");
if (tubulecolor == "r") {
close();
close();
}
if (tubulecolor == "g") {
close();
close("\\Others");
}
if (tubulecolor == "b") {
close("\\Others");
}
rename("image2");
selectWindow("image2");
selectWindow("image2");
//----------------------------------------------------------
//this is to destroy all of the holes
//----------------------------------------------------------
//----------------------------------------------------------
wait(25);
run("Duplicate...", "title=HoleKiller");
wait(25);
getRawStatistics(nPixels, Mean, min, max, std, histogram);
getDimensions(width, height, channels, slices, frames);
run("Threshold...");
setAutoThreshold("Default dark");
setThreshold(0, 1.25 * Mean);
setOption("BlackBackground", false);
run("Convert to Mask");
run("Create Selection");
if (selectionType() != -1) {
roiManager("Add"); //roi[2] holes
Holes = roiManager("count") - 1;
} else {
Holes = -1;
}
selectWindow("HoleKiller");
close();
//-----------------------------------------------------
//-------------------------------------------------------
run("FeatureJ Derivatives", "x-order=1 y-order=0 z-order=0 smoothing=smooth");
rename("GradientX");
wait(25);
//Zero's out the holes area
//
if (Holes > -1) {
roiManager("Select", Holes);
getRawStatistics(nPixels, Mean, min, max, std, histogram);
getDimensions(width, height, channels, slices, frames);
xx = 128;
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
makeRectangle(0, 0, 1, 1);
run("Fill", "slice");
while (abs(getPixel(0, 0)) > 0.5) {
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
makeRectangle(0, 0, 1, 1);
run("Fill", "slice");
if (getPixel(0, 0) > 0) {
xx = xx - 1;
} else {
xx = xx + 1;
}
counter = counter + 1;
}
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
roiManager("Select", Holes);
wait(25);
run("Fill", "slice");
}
getDimensions(width, height, channels, slices, frames);
for (ii = 0; ii < width; ii++) {
for (jj = 0; jj < height; jj++) {
currentvalue = getPixel(ii, jj);
setPixel(ii, jj, 1 / currentvalue);
}
}
getRawStatistics(nPixels, Mean, min, max, std, histogram);
run("Threshold...");
setAutoThreshold("Default dark");
setThreshold(-1 / Threshy, 1 / Threshy);
wait(50);
//run("NaN Background");
run("Convert to Mask");
wait(50);
run("Make Binary");
wait(50);
//setForegroundColor(0, 0, 0);
//setBackgroundColor(0, 0, 0);
//setOption("BlackBackground", false);
run("Create Selection");
//checks to see if actual selection exist
if (selectionType() != -1) {
roiManager("Add"); //roi[3]Tubules in X
TubulesInX = roiManager("count") - 1;
} else {
TubulesInX = -1;
}
selectWindow("GradientX");
close();
//selectWindow("GFP2-iter13");
run("FeatureJ Derivatives", "x-order=0 y-order=1 z-order=0 smoothing=smooth");
rename("GradientY");
wait(25);
if (Holes > -1) {
roiManager("Select", Holes);
getRawStatistics(nPixels, Mean, min, max, std, histogram);
getDimensions(width, height, channels, slices, frames);
xx = 128;
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
makeRectangle(0, 0, 1, 1);
run("Fill", "slice");
while (abs(getPixel(0, 0)) > 0.5) {
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
makeRectangle(0, 0, 1, 1);
run("Fill", "slice");
if (getPixel(0, 0) > 0) {
xx = xx - 1;
} else {
xx = xx + 1;
}
counter = counter + 1;
}
setForegroundColor(xx, xx, xx);
setBackgroundColor(xx, xx, xx);
roiManager("Select", Holes);
wait(25);
run("Fill", "slice");
}
getDimensions(width, height, channels, slices, frames);
for (ii = 0; ii < width; ii++) {
for (jj = 0; jj < height; jj++) {
currentvalue = getPixel(ii, jj);
setPixel(ii, jj, 1 / currentvalue);
}
}
run("Threshold...");
setAutoThreshold("Default dark");
setThreshold(-1 / Threshy, 1 / Threshy);
run("Convert to Mask");
//run("NaN Background");
wait(50);
//setForegroundColor(0, 0, 0);
//setBackgroundColor(0, 0, 0);
//setOption("BlackBackground", false);
run("Make Binary");
wait(50);
run("Create Selection");
if (selectionType() != -1) {
roiManager("Add"); //roi[4]Tubules in Y
TubulesInY = roiManager("count") - 1;
} else {
TubulesInY = -1;
}
selectWindow("GradientY");
close();
//selectWindow("GFP2-iter13");
//close();
selectWindow("image2");
getDimensions(width, height, channels, slices, frames);
newImage("Skeleton", "8-bit white", width, height, 1);
setForegroundColor(0, 0, 0);
setBackgroundColor(0, 0, 0);
if (TubulesInX > -1 && TubulesInY > -1) {
roiManager("Select", TubulesInX);
run("Fill", "slice");
wait(25);
roiManager("Select", TubulesInY);
run("Fill", "slice");
wait(25);
run("Create Selection");
run("Enlarge...", "enlarge=1");
wait(25);
run("Enlarge...", "enlarge=-1");
roiManager("Add"); //roi[5] blob tubules
BlobTubules = roiManager("count") - 1;
} else {
BlobTubules = -1;
}
selectWindow("Skeleton");
if (BlobTubules > -1) {
roiManager("Select", BlobTubules);
wait(25);
run("Fill", "slice");
}
run("Make Binary");
wait(25);
//roiManager("select",GraftAreaInSmallWindow);
//run("Enlarge...", "enlarge=-1");
//setForegroundColor(255, 255, 255);
//setBackgroundColor(255, 255, 255);
//run("Clear Outside");
run("Analyze Particles...", "size=MinTubuleLength show=Masks");
run("Create Selection");
run("Measure");
if (selectionType() != -1) {
roiManager("Add"); //roi[6] skeletonized tubulez
wait(25);
SkeletonizedTubules = roiManager("count") - 1;
} else {
SkeletonizedTubules = -1;
}
setResult("Image Name", j - 1, "Tubule" + StringyList[i]);
j = j + 1;
//drawing pictures, creates the images in traced images folder.
//------------------------------------------------------------
selectWindow("image2");
run("Select None");
Coolstring = split(StringyList[i], ".");
run("Duplicate...", "title=blank");
wait(25);
saveAs("Tiff", myDir + Coolstring[0] + "a.tif");
close();
run("Set Scale...", "distance=0 known=0 pixel=1 unit=pixel");
//drawing picture
run("Line Width...", "line=1");
wait(25);
if (SkeletonizedTubules > -1) {
roiManager("Select", SkeletonizedTubules);
run("RGB Color");
setForegroundColor(255, 255, 0);
run("Draw");
}
run("Save", "save=[" + myDir + Coolstring[0] + "b.tif" + "]");
run("Close");
wait(25);
close("\\Others");
run("Close");
roiManager("reset");
}
//Organizes tubule data
sum = 0;
counter = 0;
for (i = 0; i < j - 1; i += 1) {
Area = getResult("Area", i);
setResult("TubuleLengthPerimage [pix]", i, Area);
sum = sum + Area;
if (Area != 0) counter = counter + 1;
}
setResult("Sum of Tubule Length Per Folder [pix]", 0, sum);
setResult("Average Tubule Length Per Image [pix]", 0, sum / counter);
setResult("Tubule detection sensitivity:", 0,Threshy);
setResult("Minimum Tubule Length [Pix]",0,MinTubuleLength);
folder = File.getName(stringy);
name = folder + " Tracing Data Summary.csv";
saveAs("Results", stringy + name);
wait(25);
run("Clear Results");
// Headers, font color, and italics
showMessage("1/1", "" + "Analysis Complete
");