//Macro_Segment2D_in_ROI
macroName = "Macro_Segment2D_in_ROI";
macroDescription = "This macro loads images and ROIs (.zip) to do segmetation for pre-processes Opera images (.tif)." +
"\nOptionally, new segmentation parameters can be adjusted and measurement can be done in multiple channels" +
"\nIn the manual mode the macro allows interactively to process each image manually, alternatively batch processing is possible.";
release = "second release 17-01-2014 by Macro_Segment2D_in_ROI Martin Stöter (stoeter(at)mpi-cbg.de)";
html = ""
+"" + macroName + "/n" + release + "
"
+"Check for help on this web page:
"
+"http://idisk-srv1.mpi-cbg.de/knime/FijiUpdate/" + macroName + ".htm this is under construction
"
+"...get this URL from Log window!
"
+"";
//start macro
Dialog.create("Fiji macro: " + macroName);
Dialog.addMessage("Fiji macro: " + macroName + " (Fiji-Tools by TDS@MPI-CBG)\n \n" + macroDescription + "\nClick 'OK' to go on, 'Cancel' to quit or 'Help' for online description.");
Dialog.addHelp(html);
print("http://idisk-srv1.mpi-cbg.de/knime/FijiUpdate/TDS%20macros/" + macroName + ".htm");
Dialog.show;
//print macro name and current time to Log window
getDateAndTime(year, month, dayOfWeek, dayOfMonth, hour, minute, second, msec); month++;
print("\\Clear");
print(macroName,"\nStart:",year+"-"+month+"-"+dayOfMonth+", "+hour+"-"+minute+"-"+second);
//choose folders
inputPath = getDirectory("Choose image folder... ");
roiPath = getDirectory("Choose ROI folder... ");
outputPath = getDirectory("Choose result image folder... or create a folder");
//inputPath = "Y:\\projects\\FishStemCell_Guru\\operaimages\\006FS131021A-dechorionEmbryos384_08planes50um_bin2_autoFluo\\Meas_01(2013-10-24_18-45-15)\\";
//outputPath= "Y:\\projects\\FishStemCell_Guru\\analysis\\006FS131021\\processedImages\\006FS131021A-dechorionEmbryos384_08planes50um_bin2_auto\\segmentationNoWellsegmentation\\";
printPaths = "inputPath = \"" + inputPath + "\";\nroiPath = \"" + roiPath + "\";\noutputPath = \"" + outputPath + "\";";
print(printPaths);
availableImageFormats = newArray("Opera (.tif)", "Opera (.flex)", "Exported (.tif)", "ArrayScan (.c01)"); //image formats to choose
Dialog.create("Conditions");
Dialog.addChoice("Image format:", availableImageFormats);
Dialog.addNumber("Channels:", 3);
Dialog.addNumber("Start at well no.", 1);
Dialog.show();
imageFormat = Dialog.getChoice();
numberOfChannels = Dialog.getNumber();
startAtWellNumber = Dialog.getNumber();
//set array variables for RGB merge
availableChannels = newArray("*None*", "Channel_0", "Channel_1", "Channel_2", "Channel_3"); //array of color selection for channel 1-4
availableChannelsTags = newArray("_Ch1", "Ch2_substracted", "_Ch3", "_Ch4"); //array of color selection for channel 1-4
useChannels = newArray(numberOfChannels);
channelsTags = newArray(numberOfChannels);
channelFileName = "noOtherChannelImageOpen";
montageImage = "noMontageImageOpen";
//set boolean variables
analyseWell = true;
manualMode = true;
previousSegmentation = true;
checkControlImage = false;
//set segmentation defaults
gaussianBlurRadius = 0.60;
unsharpMaskRadius = 1.5; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
allAutoThresholdMethods = newArray("Default","Huang","Intermodes","Isodata","Li","MaxEntropy","Meas","MinError(I)","Minimum","Moments","Otsu","Percentile","RenyiEntropy","Shanbhan","Triangle","Yen");
autoThresholdMethod = allAutoThresholdMethods[4];
minObjectSize = 5;
maxObjectSize = 200;
print("Segmentation parameters: Gaussian radius =",gaussianBlurRadius,"; Unsharp mask radius =",unsharpMaskRadius,"; Auto Threshold Method =",autoThresholdMethod,"\nMinimum object size =",minObjectSize,"; Maximum object size =",maxObjectSize);
//set variables for auto contrast and background corrections
Dialog.create("Select channels");
Dialog.addMessage("Which channel to use and give channel specific text?");
for (i = 1; i <= numberOfChannels; i++) Dialog.addCheckbox("Channel " + i, useChannels[i-1]);
for (i = 1; i <= numberOfChannels; i++) Dialog.addString("Channel " + i, availableChannelsTags[i-1]);
Dialog.addCheckbox("Use previous segmetation?", previousSegmentation);
Dialog.show();
for (i = 0; i < numberOfChannels; i++) useChannels[i] = Dialog.getCheckbox();
for (i = 0; i < numberOfChannels; i++) channelsTags[i] = Dialog.getString();
previousSegmentation = Dialog.getCheckbox();
//get list of channels
channelTagList = newArray(0);
for (i = 1; i <= numberOfChannels; i++) {
if (useChannels[i-1]) channelTagList = Array.concat(channelTagList,channelsTags[i-1]);
}
Array.print(channelTagList);
// select segmentation channel if more than one
if (lengthOf(channelTagList) > 1) {
Dialog.create("Which is segmentation channel?");
Dialog.addChoice("Segmentation on channel:", channelTagList);
Dialog.show();
segmentationChannelTag = Dialog.getChoice();
} else {
segmentationChannelTag = channelTagList[0];
}
//resort channel list so that segmentation channel is first in list
tempchannelTagList = newArray(1);
tempchannelTagList[0] = segmentationChannelTag;
for (i = 0; i < lengthOf(channelTagList); i++) {
if (channelTagList[i] != segmentationChannelTag) tempchannelTagList = Array.concat(tempchannelTagList,channelTagList[i]);
}
channelTagList = tempchannelTagList;
Array.print(channelTagList);
//list files in directory
fileList = getFileList(inputPath);
l = fileList.length;
k=0;
filteredFileList =newArray(l);
for (i = 0; i < l; i++) {
//print(fileList[i], segmentationChannelTag, indexOf(fileList[i],segmentationChannelTag));
if (indexOf(fileList[i],segmentationChannelTag) != -1) {
filteredFileList[k] = fileList[i];
k++;
}
}
filteredFileList = Array.slice(filteredFileList,0,k);
//setBatchMode(true);
//configure
run("Set Measurements...", "area mean standard min centroid center shape integrated median display redirect=None decimal=3");
run("Input/Output...", "jpeg=75 gif=-1 file=.txt copy_column copy_row save_column save_row");
run("Options...", "iterations=1 count=1 black edm=Overwrite");
run("Close All");
setForegroundColor(0, 0, 0);
run("Clear Results");
wellList = getAllWellsFuntion(filteredFileList, false);
exampleFileName = getImageFileExample(filteredFileList);
//create list field strings for file names
//now load well by well
for (currentWell = startAtWellNumber-1; currentWell < wellList.length; currentWell++) { //currentWell < wellList.length; 26-27
//fileName = wellList[currentWell] + substring(exampleFileName, 6,lengthOf(exampleFileName));
fileName = wellList[currentWell] + substring(exampleFileName, 6,lengthOf(exampleFileName));
//to log window
print("well:", wellList[currentWell], ", file:", fileName);
if (imageFormat == "Opera (.tif)") open(inputPath + fileName);
imageTitle = getTitle();
heightPixel = getHeight();
widthPixel = getWidth();
if (manualMode) {
run("Enhance Contrast", "saturated=0.35");
Dialog.create("Analyse image?");
Dialog.addCheckbox("Analyse image?", analyseWell);
Dialog.addCheckbox("Stay in manual mode?", true);
Dialog.addCheckbox("Check final control image?", checkControlImage);
Dialog.show();
analyseWell = Dialog.getCheckbox();
manualMode = Dialog.getCheckbox();
checkControlImage = Dialog.getCheckbox();
}
if (analyseWell) {
//reset ROImanager and load ROI
if (isOpen("ROI Manager")) {
selectWindow("ROI Manager");
run("Close");
}
roiFileName = substring(fileName, 0, lengthOf(fileName)-4) + "_ROIset.zip";
if (!File.exists(roiPath + roiFileName)) {
printText = "ROI-file not found:\n" + roiFileName + "\nnot found in folder: " + roiPath;
print(printText);
close(imageTitle);
} else {
run("Select None");
run("ROI Manager...");
roiManager("Show None");
roiManager("Open", roiPath + roiFileName);
//generate ROI outline image
newImage("ROI outline", "8-bit white", widthPixel, heightPixel, 1);
roiManager("Select", 0);
roiManager("Draw");
run("Invert");
if (previousSegmentation) { //use loaded segmentation
//generate segmentation outline image
//setBatchMode(true);
newImage("Segmentation outline", "8-bit white", widthPixel, heightPixel, 1);
for (i=1; i < roiManager("count"); i++) {
roiManager("Select", i);
roiManager("Draw");
}
run("Invert");
} else { //do new sementation
//setBatchMode(true);
roiCount = roiManager("count");
for (i=1; i < roiCount; i++) { //deletes ROIs backwards from last until secon ROI, first is kept
roiManager("Select", roiCount - i);
roiManager("Delete");
}
updateResults();
setBatchMode(false);
do { //do auto threshold montage until dialog unchecked
if (isOpen("segmentation")) close("segmentation");
selectWindow(fileName);
if (manualMode) {
Dialog.create("Set segmentation parameters?");
Dialog.addNumber("Gaussian Blur radius:", gaussianBlurRadius);
Dialog.addNumber("Unsharp Mask radius:", unsharpMaskRadius);
Dialog.addChoice("Auto Threshold method?", allAutoThresholdMethods, autoThresholdMethod);
Dialog.addCheckbox("Show all auto threshold methods?", false);
Dialog.addNumber("Minumum object size:", minObjectSize);
Dialog.addNumber("Maximum object size:", maxObjectSize);
Dialog.show();
gaussianBlurRadius = Dialog.getNumber();
unsharpMaskRadius = Dialog.getNumber();
autoThresholdMethod = Dialog.getChoice();
autoThresholdMontage = Dialog.getCheckbox();
minObjectSize = Dialog.getNumber();
maxObjectSize = Dialog.getNumber();
print("Segmentation parameters: Gaussian radius =",gaussianBlurRadius,"; Unsharp mask radius =",unsharpMaskRadius,"; Auto Threshold Method =",autoThresholdMethod,"\nMinumum object size =",minObjectSize,"; Maximum object size =",maxObjectSize);
}
run("Duplicate...", "title=segmentation");
run("Gaussian Blur...", "sigma=" + gaussianBlurRadius);
run("Unsharp Mask...", "radius=" + unsharpMaskRadius + " mask=0.60");
if (autoThresholdMontage) {
run("Auto Threshold", "method=[Try all] ignore_black ignore_white white");
montageImage = getTitle();
waitForUser("'OK' to continue... (back to dialog)");
}
if (isOpen(montageImage)) close(montageImage);
} while (autoThresholdMontage);
selectWindow("segmentation");
run("Auto Threshold", "method=" + autoThresholdMethod + " ignore_black ignore_white white");
run("Watershed");
roiManager("Select", 0);
run("Analyze Particles...", "size=" + minObjectSize + "-" + maxObjectSize + " circularity=0.00-1.00 show=[Bare Outlines] include add");
rename("Segmentation outline");
run("Invert");
close("segmentation");
roiManager("save", outputPath + substring(fileName, 0, lengthOf(fileName)-4) + "_ROIsetNew.zip");
}
//now analyse ROI image
run("Select None");
run("Clear Results");
//setBatchMode(true);
selectWindow(fileName);
for (i=0; i < roiManager("count"); i++) { //measure segmentation channel
roiManager("Select", i);
roiManager("Measure");
}
//set contrast for RGB
selectWindow(fileName);
resetMinAndMax();
run("Enhance Contrast", "saturated=0.35");
run("8-bit");
//run("Merge Channels...", "c2=[Segmentation outline] c4=" + fileName + " c5=[ROI outline]");
run("Merge Channels...", "c1=[Segmentation outline] c2=" + fileName + " c5=[ROI outline]");
close("RGB"); //composite
selectWindow("RGB (RGB)");
saveAs("PNG", outputPath + substring(fileName, 0, lengthOf(fileName)-4) + "_manualRGBoutlines.png");
rename("RGB");
for (currentChannel = 2; currentChannel <= lengthOf(channelTagList); currentChannel++) { //if other channels show be quantified as well
channelFileName = substring(fileName,0,indexOf(fileName, segmentationChannelTag)) + channelTagList[currentChannel - 1] + substring(exampleFileName, lengthOf(exampleFileName) - 9,lengthOf(exampleFileName));
//to log window
print("well:", wellList[currentWell], ", file:", channelFileName);
if (File.exists(inputPath + channelFileName)) {
open(inputPath + channelFileName);
for (i=0; i < roiManager("count"); i++) {
roiManager("Select", i);
roiManager("Measure");
}
} else {
printText = "File not found:\n" + channelFileName + "\nnot found in folder: " + inputPath;
print(printText);
}
if (isOpen(channelFileName)) close(channelFileName);
}
saveAs("Results", outputPath + substring(fileName, 0, lengthOf(fileName)-4) + "_manualROI_HSCcount.txt");
updateResults();
setBatchMode(false);
if (checkControlImage && manualMode) { //check manually segmentation
selectWindow("RGB");
setTool("zoom");
waitForUser;
}
close("RGB");
run("Clear Results");
}
} else {
close(imageTitle);
}
}
//print current time to Log window and save log
getDateAndTime(year, month, dayOfWeek, dayOfMonth, hour, minute, second, msec); month++;
print("Macro executed successfully.\nEnd:",year+"-"+month+"-"+dayOfMonth+", "+hour+"-"+minute+"-"+second);
selectWindow("Log");
saveAs("Text", outputPath + "Log_"+year+"-"+month+"-"+dayOfMonth+", "+hour+"-"+minute+"-"+second+".txt");
/////////////////////////////////////////////////////////////////////////////////////////////
//////// F U N C T I O N S /////////////
/////////////////////////////////////////////////////////////////////////////////////////////
function getAllWellsFuntion(fileList, closeWindow) {
//function get all unique wells from a file list
//the file list needs to be a list of files exported from ArrayScan/HCSView (.tif or .TIF)
//the function goes through the sorted list and finds the well-text in file name (MFGTMP_131004100001_C02f00d1.TIF position 12 to 9 counted form end of file name => C02)
//unique well-text and number of found images per well (fields x channels) are put to a list/array
//message pops up information about number of wells found and their number of images, that will be closed then second parameter = true
Array.sort(fileList);
wellList = newArray(fileList.length);
wellImageCountList = newArray(fileList.length);
wellIndexList = newArray(fileList.length);
wellIndex = 0;
wellImageCount = 0;
currentFile = 0;
if (imageFormat == "Opera (.tif)") { //forward well reading
do {
if (endsWith(fileList[currentFile],".tif")){ //exclude metadata files
wellImageCount++;
if (wellIndex == 0) { //for first image found set current well
currentWell = substring(fileList[currentFile], 0,6);
wellList[wellIndex] = currentWell;
wellIndexList[wellIndex] = d2s(wellIndex+1,0);
wellIndex++;
}
//check if next image belongs to same well, if not put well and counted field-channel images in list
if (currentWell != substring(fileList[currentFile],0,6)) {
wellImageCountList[wellIndex-1] = d2s(wellImageCount-1,0); //write how many images in current well
wellImageCount = 1; //reset counter
currentWell = substring(fileList[currentFile],0,6);
wellList[wellIndex] = currentWell; //set new current well
wellIndexList[wellIndex] = d2s(wellIndex+1,0);
wellIndex++;
}
//for debugging: print(fileList[currentFile], currentFile, currentWell, wellIndex, wellImageCount);
}
currentFile++;
} while (currentFile < fileList.length); //for all files found
wellImageCountList[wellIndex-1] = d2s(wellImageCount,0); //write how many imges are in last well
}
//trim array lists and show in window
wellList = Array.slice(wellList,0,wellIndex);
wellIndexList = Array.slice(wellIndexList,0,wellIndex);
wellImageCountList = Array.slice(wellImageCountList,0,wellIndex);
//show result of well list
Array.show(wellIndexList,wellList,wellImageCountList);
waitForUser("Number of well found: " + wellIndex + "\n " + " \n" +"Check if number of wells and number of images in well" + "\n" + "are as expected! Otherwise press 'ESC' and check image list!");
//tidy up and close windows
if (closeWindow) {
windowList = getList("window.titles");
for (i = 0; i < windowList.length; i++) {
if (windowList[i] == "Arrays") {
selectWindow("Arrays");
run("Close");
}
}
}
//end of function: return well list
return wellList;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
function getImageFileExample(fileList) {
//function get an image file name as an example from a file list
//the file list needs to have image file name with these extensoins: .tif or .TIF
//message pops up if no image is found and macro is aborted
currentFile = 0;
if (imageFormat == "Opera (.tif)") {
do {
if (endsWith(fileList[currentFile],".tif")){ //exclude metadata files
//end of function: first image name
return fileList[currentFile];
}
currentFile++;
} while (currentFile < fileList.length); //for all files found
}
//show file list and abort macro
Array.show(fileList);
exit("No image files found!?" + "\n " + " \n" +"Check image list!");
}
//////////////////////////////////////// E N D O F M A C R O ////////////////////////////