//** Created by Damon Poburko, Dept. of Molecular & Cellular Physiology, // Stanford University, Stanford, California, March 01, 2009 // // This macro was created to faciliate the use of the Analyze Particles plugin in // Image J in images with widely varying particle inensity and varying background // intensity, where a single is not sufficient to adequately identify ROIs for // further analysis. This macro is provided as is with limited documentation. // Prince of analysis: The macro runs the Analyze Particles plugin over a series of // threshold values. On each run of Analyze Particles, those particles that meet // the user-defined criteria will be added to a common store. Once a given puncta // exceeds the maximum size, the puncta at that location will be held in the common // store at the last size which was within the selection criteria. The macro does // have some limitations in its ability to catch or identify dim puncta that are on // the shoulder of a much brighter neighbouring puncta. // //Basic Usage: // 1. Select Image that you want to anayze. // 2. Run the macro and enter selection criteria to identify puncta. Will require // some optimization of settings for varying image types. // 3. If you choose to "auto Calc." the values for the lowest threshold value // (= mean of ROI + X*SD), you will be promted to choose an ROI for // your background // 4. In Part 4 below, users may want to alter which measurements are // recorded in the results table /* version 3.3, August 31, 2011 - added option to run a background subtraction prior to finding ROIs - simplified dialog with dropDown box to choose whether # of steps or step size would be used - added option to exclude ROIs that fall within a user definable distance from the image edge - when running in batchmode, the ROI manager is closed during the macro and re-opened at the end. Macro should run faster this way. */ /* version 3.6, September 22, 2011 - removed unneccesary "setAutoThreshold();" in the particle analyzing loop. Runs ~5-10x faster on normal images and prevents 2-5x slow-down in background subtracted images */ requires("1.42l"); // Image J version check. I have not check that it works with versions of Image J prior to 1.42l, but it might // Note - will run faster with IJ1.45n5 due to faster deleting and updating of ROI manager print("\\Clear"); //clear log // ==== User Variables Dialog box: =============================================== print (call("ij.Prefs.get", "dialogDefaults.stepMethod","# of thresholds")); if ( call("ij.Prefs.get", "dialogDefaults.stepMethod","# of thresholds") == "step size" ) stepMethodArray = newArray( "step size", "# of thresholds"); if ( call("ij.Prefs.get", "dialogDefaults.stepMethod","# of thresholds") == "# of thresholds") stepMethodArray = newArray("# of thresholds","step size"); // ======generate dialog boix======================== Dialog.create("Multiple Thresholds Parameters v3.5"); Dialog.addCheckbox("analyze for 40APs (2 SDs)", false); Dialog.addCheckbox("analyze for LARGE ROIs", false); Dialog.addNumber("Thresholding settings: # od SDs:", parseInt(call("ij.Prefs.get", "dialogDefaults.xStandardDeviations", "3"))); //usually 3 Dialog.addChoice("Define # of thresholds or Step Size", stepMethodArray); Dialog.addNumber("# of thresholds OR Step size:", parseInt(call("ij.Prefs.get", "dialogDefaults.nThresholdsOrStepSize", "20"))); Dialog.addCheckbox("auto. calc. first (upper) threshold ", true); Dialog.addNumber(" If above box not checked define first threshold level", -1); Dialog.addCheckbox("auto. calc. last (lowest) threshold ", true); Dialog.addNumber(" If above box not checked define last threshold level", -1); Dialog.addMessage("Puncta Parameters:"); Dialog.addNumber("min puncta size (pixels):", parseInt(call("ij.Prefs.get", "dialogDefaults.minParticle", "4"))); Dialog.addNumber("max puncta size (pixels):", parseInt(call("ij.Prefs.get", "dialogDefaults.maxParticle", "40"))); Dialog.addNumber("min circularity (0.00-1.00):", parseFloat(call("ij.Prefs.get", "dialogDefaults.minCircularity", "0.6"))); Dialog.addMessage("Pre- & Post-hoc options:"); Dialog.addNumber("radius of bkgd subtraction (-1 = none):", parseInt(call("ij.Prefs.get", "dialogDefaults.ballSize", "-1"))); Dialog.addCheckbox("Watershed filter final ROI set", call("ij.Prefs.get", "dialogDefaults.doWatershed", false)); Dialog.addNumber("exclude ROIs within # pixel boarder: ",parseInt(call("ij.Prefs.get", "dialogDefaults.borderWidth", "5"))); Dialog.addMessage("File Handling:"); Dialog.addCheckbox("show the equivalent single threshold", false); Dialog.addCheckbox("Save puncta Images", false); Dialog.addCheckbox("Save puncta Measurements & ROIs", false); Dialog.show(); // ====== retireve values ============================ do40AP = Dialog.getCheckbox(); doLargeRois = Dialog.getCheckbox(); xStandardDeviations = Dialog.getNumber(); call("ij.Prefs.set", "dialogDefaults.xStandardDeviations", xStandardDeviations); stepMethod = Dialog.getChoice(); call("ij.Prefs.set", "dialogDefaults.stepMethod", stepMethod); nThresholdsOrStepSize = Dialog.getNumber(); call("ij.Prefs.set", "dialogDefaults.nThresholdsOrStepSize", nThresholdsOrStepSize); autoMax = Dialog.getCheckbox(); autoMax = 1; if (autoMax==true) autoMax = 0; autoFloor = Dialog.getCheckbox(); autoFloor = 1; if (autoFloor==true) autoFloor = 0; maxPixel = Dialog.getNumber(); floorPixel = Dialog.getNumber(); minParticle = Dialog.getNumber(); call("ij.Prefs.set", "dialogDefaults.minParticle", minParticle); maxParticle = Dialog.getNumber(); call("ij.Prefs.set", "dialogDefaults.maxParticle", maxParticle); minCircularity = Dialog.getNumber(); call("ij.Prefs.set", "dialogDefaults.minCircularity", minCircularity); ballSize = Dialog.getNumber(); call("ij.Prefs.set", "dialogDefaults.ballSize", ballSize); if (ballSize != -1) run("Subtract Background...", "rolling="+ballSize+""); doWatershed =Dialog.getCheckbox(); call("ij.Prefs.set", "dialogDefaults.doWatershed", doWatershed); borderWidth = Dialog.getNumber(); call("ij.Prefs.set", "dialogDefaults.borderWidth", borderWidth); doSimpleThreshold = Dialog.getCheckbox(); saveImages = Dialog.getCheckbox(); saveResults = Dialog.getCheckbox(); //additional sets of default values for common analyses. Other varialbes/criteria could be added if (do40AP == true) { xStandardDeviations = 2; userStepSize = 8; } if (doLargeRois == true) { minParticle = 9; maxParticle = 40; } // ===== Part 2: get image path info & start analysis =========================================================== // =================================================================================================== imagePath = getDirectory("image"); setBatchMode(true); // **** macros manipulating the ROI list run much faster when the ROI manager is closed and in BatchMode **** if (isOpen("ROI Manager")) { selectWindow("ROI Manager"); run("Close"); } imageName = getTitle(); if (indexOf(imageName,".tif")!=-1) { baseName = substring( imageName, 0, lastIndexOf( imageName, ".tif" ) ); } else { baseName = imageName; } run("Duplicate...", "title=working"); run("Gaussian Blur...", "sigma=0.90"); if (indexOf(imageName,"NH4Cl")!=-1) { // override user selection of SD when analyzing NH4Cl difference images xStandardDeviations = 2; } if (autoMax == 0) { getStatistics(area, mean, min, max, std); maxPixel = max; SD = std; } // ===== determine background fluorescence ========== if (autoFloor == 0) { selectWindow(imageName); run("Enhance Contrast", "saturated=0.5"); waitForUser("Select representative background ROI \n then click OK to resume"); getStatistics(area, mean, min, max, std); SD = round(std); floorPixel = mean + (xStandardDeviations * SD); run("Select None"); } // ===== SET X PIXEL WIDE BORDER EQUAL TO ZERO TO AVOID EDGE ISSUES ========== selectWindow("working"); w = getWidth(); h = getHeight(); // ====== Part 3: Calculate step size and fill array from nThresholds or userStepSize ====================================== //================================================================================================= if (stepMethod == "step size") { nThresholds = floor ( (maxPixel - floorPixel) / nThresholdsOrStepSize ); lowerLimits = newArray(nThresholds); stepSize = nThresholdsOrStepSize; for (k =0; k 1 ) { nextName = "puncta "+ lowerLimits[i]; rename(nextName); imageCalculator("OR create", "previousPuncta",nextName); rename("Or"); selectWindow(nextName); close(); selectWindow("previousPuncta"); close(); selectWindow("Or"); rename("previousPuncta"); } } // nResults!=0 loop } // end i loop // ==== 110815 v3.2- added option to run a watershed filter on the final binary image ==================== if (doWatershed == true) run("Watershed"); if (nResults!=0) { roundedFloor = round(floorPixel); intSD = floor(SD); if (stepMethod == "step size") definedStepSize = "yes"; if (stepMethod != "step size") definedStepSize = "no"; // ***** save analysis parameters in the puncta image header. Should always be able to reconstruct analysis from this info. ******* setMetadata("Info", "# SDs: " + xStandardDeviations + "\n # thresholds: " + nThresholds + "\n user defined step size: " + definedStepSize + "\n applied watershed to final image: " + doWatershed+ "\n background: " + roundedFloor + "\n SD: " + intSD + "\n stepSize: " + stepSize + "\n Max Intensity: " + maxPixel +"\n lowest threshold: " + lowerLimits[nThresholds-1] + "\n min puncta Size:" + minParticle + "\n max puncta Size: " + maxParticle + "\n min circularity: " + minCircularity + ""); i = i-1; suffix = "multThrld_" + lowerLimits[0] + "-" + lowerLimits[i]; finalName = baseName + "_" + suffix; rename(finalName); if (saveImages == true) { save(imagePath + finalName + ".tif"); } else { rename(finalName + ".tif"); } if (doSimpleThreshold == true) { // optional calculation of an equivalent simple threshold selectWindow("working"); setAutoThreshold(); resetThreshold(); setThreshold(lowerLimits[i], 64000); run("Analyze Particles...", "size=" + minParticle + "-" + maxParticle + " circularity=" + minCircularity + "-1.00 show=Masks display clear"); simpleThName = baseName + "_sglThrld_" + lowerLimits[i]; rename(simpleThName); if (saveImages == true) save(imagePath + simpleThName + ".tif"); } roiManager("reset"); selectWindow(finalName + ".tif"); setAutoThreshold(); run("Set Measurements...", "area mean min centroid shape redirect=" + imageName + " decimal=3"); run("Analyze Particles...", "size=" + minParticle + "-Infinity circularity=" + minCircularity + "-1.00 display exclude clear add"); //====== compare all final ROIs and remove if their bounds hit the border ============== nROIs = roiManager("count"); print("# ROIs found: "+ nROIs); lxBound = borderWidth; uxBound = w - borderWidth; lyBound = borderWidth; uyBound = h - borderWidth; for (i = 1; i <= nROIs; i++) { j = nROIs - i; roiManager("select",j); getSelectionBounds(x, y, width, height); if ( (x < lxBound) || ( (x+width) > uxBound) || (y < lyBound) || ( (y+height) > uyBound) ) roiManager("Delete"); } print("# ROIs kept: "+ roiManager("count")); //110904 - v3.4: removed option to resize ROIs. Have more efficient macros to do this print(""); for (q=0;q