// Creates stack projections for subgroups // and saves them to disk. macro "Grouped Projections Batch" { // Parameters extension = ".BTF"; method="Max Intensity"; //one of Max Intensity", "Min Intensity","Median","Average Intensity","Standard Deviation" subStackSize = 300; overlap = 10; // Get user input if requiered inargs = getArgument(); if (inargs=="") { //Display dialog and ask for paths inputDir = getDirectory("Input directory"); outputDir = getDirectory("Output directory"); } else { //Parse input and output paths from argumet string paths = split(files," "); inputDir = paths[1]: outputDir = paths[2]; } processFolder(inputDir); // Process all files and recurse into subdirs function processFolder(input) { list = getFileList(input); for (i = 0; i < list.length; i++) { if(File.isDirectory(input + list[i])) processFolder("" + input + list[i]); if(endsWith(list[i], extension)) processFile(input+ list[i], outputDir); } } // Single file projections function processFile(inputFile,basePath) { // open input input file run("Bio-Formats Importer", "open="+inputFile+" color_mode=Default rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT use_virtual_stack"); inputID = getImageID(); // Input checking if (nSlices() == 1) {exit("This macro only operates on stacks.")}; if (overlap >= subStackSize) {error("Overlap must be smaller than size of substack");} //Check if sub stack will fit in memory maxMem = parseInt(IJ.maxMemory()); stackMem = getWidth()*getHeight()*bitDepth()/8*subStackSize; if (stackMem > maxMem) { exit("Substack is too large for available memory"); } //FIXME calculate iMax correctly for non zero overlaps iMax = floor(nSlices()/subStackSize)+1; methodPrefix = replace(method,' ','-'); resultName = methodPrefix; inputInfo = getImageInfo; inputName = getInfo("image.filename"); dotIndex = lastIndexOf(inputName, "."); if (dotIndex >= 0) { inputName = substring(inputName, 0, dotIndex); } progressTitle = "[Progress]"; run("Text Window...", "name="+ progressTitle +" width=30 height=3 monospaced"); print(progressTitle,"\\Update:0/"+iMax+" substacks (0%)\n"+getBar(0, 100)); print("Calculating the grouped "+method+" projection for\n"+inputFile+"..."); setBatchMode(true); tStart = getTime(); for (i=0; i<iMax; i++) { print(progressTitle,"\\Update:"+i+"/"+iMax+" substacks ("+round(i/iMax*100)+"%)\n"+getBar(i, 100)); start=i*subStackSize+1; stop=start+subStackSize+overlap; if (stop > nSlices()) { stop=nSlices(); i = iMax+1; } sliceName = methodPrefix+"_"+IJ.pad(start,5)+"-"+IJ.pad(stop,5); calculateProjection(start,stop,"SubStack",method); rename(sliceName); if (i>1) { addSlice(resultName,resultName,getTitle()); selectImage(resultName); setSlice(nSlices); setMetadata("Label", sliceName); } else if (i==1) { addSlice(resultName,slice1,sliceName); selectImage(resultName); setSlice(1); setMetadata("Label", slice1); setSlice(2); setMetadata("Label", sliceName); setMetadata("Info", inputInfo); } else if (i==0) { slice1=getTitle(); } selectImage("SubStack"); close(); selectImage(inputID); } selectImage(resultName); setSlice(1); run("Enhance Contrast...", "saturated=0.4 process_all"); if (saveToDisk) { saveAs("Tiff",basePath+inputName+"_"+resultName+"-grouped"); } close(); close(inputID); setBatchMode(false); tStop = getTime(); walltime = (tStop-tStart)/1000/60; print("Done! (took "+d2s(walltime,1)+" min to process "+i+" substacks."); print(progressTitle, "\\Close"); //Subfunctions function calculateProjection(iStart,iStop,resultTitle,method) { run("Duplicate...", "title="+resultTitle+" duplicate range="+iStart+"-"+iStop); if (nSlices>1) { run("Z Project...", "start=1 stop="+(iStop-iStart+1)+" projection=["+method+"]"); } } //add projection in2 to existing result stack in2 function addSlice(resultTitle,in1,in2) { run("Concatenate...", " title=["+resultTitle+"] image1="+in1+" image2="+in2); showStatus("Grouped Stack Proj. ("+i+"/"+iMax+"):"); showProgress(i/iMax); } //get string representation of progress bar with p1 out of p2 done function getBar(p1, p2) { n = 20; bar1 = "--------------------"; bar2 = "********************"; index = round(n*(p1/p2)); if (index<1) index = 1; if (index>n-1) index = n-1; return substring(bar2, 0, index) + substring(bar1, index+1, n); } } }