//-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // latest release date: 09/30/2015 //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- /* * Copyright (C), Jan Brocher / BioVoxxel. All rights reserved. * * All Macros/Plugins were written by Jan Brocher/BioVoxxel. * * Redistribution and use in source and binary forms of all plugins and macros, with or without modification, * are permitted provided that the following conditions are met: * * 1.) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2.) Redistributions in binary form must reproduce the above copyright notice, this list of conditions * and the following disclaimer in the documentation and/or other materials provided with the distribution. * 3.) Neither the name of BioVoxxel nor the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written permission. * * DISCLAIMER: * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ?AS IS? AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ requires("1.50a"); // BioVoxxel Macro Menu var filemenu = newMenu("BioVoxxel Macros Menu Tool", newArray("Extended Particle Analyzer", "Field-of-view measure correction", "Shape Descriptor Maps", "Binary Feature Extractor", "Speckle Inspector", "Watershed Irregular Features", "EDM Binary Operations", "Auto Binary Masking", "-", "Threshold Check", "-", "Filter Check", "-", "Flat-field correction", "Pseudo flat-field correction", "Convoluted Background Subtraction", "Scaled Intensity Plots", "Stack Line Plots", "-", "Gaussian weighted Median", "Difference of Gaussian", "Difference from Median", "Adaptive Filter", "Recursive Filters", "-", "Hyperstack Color Coding", "-", "Neighbor Analysis", "2D Particle Distribution", "Cluster Indicator", "-", "About")); macro "BioVoxxel Macros Menu Tool - C000C010C020C030C040C050Df9C050D62C050D75C060D87C060D76C060D61C060Db8C060D63C060D74Da8Dc8C060D50De9C060D81C060De7C060D91Dc2C060D77Dd4Dd8C060De8C070D71D97Dd3C070D73D78C070D51D60De6C070D06D5aD69Db2C070D4bD86Dd5C070D3dD98Da7C070D64Da2C070D3cD72D82D83D84D85D92D93D94D95D96Da1Da3Da4Da5Da6Db3Db4Db5Db6Db7Dc3Dc4Dc5Dc6Dc7Dd6Dd7C070D2dC070Dd9C070C080D2cC080D15D19Dd2C080D88C080D18C080D24DafC080D33C080D2bC080D42D65C080De5C080D52C080D4cC080D17D41D68C080C090D2aD59C090D9fDb1Dc9C090D32D4aD5bC090D1aD3bC090D16D53D66C090D25D29D5eD6eDf8C090D26D27D28D34D35D36D37D38D39D3aD43D44D45D46D47D48D49D54D55D56D57D58D67DeaC090D6aC090DbeC090D07C090D23DdbC090D70D7eDcdC090D79DccC0a0D4eDb9C0a0DbdDdcC0a0D14C0a0D8eDaeC0a0D4dD8fC0a0D05Da9C0a0DebC0b0Dc1DfaC0b0D9eC0b0D5cD5dD99DdaC0b0D6bD6cD6dD7aD7bD7cD7dD89D8aD8bD8cD8dD9aD9bD9cD9dDaaDabDacDadDbaDbbDbcDcaDcbC0b0De4C0b0D1bD3eC0b0D80C0b0C0c0Df7C0c0D08C0c0D7fC0c0C0d0D2eC0d0Dd1C0d0D6fC0d0C0e0C0f0D5fC0f0"{ BVCmd = getArgument(); if (BVCmd!="-") { if (BVCmd=="Extended Particle Analyzer") { run("Extended Particle Analyzer"); } else if (BVCmd=="Field-of-view measure correction") { CountCorrection(); } else if (BVCmd=="Shape Descriptor Maps") { ShapeDescriptorMaps(); } else if (BVCmd=="Binary Feature Extractor") { run("Binary Feature Extractor"); } else if (BVCmd=="Speckle Inspector") { run("Speckle Inspector"); } else if (BVCmd=="Watershed Irregular Features") { run("Watershed Irregular Features"); } else if (BVCmd=="EDM Binary Operations") { run("EDM Binary Operations"); } else if (BVCmd=="Auto Binary Masking") { AutoMasking(); } else if (BVCmd=="Threshold Check") { ThresholdCheck(); } else if (BVCmd=="Filter Check") { run("Filter Check"); } else if (BVCmd=="Flat-field correction") { FFBackgroundCorrection(); } else if (BVCmd=="Pseudo flat-field correction") { run("Pseudo flat field correction"); } else if (BVCmd=="Median Background Subtraction") { MedianBackgroundSubtraction(); } else if (BVCmd=="Convoluted Background Subtraction") { run("Convoluted Background Subtraction"); } else if (BVCmd=="Scaled Intensity Plots") { ScaledIntensityPlots(); } else if (BVCmd=="Stack Line Plots") { StackLinePlots(); } //else if (BVCmd=="Combine Plots") { CombinePlots(); } else if (BVCmd=="Gaussian weighted Median") { run("Gaussian Weighted Median"); } else if (BVCmd=="Difference of Gaussian") { DifferenceOfGaussian(); } else if (BVCmd=="Difference from Median") { DifferenceOfMedian(); } else if (BVCmd=="Adaptive Filter") { run("Adaptive Filter"); } else if (BVCmd=="Recursive Filters") { run("Recursive Filters"); } else if (BVCmd=="Hyperstack Color Coding") { HyperstackColorCoding(); } else if (BVCmd=="Neighbor Analysis") { NeighborAnalysis(); } else if (BVCmd=="2D Particle Distribution") { run("Particle Distribution (2D)"); } else if (BVCmd=="Cluster Indicator") { run("Cluster Indicator"); } else if (BVCmd=="Particle Length (via Skeleton)") { CorrectedSkeletonLength(); } else if (BVCmd=="About") { About(); } //deprecated links (not present in the menu above, but could still be included (if needed by individual users) else if (BVCmd=="Advanced Particle Analyzer (deprecated)") { AdvancedParticleAnalyzer(); } else if (BVCmd=="Contrast Detection (deprecated)") { ContrastDetection(); } else if (BVCmd=="Cluster Indicator (deprecated macro)") { ClusterIndicator(); } } } //------------------------------------------------------------------------------------------ //Analyze Particles according to shape discriptor limitations //Author: Jan Brocher/BioVoxxel //First version released: 02/05/2013 //version 0.3 (03/05/2013), bug-fixed analyses, works with selections //version 0.4 (08/05/2013), bug-fix to work with scaled images and improved performance //version 0.5 Image selection changed to drop-down menu (14/05/2013) //version 0.6 Added field of view count correction by eliminating edge particles on 2 frame borders (31/05/2013) //version 0.7 added th euser choice to use scaled units or pixels for particle analysis (07/06/2013) //version 0.9 added Extent, Feret's AR and Compactness ; including a bugfix to enable adding to ROI Manager (07/06/2013) //version 1.0 "memory of keyed-in parameters added, restore default also possible (08/07/2013) //version 1.1 Thanks to a suggestion from Sidnei Paciornik added redirection to and usage of original grayscale image // --> calculation of and exclusion by coefficient of variance (COV) (17/02/2014) //version 1.2 Thanks to suggestions from Gabriel Landini and Jan Eglinger improved performance using floodFill command //version 1.3 made Area, Perimeter and Max. Feret sensitive to scaling and enable decision to take units or pixel values //version 1.4 solved problems with object elimination due to accidental scaling of XStart and YStart //------------------------------------------------------------------------------------------ function AdvancedParticleAnalyzer() { originalImg=getTitle(); getDimensions(width, height, channels, slices, frames); getVoxelSize(Vw, Vh, Vdepth, Vunit); //run("Select None"); if(isOpen("Log")==1) { selectWindow("Log"); run("Close"); } if(is("binary")==false || slices>1) { exit("works only on individual 8-bit binary images"); } openImages=nImages; imageNames = newArray(nImages+1); imageNames[0] = "None"; for (i=0; i1) { setSlice(1); } run("Canvas Size...", "width="+(width)+" height="+(height)+" position="+imgPos); selectWindow(duplicate); } original=getTitle(); selectWindow(original); if(Vunit!="pixels" || Vunit!="Pixels") { if(usePixel==true) { usedUnit=" pixel"; } else { usedUnit=""; } } else { usedUnit=""; } run("Analyze Particles...", "size=" + Area + usedUnit + " circularity="+Circularity+" show=Masks" + ExcludeEdges + " clear" + IncludeHoles + " record"); temp=getTitle(); initList=nResults; //Calculate additional values compactness=newArray(initList); FAR=newArray(initList); extent=newArray(initList); cov=newArray(initList); for(calc=0; calcExtentMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(Perimeter!="0-Infinity" && end==false) { PerimeterMin=substring(Perimeter, 0, (indexOf(Perimeter, "-"))); PerimeterMax=substring(Perimeter, (indexOf(Perimeter, "-")+1)); if(PerimeterMax=="Infinity") { PerimeterMax=999999999999; } currentPerimeter = getResult("Perim.", n); if(Vunit!="pixels" || Vunit!="Pixels") { if(usePixel==true) { toUnscaled(currentPerimeter); } } if(currentPerimeterPerimeterMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(Roundness!="0.00-1.00" && end==false) { RoundnessMin=substring(Roundness, 0, (indexOf(Roundness, "-"))); RoundnessMax=substring(Roundness, (indexOf(Roundness, "-")+1)); if(getResult("Round", n)RoundnessMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(Solidity!="0.00-1.00" && end==false) { SolidityMin=substring(Solidity, 0, (indexOf(Solidity, "-"))); SolidityMax=substring(Solidity, (indexOf(Solidity, "-")+1)); if(getResult("Solidity", n)SolidityMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(Compactness!="0.00-1.00" && end==false) { CompactnessMin=substring(Compactness, 0, (indexOf(Compactness, "-"))); CompactnessMax=substring(Compactness, (indexOf(Compactness, "-")+1)); if(compactness[n]CompactnessMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(AR!="0.00-Infinity" && end==false) { ARMin=substring(AR, 0, (indexOf(AR, "-"))); ARMax=substring(AR, (indexOf(AR, "-")+1)); if(ARMax=="Infinity") { ARMax=999999999999; } if(getResult("AR", n)ARMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(FeretAR!="0.00-Infinity" && end==false) { FARMin=substring(FeretAR, 0, (indexOf(FeretAR, "-"))); FARMax=substring(FeretAR, (indexOf(FeretAR, "-")+1)); if(FARMax=="Infinity") { FARMax=999999999999; } if(FAR[n]FARMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(EllipsoidAngle!="0-180" && end==false) { EllipsoidAngleMin=substring(EllipsoidAngle, 0, (indexOf(EllipsoidAngle, "-"))); EllipsoidAngleMax=substring(EllipsoidAngle, (indexOf(EllipsoidAngle, "-")+1)); if(getResult("Angle", n)EllipsoidAngleMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(MaxFeret!="0.00-Infinity" && end==false) { MaxFeretMin=substring(MaxFeret, 0, (indexOf(MaxFeret, "-"))); MaxFeretMax=substring(MaxFeret, (indexOf(MaxFeret, "-")+1)); if(MaxFeretMax=="Infinity") { MaxFeretMax=999999999999; } currentMaxFeret = getResult("Feret", n); if(Vunit!="pixels" || Vunit!="Pixels") { if(usePixel==true) { toUnscaled(currentMaxFeret); } } if(currentMaxFeretMaxFeretMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(FeretAngle!="0-180" && end==false) { FeretAngleMin=substring(FeretAngle, 0, (indexOf(FeretAngle, "-"))); FeretAngleMax=substring(FeretAngle, (indexOf(FeretAngle, "-")+1)); if(getResult("FeretAngle", n)FeretAngleMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } if(COV!="0.00-1.00" && end==false) { COVMin=substring(COV, 0, (indexOf(COV, "-"))); COVMax=substring(COV, (indexOf(COV, "-")+1)); if(cov[n]COVMax) { floodFill(X[n],Y[n], "8-connected"); end=true; } } } selectWindow(temp); if(Vunit!="pixels") { if(usePixel==false) { setVoxelSize(Vw, Vh, Vdepth, Vunit); } else { setVoxelSize(1, 1, 1, "pixels"); } } run("Analyze Particles...", "size=0-Infinity" + usedUnit + " circularity=0.00-1.00 show=["+Output+"]" + DisplayResults + ExcludeEdges + " clear" + IncludeHoles + Summarize + " record" + AddToManager); if(Output!="Nothing") { close(temp); } else { rename("PartAnal_"+originalImg); } finalImg=getTitle(); finalList=nResults; nFAR=newArray(finalList); nCompactness=newArray(finalList); nExtent=newArray(finalList); nCov=newArray(finalList); for(newSD=0; newSD1 || channels>1 || frames>1) { exit("Only works with individual 8-bit binary images"); } Dialog.create("Analyze Particles"); Dialog.addString("Size (pixel^2)", "0-Infinity"); Dialog.addString("Circularity", "0.00-1.00"); Dialog.addChoice("Show", newArray("Nothing", "Outlines", "Bare Outlines", "Ellipses", "Masks", "Count Masks", "Overlay Outlines", "Overlay Masks"), "Masks"); Dialog.addCheckbox("Include holes", false); Dialog.addHelp("www.biovoxxel.de/macros.html"); Dialog.show(); Size=Dialog.getString(); Circularity=Dialog.getString(); Output=Dialog.getChoice(); IncludeHoles=Dialog.getCheckbox(); if(IncludeHoles==true) {IncludeHoles=" include";} else {IncludeHoles=""; } setBatchMode(true); selectWindow(original); run("Analyze Particles...", "size="+Size+" circularity="+Circularity+" show=["+Output+"] clear slice exclude" + IncludeHoles); if(Output=="Masks") { run("Invert LUT"); } results=nResults; correctionFactor=newArray(results); boundWidth=newArray(results); boundHeight=newArray(results); originalArea=newArray(results); finalCount=0; originalAreaSum=0; correctedAreaSum=0; for(i=0; i0) { if(Area[i]>biggestArea) { biggestArea=Area[i]; } if(Peri[i]>biggestPeri) { biggestPeri=Peri[i]; } if(Feret[i]>biggestFeret) { biggestFeret=Feret[i]; } if(Angle[i]>biggestAngle) { biggestAngle=Angle[i]; } if(FeretAngle[i]>biggestFeretAngle) { biggestFeretAngle=FeretAngle[i]; } if(Circ[i]>biggestCirc) { biggestCirc=Circ[i]; } if(Roundness[i]>biggestRoundness) { biggestRoundness=Roundness[i]; } if(AR[i]>biggestAR) { biggestAR=AR[i]; } if(Solidity[i]>biggestSolidity) { biggestSolidity=Solidity[i]; } if(Compactness[i]>biggestCompactness) { biggestCompactness=Compactness[i]; } if(Extent[i]>biggestExtent) { biggestExtent=Extent[i]; } } biggestValue=newArray("biggestArea", "biggestPeri", "biggestFeret", "biggestAngle", "biggestFeretAngle", "biggestCirc", "biggestRounsness", "biggestAR", "biggestSolidity", "biggestCompactness", "biggestExtent"); } /* if(showValues==true) { //print biggest values in the Log winsow print("highest values for individual shape descriptors"); print("Area: "+biggestArea); print("Perimeter: "+biggestPeri); print("Max. Feret: "+biggestFeret); print("Angle: "+biggestAngle); print("Feret Angle: "+biggestFeretAngle); print("Circularity: "+biggestCirc); print("Roundness: "+biggestRoundness); print("Aspect Ratio: "+biggestAR); print("Solidity: "+biggestSolidity); print("Compactness: "+biggestCompactness); print("Extent: "+biggestExtent); } */ //******************************************************************* setPasteMode("Copy"); selectWindow(result); setBatchMode("hide"); for(nS=1; nS<12; nS++) { run("Add Slice"); } run("Select None"); //run voronoi on particles selectWindow(input); run("Voronoi"); setThreshold(1, 255); setOption("BlackBackground", true); run("Convert to Mask"); run("Invert"); //color code shape descriptor maps shapeDescriptors=newArray("Area", "Perim.", "Feret", "Angle", "FeretAngle", "Circ.", "Round", "AR", "Solidity", "Compactness", "Extent"); mapNames=newArray("Area", "Perimeter", "Max Feret", "Angle", "Feret Angle", "Circularity", "Roundness", "Aspect Ratio", "Solidity", "Compactness", "Extent"); for(m=0; m<11; m++) { selectWindow(input); run("Duplicate...", "title=["+mapNames[m]+"]"); map=getTitle(); selectWindow(map); for(i=0; i1) { setMetadata("Label", mapNames[mask-2]); } } setSlice(1); close(input); run(LUT); setBatchMode("show"); run("Select None"); if(calibrationbar==true) { newImage("Calibration Bar", "8-bit Ramp", 256, 30, 1); run(LUT); run("RGB Color"); setForegroundColor(255, 255, 255); setBackgroundColor(0, 0, 0); run("Canvas Size...", "width=256 height=80 position=Top-Center"); setFont("SansSerif", 11, "Bold"); drawString("smallest (Area, Perimeter, AR) biggest", 5, 45); drawString("0 deg (Angle, Feret Angle) 180 deg", 5, 60); drawString("0 (Circ., Round, Solidity, Compact., Extent) 1", 5, 75); setBatchMode("show"); } //updateResults(); setBatchMode(false); if(distributionPlot==true) { leftButton=16; while(isOpen(result)) { getCursorLoc(x, y, z, clicked); wait(500); if(clicked&leftButton!=0 && isActive(currentID) && z>0) { resultEntries = nResults; selectedData = newArray(resultEntries+1); selectedData[0] = 0; for(r=0; r=min && PartAnal<=max) { setForegroundColor(255,0,255); roiManager("Fill"); positive=positive+1; PosPart=PosPart+PartAnal; } //excluded objects else if (PartAnalmax) { setForegroundColor(0,93,0); roiManager("Fill"); more=more+1; NegMore=NegMore+PartAnal; } } selectWindow("Results"); run("Close"); //result selectWindow("Output"); end=roiManager("count"); IJ.renameResults("CentroidList","Results") selectWindow("Output"); for (label=0;label1 || slices>1 || frames>1) { exit("works only with single images"); } if(type!=8) { exit("works only with 8-bit images"); } if(is("Inverting LUT")) { showMessageWithCancel("Caution inverted LUT", "The image has an inverted LUT\nLUT will be automatically inverted"); selectWindow(original); run("Invert LUT"); } run("Select None"); run("Overlay Options...", "stroke=black width=1 set"); run("Conversions...", "scale weighted"); //Threshold name definition array ThrNames = newArray("Default", "Huang", "Intermodes", "IsoData", "Li", "MaxEntropy", "Mean", "MinError", "Minimum", "Moments", "Otsu", "Percentile", "RenyiEntropy", "Shanbhag", "Triangle", "Yen", "Bernsen", "Contrast", "Mean (local)", "Median", "MidGrey", "Niblack", "Otsu (local)", "Phansalkar", "Sauvola"); //initial dialog to choose thresholds and parameters var prevWhiteObj = call("ij.Prefs.get", "threshold.check.objects", true); var prevIgnoreBlack = call("ij.Prefs.get", "threshold.check.ignoreBlack", false); var prevIgnoreWhite = call("ij.Prefs.get", "threshold.check.ignoreWhite", false); var prevIncludeLocal = call("ij.Prefs.get", "threshold.check.local", false); var prevRadius = call("ij.Prefs.get", "threshold.check.radius", 15); var prevParam1 = call("ij.Prefs.get", "threshold.check.param1", 0); var prevParam2 = call("ij.Prefs.get", "threshold.check.param2", 0); var prevQuant = call("ij.Prefs.get", "threshold.check.quant", false); var prevExtendedQuant = call("ij.Prefs.get", "threshold.check.extendedQuant", false); var prevMontage = call("ij.Prefs.get", "threshold.check.montage", false); Dialog.create("Threshold Check v2.1 by BioVoxxel"); Dialog.addCheckbox("bright objects on dark background", prevWhiteObj); Dialog.addCheckbox("ignore black (default=off)", prevIgnoreBlack); Dialog.addCheckbox("ignore white (default=off)", prevIgnoreWhite); Dialog.addMessage("_________________________________"); Dialog.addCheckbox("include local thresholds", prevIncludeLocal); Dialog.setInsets(0, 20, 0); Dialog.addNumber("Radius (default=15)", prevRadius); Dialog.setInsets(0, 20, 0); Dialog.addNumber("Parameter 1 (default=0)", prevParam1); Dialog.setInsets(0, 20, 0); Dialog.addNumber("Parameter 2 (default=0)", prevParam2); Dialog.addMessage("_________________________________"); Dialog.addCheckbox("Quantification (relative)", prevQuant); Dialog.addCheckbox("Extended quality measures", prevExtendedQuant); Dialog.addCheckbox("Test watershed-ability", false); Dialog.addCheckbox("Montage output (optional)", prevMontage); Dialog.addCheckbox("Remember current dialog settings", false); Dialog.show(); whiteObj = Dialog.getCheckbox(); ignoreBlack = Dialog.getCheckbox(); ignoreWhite = Dialog.getCheckbox(); includeLocal = Dialog.getCheckbox(); radius = Dialog.getNumber(); param1 = Dialog.getNumber(); param2 = Dialog.getNumber(); quant = Dialog.getCheckbox(); extendedQuant = Dialog.getCheckbox(); doWatershed = Dialog.getCheckbox(); montage = Dialog.getCheckbox(); settings = Dialog.getCheckbox(); if(settings==true) { call("ij.Prefs.set", "threshold.check.objects", whiteObj); call("ij.Prefs.set", "threshold.check.ignoreBlack", ignoreBlack); call("ij.Prefs.set", "threshold.check.ignoreWhite", ignoreWhite); call("ij.Prefs.set", "threshold.check.local", includeLocal); call("ij.Prefs.set", "threshold.check.radius", radius); call("ij.Prefs.set", "threshold.check.param1", param1); call("ij.Prefs.set", "threshold.check.param2", param2); call("ij.Prefs.set", "threshold.check.quant", quant); call("ij.Prefs.set", "threshold.check.extendedQuant", extendedQuant); call("ij.Prefs.set", "threshold.check.montage", montage); } if(isOpen("Results")==1) { selectWindow("Results"); run("Close"); } //Define settings for bright/dark objects if(whiteObj==true) { white = " white"; clickIntensity = "lowest"; } else { white = ""; clickIntensity = "highest"; } if(includeLocal==true) { rounds = 25; } else { rounds = 16; } if(ignoreBlack==true) { ignoreBlack = " ignore_black"; } else { ignoreBlack = ""; } if(ignoreWhite==true) { ignoreWhite = " ignore_white"; } else { ignoreWhite = ""; } saturation = 1; if(quant==true) { selectWindow(original); run("Duplicate...", "title=Sensitivity definition"); sensitivityDefinition = getTitle(); setLocation(LocX, LocY, LocW, LocH); run("Enhance Contrast...", "saturated="+saturation+" normalize"); setTool("point"); waitForUser("make 1 (!) point selection in an area\nwith the "+clickIntensity+" intensity which\nshould still be recognized by the threshold\n\nthen press Ok"); if(selectionType()!=10) { close(sensitivityDefinition); exit("need 1 point selection"); } else { getSelectionBounds(sensitivityDefinitionX, sensitivityDefinitionY, widthSel, heightSel); close(sensitivityDefinition); setTool(0); } } setBatchMode(true); //Auto Threshold selectWindow(original); run("Auto Threshold", "method=[Try all]" + ignoreBlack + ignoreWhite + white); if(isOpen("Log")==1) { selectWindow("Log"); run("Close"); } selectWindow("Montage"); run("Montage to Stack...", "images_per_row=4 images_per_column=4 border=1"); rename("ThresholdCheck_"+original); AutoThreshold = getTitle(); run("Canvas Size...", "width="+width+" height="+height+" position=Top-Left zero"); close("Montage"); selectWindow(AutoThreshold); //setBatchMode("show"); if(includeLocal==true) { //Auto Local Threshold selectWindow(original); run("Auto Local Threshold", "method=[Try all] radius=" + radius + " parameter_1=" + param1 + " parameter_2=" + param2 + white); run("Montage to Stack...", "images_per_row=3 images_per_column=3 border=1"); rename("AutoLocalThreshold"); AutoLocalThreshold = getTitle(); run("Canvas Size...", "width="+width+" height="+height+" position=Top-Left zero"); close("Montage"); run("Concatenate...", " title=[ThresholdCheck_"+original+"] image1=["+AutoThreshold+"] image2=["+AutoLocalThreshold+"] image3=[-- None --]"); //setBatchMode("show"); } ThresholdStack = getTitle(); if(doWatershed) { run("Watershed", "stack"); } //produce color coded stack selectWindow(ThresholdStack); run("Select None"); run("HiLo"); run("RGB Color"); selectWindow(original); run("Duplicate...", "title=[dup_"+original+"]"); duplicate=getTitle(); if(whiteObj==false) { run("Invert"); } run("Green"); run("Enhance Contrast...", "saturated="+saturation+" normalize"); run("Select All"); run("Copy"); setPasteMode("Add"); selectWindow(ThresholdStack); run("Select All"); for (i=1;i<=rounds;i++) { setSlice(i); run("Paste"); } if(quant==true) { //get sensitivity for over-thresholding newImage("red", "8-bit white", width, height, 1); run("Red"); run("RGB Color"); run("Select All"); run("Paste"); run("HSB Stack"); setSlice(1); makeRectangle(sensitivityDefinitionX-1, sensitivityDefinitionY-1, 3, 3); getRawStatistics(nPixels, overSensitivityDefinition); close("red"); //get sensitivity for under-thresholding newImage("blue", "8-bit white", width, height, 1); run("Blue"); run("RGB Color"); run("Select All"); run("Paste"); run("HSB Stack"); setSlice(1); makeRectangle(sensitivityDefinitionX-1, sensitivityDefinitionY-1, 3, 3); getRawStatistics(nPixels, underSensitivityDefinition); close("blue"); close(duplicate); //run the quantification function ThresholdQuant(ThresholdStack); } selectWindow(ThresholdStack); fontSize = round(height/20); if(fontSize<10) { fontSize=10; } setFont("SansSerif", fontSize, "bold"); setColor(255,255,255); for(o=0; ohighestQuality) { bestThreshold = ThrNames[runs-1]; highestQuality = quality; bestUnder = valueUnder; bestOver = valueOver; bestThresholdIndex = runs; } //updateResults(); setResult("Label", nResults, "quality ="); setResult("%Area", nResults-1, quality); //updateResults(); setResult("Label", nResults, "-----------------------------------"); setResult("%Area", nResults-1, "---------------"); updateResults(); } setResult("Label", nResults, "bright objects:"); setResult("%Area", nResults-1, whiteObj); setResult("Label", nResults, "saturation:"); setResult("%Area", nResults-1, saturation); setResult("Label", nResults, "sensitivity definition location:"); setResult("%Area", nResults-1, ""+round(sensitivityDefinitionX)+" / "+round(sensitivityDefinitionY)); setResult("Label", nResults, "hue cut-off (under):"); setResult("%Area", nResults-1, underSensitivityDefinition); setResult("Label", nResults, "hue cut-off (over):"); setResult("%Area", nResults-1, overSensitivityDefinition); setResult("Label", nResults, "------------------------------"); setResult("%Area", nResults-1, "---------------"); setResult("Label", nResults, "best thresholds:"); setResult("%Area", nResults-1, bestThreshold); for(bT=1; bT<=rounds; bT++) { testQuality = getResult("%Area", (bT*6)-2); if(testQuality == highestQuality && bT!=bestThresholdIndex) { setResult("Label", nResults, "best thresholds"); setResult("%Area", nResults-1, ThrNames[bT-1]); } } updateResults(); setResult("Label", nResults, "------------------------------"); setResult("%Area", nResults-1, "---------------"); } run("Set Measurements...", "area mean standard modal min centroid center perimeter bounding fit shape feret's integrated median skewness kurtosis area_fraction stack display redirect=None decimal=3"); } //--------------------------------------------------------------------------------------- // Flat-field background correction, jan Brocher/BioVoxxel 2013 //--------------------------------------------------------------------------------------- function FFBackgroundCorrection() { setBatchMode(true); openImages=nImages; if(openImages==0) { exit("No open images found"); } imageNames = newArray(nImages); for (i=0; i0) { run("Maximum...", "radius=" + dilation); } if(medianOffset!=0) { run("Subtract...", "value=" + medianOffset); } medianPlotWithOffset = getProfile(); imageCalculator("subtract", original, bckgr); run("Restore Selection"); finalPlot = getProfile(); close(bckgr); } Plot.create("MedSubBG_"+ original, "Distance (" + unit + ")", "Intensity", originalPlot); toUnscaled(originalPlotMax); Plot.setLimits(0, lineLength, 0, originalPlotMax); Plot.setColor("red"); Plot.add("line", medianPlot); Plot.setColor("blue"); Plot.add("line", finalPlot); if(medianOffset!=0 || dilation>0) { Plot.setColor("green"); Plot.add("line", medianPlotWithOffset); } Plot.setColor("darkGray"); Plot.show(); } else { setPasteMode("Copy"); selectWindow(original); run("Select None"); run("Duplicate...", "title=Background"); bckgr=getTitle(); setLocation(x+(width/2), y, width, height); run("Median..."); if(dilation>0) { run("Maximum...", "radius=" + dilation); } if(medianOffset > 0) { run("Subtract...", "value=" + medianOffset); } run("Restore Selection"); imageCalculator("subtract", original, bckgr); close(bckgr); } } //--------------------------------------------------------------------------------------- // Scaled Intensity Plots, by Jan Brocher // first release: v0.1, 14-02-2014 //--------------------------------------------------------------------------------------- function ScaledIntensityPlots() { original = getTitle(); type=bitDepth(); getRawStatistics(length, mean, intMin, intMax); getPixelSize(unit, pixelWidth, pixelHeight); getSelectionBounds(xSelection, ySelection, widthSelection, heightSelection); if(selectionType()==0 || selectionType()==5 || selectionType()==6 || selectionType()==7) { if(selectionType()==0) { rectSelection = "pos"; } else { rectSelection = "neg"; } if(type==8 || type==24) { initialYmax = 255; } else if(type==16) { initialYmax = 65535; } else if(type==32 && intMax > 1) { initialYmax = intMax; } else { initialYmax = 1; } openImages=nImages; plotImages=nImages; plotArray=newArray(nImages); p = 0; if(openImages==0) { exit("No open images found"); } for (i=0; i0) { imageNames = newArray(plotImages+1); imageNames[0] = "No"; for (n=1; n0) { Dialog.addChoice("add to existing plot", imageNames, "No"); } Dialog.addCheckbox("Draw grid lines", prevGridLines); Dialog.addCheckbox("reset to default values after run", false); Dialog.show(); if(rectSelection=="pos") { direction = Dialog.getRadioButton(); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevDirection", direction); } windowWidth = Dialog.getNumber(); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevWidth", windowWidth); windowHeight = Dialog.getNumber(); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevHeight", windowHeight); yMin = Dialog.getNumber(); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevMinLimit", yMin); yMax = Dialog.getNumber(); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevMaxLimit", yMax); color = Dialog.getChoice(); look = Dialog.getChoice(); if(plotImages>0) { addToExistingPlot = Dialog.getChoice(); } grid = Dialog.getCheckbox(); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevGridLines", grid); default = Dialog.getCheckbox(); if(default==true) { call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevDirection", "horizontal"); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevWidth", 450); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevHeight", 200); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevMinLimit", 0); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevMaxLimit", initialYmax); call("ij.Prefs.set", "BVTB.scaledIntensityPlots.prevGridLines", true); } if(grid==true) { setGrid = "draw "; } else { setGrid = ""; } if(rectSelection=="pos") { if(direction=="horizontal") { selectWindow(original); intensityValues = getProfile(); } else if(direction=="vertical") { selectWindow(original); setKeyDown("alt"); intensityValues = getProfile(); setKeyDown("none"); } } else { selectWindow(original); intensityValues = getProfile(); } if(plotImages>0) { if(addToExistingPlot!="No") { selectWindow(addToExistingPlot); Plot.getValues(existingX, existingY); Array.getStatistics(existingX, existingMin, existingMax); metadata = getMetadata("Info"); if(metadata=="") { exit("destination plot was not created\nwith scaled intensity plots tool.\nnecessary metadata not existing"); } else if(substring(metadata, 6, 7)=="1") { setGrid = "draw"; } else if(substring(metadata, 6, 7)=="0") { setGrid = ""; } } else { existingMax = 5000000000; } } else { existingMax = 5000000000; } run("Profile Plot Options...", "width="+windowWidth+" height="+windowHeight+" minimum=0 maximum=0 fixed interpolate "+setGrid+" sub-pixel"); if(plotImages==0) { Plot.create("Plot of "+original, "Distance (pixel)", "Intensity"); } else if(plotImages>0 && addToExistingPlot=="No") { addSuffix = 0; for(n=0; n<=plotImages; n++) { if(imageNames[n]=="Plot of "+original) { addSuffix = addSuffix + 1; } for(epn=0; epn<=plotImages; epn++) { if(endsWith(imageNames[n], addSuffix)==true) { addSuffix = addSuffix + 1; } } } newPlotName = "Plot of "+original+"-"+addSuffix; Plot.create(newPlotName, "Distance (pixel)", "Intensity"); } else { Plot.create("TransientPlot", "", ""); } if(rectSelection=="neg") { if(length>existingMax && addToExistingPlot!="No") { length = existingMax+1; } Plot.setLimits(0, length, yMin, yMax); } else if(rectSelection=="pos" && direction=="horizontal") { if(widthSelection>existingMax && addToExistingPlot!="No") { widthSelection = existingMax+1; } Plot.setLimits(0, widthSelection, yMin, yMax); } else if(rectSelection=="pos" && direction=="vertical") { if(heightSelection>existingMax && addToExistingPlot!="No") { heightSelection = existingMax+1; } Plot.setLimits(0, heightSelection, yMin, yMax); } Plot.setFrameSize(windowWidth, windowHeight); Plot.setColor(color); Plot.add(look, intensityValues); Plot.show(); currentPlot = getTitle(); //set plot metadata setMetadata("Info", "grid: "+grid+"\nwindow_width: "+windowWidth+"\nwindow_height: "+windowHeight+"\nmin. int. limit: "+yMin+"\nmax. int. limit: "+yMax); if(addToExistingPlot!="No") { selectWindow(currentPlot); run("Select All"); run("Copy"); run("Select None"); selectWindow(addToExistingPlot); run("RGB Color"); setPasteMode("Transparent-white"); run("Select All"); run("Paste"); run("Select None"); setPasteMode("Copy"); close(currentPlot); } } else { exit("line or rectangular selection needed"); } } /** * Stack Line Plots, developed by Jan Brocher/BioVoxxel 2014 * v0.1 first release (05-03-14) * **/ function StackLinePlots() { if(isKeyDown("shift")) { alt= true; } else { alt = false; } setBatchMode(true); original = getTitle(); getLocationAndSize(x, y, width, height); type = bitDepth(); if(type>16) { exit("works only with 8- and 16-bit images"); } getDimensions(width, height, channels, slices, frames); if(slices>1 && frames>1) { Dialog.create("Multi plot setup"); Dialog.addChoice("select dimension", newArray("slices", "frames"), "slices"); Dialog.show(); dim = Dialog.getChoice(); if(dim=="slices") { dimension = slices; } else { dimension = frames; } } else if(slices>1 && frames<2) { dimension = slices; dim = "slices"; } else if(slices<2 && frames>1) { dimension = frames; dim = "frames"; } if(slices<2) { exit("Stack needed"); } selection = Roi.getType; if(selection!="freeline" && selection!="line" && selection!="polyline") { exit("line selection needed"); } getSelectionCoordinates(xpoints, ypoints); toUnscaled(xpoints, ypoints); yValues = newArray(xpoints.length); selectWindow(original); setBatchMode("Hide"); if(alt==false) { yMax=0; for(s=1; s<=dimension; s++) { if(dim=="slices") { Stack.setSlice(s); } else { Stack.setFrame(s); } yValues = getProfile(); Array.getStatistics(yValues, min, max, mean, stdDev); if(max>yMax) { yMax=max; } } } else if(alt==true) { yMax = pow(2, type) - 1; } for(s=1; s<=dimension; s++) { selectWindow(original); if(dim=="slices") { Stack.setSlice(s); } else { Stack.setFrame(s); } yValues = getProfile(); Plot.create("Plot of " + original, "line length", "pixel intensity", yValues); Plot.setLimits(0, yValues.length, 0, yMax); Plot.show(); } run("Images to Stack", "name=[PlotStack_"+original+"] title=[Plot of] use"); setBatchMode("exit and display"); selectWindow(original); setLocation(x, y); } /* //------------------------------------------------------------------------------------------------------------------------------------- // Contrast Detection, developed by Jan Brocher/BioVoxxel 2013 // deprecated //------------------------------------------------------------------------------------------------------------------------------------- function ContrastDetection() { if(isOpen("Log")==1) { selectWindow("Log"); run("Close"); } setPasteMode("Copy"); original=getTitle(); getDimensions(width, height, channels, slices, frames); type=bitDepth(); if(slices>1) { exit("works only with individual images so far"); } Dialog.create("Contrast Setup"); Dialog.addNumber("radius", 1); Dialog.addCheckbox("enhance edges in original", false); Dialog.addCheckbox("enhance contrast", true); Dialog.addNumber("contrast saturation", 1); Dialog.addCheckbox("final maxima filter", false); Dialog.addCheckbox("inverse", false); Dialog.show(); r=Dialog.getNumber(); sharpen=Dialog.getCheckbox(); contrast=Dialog.getCheckbox(); satur=Dialog.getNumber(); finalFilter=Dialog.getCheckbox(); inverse=Dialog.getCheckbox(); setBatchMode(true); run("Duplicate...", "title=Minimum"); run("Conversions...", "scale weighted"); if(type==24) { run("8-bit"); } Minimum=getTitle(); run("Duplicate...", "title=Maximum"); if(type==24) { run("8-bit"); } Maximum=getTitle(); selectWindow(Minimum); run("Minimum...", "radius=r"); selectWindow(Maximum); run("Maximum...", "radius=r"); setPasteMode("Difference"); selectWindow(original); run("Select All"); run("Copy"); selectWindow(Minimum); run("Paste"); selectWindow(Maximum); run("Paste"); setPasteMode("Subtract"); if(inverse==true || sharpen==true) { selectWindow(Minimum); } else { selectWindow(Maximum); } run("Select All"); run("Copy"); if(inverse==true || sharpen==true) { selectWindow(Maximum); rename(original + "_Minima_r("+r+")"); } else { selectWindow(Minimum); rename(original + "_Maxima_r("+r+")"); } resultWindow=getTitle(); run("Paste"); if(sharpen==true) { selectWindow(resultWindow); run("Select All"); run("Copy"); selectWindow(original); run("Duplicate...", "title=Enhanced_"+original); run("Select All"); run("Paste"); } if(contrast==true && sharpen==false) { selectWindow(resultWindow); run("Enhance Contrast...", "saturated=satur normalize"); } if(finalFilter==true) { run("Minimum...", "radius=0.5"); } setBatchMode(false); } */ //----------------------------------------------------------------------------------------------------------------------------------------- //Hyperstack Color-coding //Based on the idea of the temporal color coding from the macro of Kota Miura and Johannes Schindelin //Offers the choice to code time or volume in a hyperstack //Keeps the color coded Hyperstack in addition to a color coded Z-projection stack. Z-Projection type can be selected //Author: Jan Brocher/BioVoxxel, 2013 //Version: 0.1 (25/04/2013) //----------------------------------------------------------------------------------------------------------------------------------------- function HyperstackColorCoding() { //read input original=getTitle(); type=Stack.isHyperstack; BitDepth=bitDepth(); run("Select None"); if(isOpen("Log")==1) { selectWindow("Log"); run("Close"); } if (BitDepth!=8) { exit("works only with 8-bit images"); } getLut(r, g, b); getDimensions(width, height, channels, slices, frames); if(channels>1) { exit("does not work with multi-channel stacks"); } setPasteMode("Copy"); //Setup dialog Dialog.create("Dimension Choice"); if(type==true) { Dialog.addChoice("Color code", newArray("Time", "Volume"), "Time"); } else if (slices==1) { Dialog.addChoice("Color code", newArray("Time")); } else if (frames==1) { Dialog.addChoice("Color code", newArray("Volume")); } Dialog.addChoice("LUT", newArray("Spectrum", "Rainbow RGB", "Fire", "Ice", "16_colors", "cool", "Green Fire Blue"), "Spectrum"); if(slices>1) { Dialog.addCheckbox("Z-Projection", true); Dialog.addChoice("Projection type", newArray("Average Intensity", "Max Intensity", "Min Intensity", "Sum Slices", "Standard Deviation", "Median"), "Max Intensity"); Dialog.addCheckbox("All time frames", true); } Dialog.addCheckbox("Calibration bar", false); Dialog.show(); Dimension=Dialog.getChoice(); LUT=Dialog.getChoice(); if(slices>1) { ZProject=Dialog.getCheckbox(); ProjectType=Dialog.getChoice(); ProjectionFrames=Dialog.getCheckbox(); } else { ZProject=false; } CalBar=Dialog.getCheckbox(); //creation of output stack run("Hyperstack...", "title=Colored_"+Dimension+"_"+original+" type=RGB display=Composite width="+width+" height="+height+" channels="+channels+" slices="+slices+" frames="+frames); output=getTitle(); selectWindow(original); run(LUT); getLut(Oreds, Ogreens, Oblues); //calling the color coding function ColorCoding(); if (CalBar==true) { CalibrationBar(); } exit(); function ColorCoding() { if (Dimension=="Time") { n=frames; runs=slices; } else if (Dimension=="Volume") { n=slices; runs=frames; } reds=newArray(256); greens=newArray(256); blues=newArray(256); setBatchMode(true); for (hyper=1; hyper<=runs; hyper++) { for (i=1; i<=n; i++) { if (Dimension=="Time") { Stack.setSlice(hyper); Stack.setFrame(i); } else if (Dimension=="Volume") { Stack.setFrame(hyper); Stack.setSlice(i); } color=floor((255/n)*i); for (loop=0; loop<256; loop++) { f=(loop/255); reds[loop]=round(Oreds[color]*f); greens[loop]=round(Ogreens[color]*f); blues[loop]=round(Oblues[color]*f); } selectWindow(original); if (Dimension=="Time") { Stack.setSlice(hyper); Stack.setFrame(i); } else if (Dimension=="Volume") { Stack.setFrame(hyper); Stack.setSlice(i); } setLut(reds, greens, blues); run("Select All"); run("Copy"); selectWindow(output); if (Dimension=="Time") { Stack.setSlice(hyper); Stack.setFrame(i); } else if (Dimension=="Volume") { Stack.setFrame(hyper); Stack.setSlice(i); } run("Paste"); } } Stack.setFrame(1); Stack.setSlice(1); if (ZProject==true) { selectWindow(output); if(ProjectionFrames==true) { run("Z Project...", "start=1 stop="+slices+" projection=["+ProjectType+"] all"); } else { run("Z Project...", "start=1 stop="+slices+" projection=["+ProjectType+"]"); } } setBatchMode(false); selectWindow(original); setLut(r, g, b); Stack.setFrame(1); Stack.setSlice(1); } function CalibrationBar() { if (Dimension=="Time") { n=frames; } else if (Dimension=="Volume") { n=slices; } newImage("Calibration Bar", "8-bit Ramp", 256, 35, 1); run(LUT); setBackgroundColor(255, 255, 255); run("RGB Color"); run("Canvas Size...", "width=256 height=50 position=Top-Center"); setFont("SansSerif", 12, "bold"); setColor(0, 0, 0); if (Dimension=="Time") { drawString("1", 2, 49); if(n<100) { drawString(n, 240, 49); } else { drawString(n, 230, 49); } } else if (Dimension=="Volume") { run("Rotate 90 Degrees Right"); drawString("1", 1, 13); drawString(n, 1, 255); } } } //----------------------------------------------------------------------------------------------------------------------------------------- // Neighbor Analysis // Gives a color coded output regarding the number of neighbors of each particle in a binary image // Author: Jan Brocher/BioVoxxel, 2013 // Version: 0.4 (31/01/2014) // version: 0.5 (04/04/2014) Thanks to Gabriel Landini improved time performance using the floodFill command // version: 0.6 (02/11/2016) thanks to Dennis Defoe, edge particles can be visually eliminated but still be included in the analysis as neighbors //----------------------------------------------------------------------------------------------------------------------------------------- function NeighborAnalysis() { original=getTitle(); type=is("binary"); if(type==false) { exit("works only with 8-bit binary images"); } getDimensions(width, height, channels, slices, frames); run("Options...", "iterations=1 count=1 black edm=Overwrite do=Nothing"); if(isOpen("Log")==1) { selectWindow("Log"); run("Close"); } //Setup Dialog.create("Analysis Setup"); Dialog.addChoice("Particle color", newArray("white", "black"), "white"); Dialog.addChoice("Analysis method", newArray("Voronoi", "UEP Voronoi", "Centroid Neighborhood", "Particle Neighborhood"), "Voronoi"); Dialog.addNumber("Neighborhood radius (pixel)", 0); Dialog.addCheckbox("do watershed first", false); Dialog.addString("Size (pixel^2)", "0-Infinity"); Dialog.addString("Circularity", "0.00-1.00"); Dialog.addCheckbox("visually exclude edge particles", false); Dialog.addCheckbox("exclude edge particles", false); Dialog.addCheckbox("produce calibration bar", true); Dialog.addCheckbox("plot neighbor distribution", true); Dialog.addHelp("www.biovoxxel.de/macros.html"); Dialog.show(); color=Dialog.getChoice(); method=Dialog.getChoice(); hoodRadius=Dialog.getNumber(); watershed=Dialog.getCheckbox(); size=Dialog.getString(); circularity=Dialog.getString(); dontVisualizeEdges=Dialog.getCheckbox(); excludeEdges=Dialog.getCheckbox(); calibrationbar=Dialog.getCheckbox(); createPlot=Dialog.getCheckbox(); selectWindow(original); run("Select None"); if(color=="black") { run("Invert"); } if(excludeEdges==true) { edges="exclude"; } else { edges=""; } //prepare original image for analysis run("Analyze Particles...", "size="+size+" circularity="+circularity+" show=Masks "+edges+" clear"); run("Invert LUT"); rename(original+"-1"); original=getTitle(); //******************************************************************* setBatchMode(true); if(method=="Voronoi") { run("Duplicate...", "title=[V-Map_"+original+"]"); voronoi=getTitle(); } else if(method=="UEP Voronoi") { run("Duplicate...", "title=[UEP-V-Map_"+original+"]"); voronoi=getTitle(); } else if(method=="Centroid Neighborhood" || method=="Particle Neighborhood") { run("Duplicate...", "title=[NbHood_"+original+"]"); neighborhood=getTitle(); } //initial particle watershed if activated if(watershed==true) { run("Watershed"); } //if method==Voronoi if(method=="Voronoi") { //Analyze voronoi particle number selectWindow(voronoi); run("Set Measurements...", " centroid redirect=None decimal=3"); run("Analyze Particles...", "size=0-Infinity circularity=0.00-1.00 show=Nothing clear record"); //define variables initialParticles=nResults; X=newArray(nResults); Y=newArray(nResults); neighborArray=newArray(nResults); neighbors=0; mostNeighbors=0; //run voronoi run("Voronoi"); setThreshold(1, 255); setOption("BlackBackground", true); run("Convert to Mask"); run("Invert"); //retveive particle coordinates for(l=0; lmostNeighbors) { mostNeighbors=neighbors; } } } if(method=="UEP Voronoi") { //create ultimate points selectWindow(voronoi); run("Ultimate Points"); setThreshold(1, 255); setOption("BlackBackground", true); run("Convert to Mask"); //analyze UEP number run("Set Measurements...", " centroid redirect=None decimal=3"); run("Analyze Particles...", "size=0-Infinity circularity=0.00-1.00 show=Nothing clear record"); //define variables initialParticles=nResults; X=newArray(nResults); Y=newArray(nResults); neighborArray=newArray(nResults); neighbors=0; mostNeighbors=0; //run voronoi run("Voronoi"); setThreshold(1, 255); setOption("BlackBackground", true); run("Convert to Mask"); run("Invert"); //retveive particle coordinates for(l=0; lmostNeighbors) { mostNeighbors=neighbors; } } } //if method==centroid neighborhood if(method=="Centroid Neighborhood") { selectWindow(neighborhood); run("Set Measurements...", " centroid redirect=None decimal=3"); run("Analyze Particles...", "size=0-Infinity circularity=0.00-1.00 show=Nothing clear record"); //define variables initialParticles=nResults; X=newArray(nResults); Y=newArray(nResults); neighborArray=newArray(nResults); neighbors=0; mostNeighbors=0; //retveive particle coordinates for(l=0; lmostNeighbors) { mostNeighbors=neighbors; } close(selector); } } //if method==particle neighborhood if(method=="Particle Neighborhood") { selectWindow(neighborhood); run("Set Measurements...", " centroid redirect=None decimal=3"); run("Analyze Particles...", "size=0-Infinity circularity=0.00-1.00 show=Nothing clear record"); //define variables initialParticles=nResults; X=newArray(nResults); Y=newArray(nResults); neighborArray=newArray(nResults); neighbors=0; mostNeighbors=0; //retveive particle coordinates for(l=0; lmostNeighbors) { mostNeighbors=neighbors; } close(selector); } } if(mostNeighbors==0) { exit("no neighbors detected\ndid you choose the correct particle color?"); } //******************************************************************* //Color coded original features selectWindow(original); if(method=="Voronoi") { run("Duplicate...", "title=[Voronoi_"+original+"]"); } else if(method=="UEP Voronoi") { run("Duplicate...", "title=[UEP-V_"+original+"]"); } else if(method=="Centroid Neighborhood") { run("Duplicate...", "title=[C-NbHood_"+hoodRadius+"_"+original+"]"); } else if(method=="Particle Neighborhood") { run("Duplicate...", "title=[P-NbHood_"+hoodRadius+"_"+original+"]"); } particles=getTitle(); if(watershed==true) { run("Watershed"); } selectWindow(particles); for(mark=0; mark0) { neighborList[nextNeighbor] = neighborList[nextNeighbor] + 1; } } particleCount = initialParticles; } Plot.create("Distribution: " + particles, "neighbors", "count", neighborList); Plot.addText("particles (total) = " + particleCount, 0.01, 0.1); setBatchMode("show"); } close(original); //Calibration Bar if(calibrationbar==true) { stepsize=floor(256/mostNeighbors); newImage("Calibration_"+original, "8-bit Black", (stepsize*mostNeighbors), 30, 1); w=getWidth(); step=0; for(c=0; c<=mostNeighbors; c++) { makeRectangle(step, 0, step+stepsize, 30); setForegroundColor(c+1, c+1, c+1); run("Fill"); step=step+stepsize; } run("Select None"); run("glasbey"); run("RGB Color"); setForegroundColor(255, 255, 255); setBackgroundColor(0, 0, 0); run("Canvas Size...", "width="+w+" height=50 position=Top-Center"); if(mostNeighbors>9) { offset=15; } else { offset=10; } drawString("1", 2, 48); drawString(mostNeighbors, w-offset, 48); } setBatchMode(false); exit(); } //----------------------------------------------------------------------------------------------------------------------------------------- /* function ParticleDistribution2D() { original = getTitle(); getSelectionBounds(xPos, yPos, width, height); run("Options...", "iterations=1 count=1 black edm=Overwrite"); run("Set Measurements...", "area mean standard modal min centroid center perimeter bounding fit shape feret's integrated median skewness kurtosis area_fraction redirect=None decimal=3"); Dialog.create("Setup"); Dialog.addString("Size:", "0-Infinity"); Dialog.addString("Circularity:", "0.00-1.00"); Dialog.addCheckbox("include holes", false); Dialog.addCheckbox("exclude edges", false); Dialog.addCheckbox("show ultimate points", false); Dialog.addRadioButtonGroup("evaluate by", newArray("mean", "median"), 1, 2, "median"); Dialog.addRadioButtonGroup("conficence interval (CI)", newArray("95%", "99%", "99.9%"), 1, 3, "95%"); Dialog.show(); size = Dialog.getString(); circ = Dialog.getString(); holes = Dialog.getCheckbox(); edges = Dialog.getCheckbox(); uep = Dialog.getCheckbox(); take = Dialog.getRadioButton(); confidence = Dialog.getRadioButton(); if(holes==true) { hole = "include "; } else { hole = ""; } if(edges==true) { edge = "exclude "; } else { edge = ""; } if(uep==true) { output = "Masks "; } else { output = "Nothing "; } //determination of critical F- and t-values if(confidence=="95%") { criticalF = newArray(2.978237016, 1.840871688, 1.53431418, 1.391719552, 1.158655374, 1.109688288, 1.076352036, 1.061912029, 1.053397886, 1.047627319); criticalT = newArray(1.812461102, 1.697260851, 1.670648865, 1.660234327, 1.647906854, 1.646378818, 1.645615867, 1.645361708, 1.645234659, 1.645158438); pListed = 0.05; } else if(confidence=="99%") { criticalF = newArray(4.849146802, 2.385967353, 1.836259361, 1.597669125, 1.231664935, 1.158625448, 1.109682472, 1.088680123, 1.076352997, 1.068021936); criticalT = newArray(2.763769458, 2.457261531, 2.390119457, 2.364217356, 2.333828914, 2.330082625, 2.328213787, 2.327591515, 2.32728048, 2.327093897); pListed = 0.01; } else if(confidence=="99.9%") { criticalF = newArray(8.753866276, 3.217090322, 2.252265545, 1.867401382, 1.319136791, 1.216098723, 1.148287469, 1.1194961, 1.102684079, 1.091358502); criticalT = newArray(4.143700493, 3.385184866, 3.231709121, 3.173739481, 3.106611618, 3.098402156, 3.09431229, 3.092951196, 3.092271061, 3.091863111); pListed = 0.001; } //particle analysis run("Analyze Particles...", "size="+size+" circularity="+circ+" show="+output+""+edge+"clear "+hole+"record"); if(uep==true) { run("Invert LUT"); run("Ultimate Points"); setThreshold(1, 255); setOption("BlackBackground", true); run("Convert to Mask"); UEP = getTitle(); } particles = nResults; area = width * height; randomPart = 0.5 * sqrt(area/particles); stdDevRandom = sqrt(randomPart); print("Theoretical random nearest neighbor distance = "+randomPart); print("Variance = "+randomPart); print("StdDev = "+stdDevRandom); x = newArray(particles); y = newArray(particles); for(c=0; c0) { if (dist[count]=11 && particles<31 && F>=criticalF[0]) || (particles>=31 && particles<61 && F>=criticalF[1]) || (particles>=61 && particles<101 && F>=criticalF[2]) || (particles>=101 && particles<501 && F>=criticalF[3]) || (particles>=501 && particles<1001 && F>=criticalF[4]) || (particles>=1001 && particles<2001 && F>=criticalF[5]) || (particles>=2001 && particles<3001 && F>=criticalF[6]) || (particles>=3001 && particles<4001 && F>=criticalF[7]) || (particles>=4001 && particles<5001 && F>=criticalF[8]) || (particles>=5001 && F>=criticalF[9])) { //Welch Test Tvalue = abs(randomPart-testValue) / (sqrt((randomPart/particles) + (variance/particles))); df = floor((pow(((randomPart/particles) + (variance/particles)),2)) / ((pow((randomPart/particles),2)/(particles-1)) + (pow((variance/particles),2)/(particles-1)))); print("d.f. = " + df); print("t = " + Tvalue + " (Welch's t-test)"); } else { //Student's t-Test Tvalue = (abs(randomPart-testValue)) / (sqrt(0.5*(randomPart+variance)) * sqrt(2/particles)); df = (2*particles) - 2; print("d.f.: " + df); print("t = " + Tvalue + " (Student's t-test)"); } //critical t-values for alpha=0.01 (two-tailed) if(df>=10 && df<30) { criticalTValue=criticalT[0]; } else if(df>=30 && df<60) { criticalTValue=criticalT[1]; } else if(df>=60 && df<100) { criticalTValue=criticalT[2]; } else if(df>=100 && df<500) { criticalTValue=criticalT[3]; } else if(df>=500 && df<1000) { criticalTValue=criticalT[4]; } else if(df>=1000 && df<2000) { criticalTValue=criticalT[5]; } else if(df>=2000 && df<3000) { criticalTValue=criticalT[6]; } else if(df>=3000 && df<4000) { criticalTValue=criticalT[7]; } else if(df>=4000 && df<5000) { criticalTValue=criticalT[8]; } else if(df>=5000) { criticalTValue=criticalT[9]; } print("critical t-value = " + criticalTValue); print("confidence interval = " + confidence); print("--------------------------------------------------------------------------"); if(Tvalue >= criticalTValue) { if(testValue < randomPart) { print(" ---> clustering particles"); } else if(testValue > randomPart) { print(" ---> self-avoiding particles"); } print("significant different from random distribution with p < " + pListed); } else { print(" ---> random particle distribution"); print("no significant difference to random distribution (p > "+pListed+")"); } print("according to " + take + " nearest neighbor distance"); print("--------------------------------------------------------------------------"); } */ //----------------------------------------------------------------------------------------------------------------------------------------- // Cluster Finder, Jan Brocher/BioVoxxel 2014 // v0.1 first release // v0.2 detection methods changed (UEP and voronoi distance based) (04-03-14) //----------------------------------------------------------------------------------------------------------------------------------------- function ClusterIndicator() { original = getTitle(); run("Remove Overlay"); if(is("binary")==false) { exit("works only on 8-bit binary images"); } run("Select None"); getDimensions(width, height, channels, slices, frames); run("Overlay Options...", "stroke=blue width=1 fill=none set"); run("Set Measurements...", "area centroid center bounding area_fraction redirect=None decimal=3"); Dialog.create("Cluster Finder"); Dialog.addNumber("estimated cluster diameter (pixel)", 50); Dialog.addNumber("density (x-fold of total image)", 2); Dialog.addNumber("max. iterations", 25); Dialog.addRadioButtonGroup("method", newArray("average ND", "UEP NND"), 1, 2, "average ND"); Dialog.addCheckbox("fuse center-cluster overlaps", true); Dialog.addCheckbox("show ROI manager", false); Dialog.addCheckbox("show terminated iterations", false); Dialog.addCheckbox("show calculation image", false); Dialog.show(); clusterSize = Dialog.getNumber(); clusterRadius = clusterSize/2; density = Dialog.getNumber(); maxIterations = Dialog.getNumber(); method = Dialog.getRadioButton(); showOverlap = Dialog.getCheckbox(); manager = Dialog.getCheckbox(); termIterations = Dialog.getCheckbox(); showCalcImg = Dialog.getCheckbox(); if(manager==true) { roiManager("reset"); setBatchMode(true); } else { setBatchMode(true); roiManager("reset"); } selectWindow(original); run("Analyze Particles...", "size=0-Infinity circularity=0.00-1.00 show=Nothing clear record"); //individualArea = newArray(nResults); u = newArray(nResults); v = newArray(nResults); if(method=="UEP NND") { //create intensity coded ultimate point distances = newArray(nResults*nResults); NND = newArray(nResults); count = 0; for(a=0; a distances[count]) { NND[a] = distances[count]; } } count++; } } countLast = 0; for(b=0; b distances[countLast]) { NND[nResults-1] = distances[countLast]; } countLast++; } newImage(original+"-UEP_NND", "32-bit black", width, height, 1); evaluation = getTitle(); selectWindow(evaluation); for(norm=0; norm= (limit*density))) { sumClusterDensity = sumClusterDensity + localValue; roiManager("add"); //print("in: "+X+"("+xClusterPos[counter]+")/("+yClusterPos[counter]+")"+Y+" - counter: "+ counter); //control output xClusterPos[counter] = X; yClusterPos[counter] = Y; Xold = X; Yold = Y; counter = counter + 1; } else if(addToManager==1 && (localValue < (limit*density))) { excluded = excluded + 1; //print("excluded: "+X+"/"+Y); //control output } i=maxIterations; List.clear(); } else { nX = XM; nY = YM; Xold = X; Yold = Y; //print(nY+" / "+X); //control output makeOval((nX-clusterRadius), (nY-clusterRadius), clusterSize, clusterSize); i++; if(i==maxIterations) { terminatedIterations = terminatedIterations + 1; if(termIterations==true) { selectWindow(original); makeOval((nX-clusterRadius), (nY-clusterRadius), clusterSize, clusterSize); run("Add Selection..."); selectWindow(evaluation); } } } } } } fusion = 0; count = roiManager("count"); if(showOverlap==true) { showStatus("Cluster fusion"); selectWindow(original); for(point=0; point "+(totalBrightness*density)+" %) ("+((100*count)/totalCount)+" %)"); //print("average density: " + sumClusterDensity/count + " % or ROI area"); print("--------------------------------------------------"); print(excluded + " clusters excluded due to low density ("+((100*excluded)/totalCount) + " %)"); print(duplicatedDetection + " duplicate clusters ("+((100*duplicatedDetection)/totalCount) + " %)"); print(fusion + " ROIs fused due to overlap ("+((100*fusion)/totalCount) + " %)"); print(terminatedIterations + " terminated iterations ("+((100*terminatedIterations)/totalCount) + " %) (blue ROIs)"); print("_____________________________________________"); run("Options...", "iterations=1 count=1 black edm=8-bit do=Nothing"); run("Set Measurements...", "area mean standard modal min centroid center perimeter bounding fit shape feret's integrated median skewness kurtosis area_fraction stack display redirect=None decimal=3"); setBatchMode(false); showStatus("Done"); exit(); } //----------------------------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------------------------- function CorrectedSkeletonLength() { setOption("BlackBackground", true); original = getTitle(); if (is("binary")==false) { exit("8-bit binary image necessary"); } //setup dialog Dialog.create("Setup"); Dialog.addString("Size:", "0-Infinity"); Dialog.addString("Circularity:", "0.00-1.00"); Dialog.addChoice("Show", newArray("Nothing", "Outlines", "Bare Outlines", "Ellipses", "Masks", "Count Masks", "Overlay Outlines", "Overlay Masks"), "Nothing"); Dialog.addCheckbox("clear results", false); Dialog.addCheckbox("include holes", false); Dialog.addCheckbox("exclude edges", false); Dialog.addCheckbox("mininmal results", true); Dialog.show(); size = Dialog.getString(); circ = Dialog.getString(); show = Dialog.getChoice(); clear = Dialog.getCheckbox(); holes = Dialog.getCheckbox(); edges = Dialog.getCheckbox(); display = Dialog.getCheckbox(); if(clear==true) { clear = "clear "; } else { clear = ""; } if(holes==true) { hole = "include "; } else { hole = ""; } if(edges==true) { edge = "exclude "; } else { edge = ""; } setBatchMode(true); //create distance map of particles selectWindow(original); run("Duplicate...", "title=distance"); distance = getTitle(); run("Distance Map"); //create particle skeleton selectWindow(original); run("Duplicate...", "title=skeleton"); skeleton = getTitle(); run("Skeletonize"); //create endpoint erosded skeleton run("Duplicate...", "title=eroded"); eroded = getTitle(); run("Options...", "iterations=1 count=7 black edm=Overwrite do=Erode"); //create binary endpoint image run("Calculator Plus", "i1="+skeleton+" i2="+eroded+" operation=[Subtract: i2 = (i1-i2) x k1 + k2] k1=1 k2=0 create"); endpoints = getTitle(); //create image with endpoint intensities run("Select All"); run("Copy"); selectWindow(distance); run("Select All"); setPasteMode("Transparent-white"); run("Paste"); run("Select None"); correction = getTitle(); //results display mode and redirect to the endpoint intensity image if(display==true) { run("Set Measurements...", "area centroid integrated redirect=["+correction+"] decimal=3"); } else { run("Set Measurements...", "area mean standard modal min centroid center perimeter bounding fit shape feret's integrated median skewness kurtosis area_fraction redirect=["+correction+"] decimal=3"); } //analysis selectWindow(skeleton); run("Analyze Particles...", "size="+size+" circularity="+circ+" show=["+show+"] display " + edge + clear + hole +" record"); setBatchMode("show"); //correct the length by addition of skeleton area to endpoint intensities for(n=0; n