//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 ////////////////////////////