/* Enigma+ Version 22.0602 * Matt Foley @ SMM (University of Sydney) * * This macro is two parts * * CraterExtract - generates a collection of craters from a thresholded stack and a CSV list * * Enigma+ - analyses the crater stack * * 22.0602 update * Cleaned up labelling - TDF now CF * Moved image appropriate-ness check (/* Check if dataset is appropriate / to /* Load parameters from preferences file /) * to after the dialog box/crater file generator (/* Tidy up and begin /) * Allows for a CF dummy to be created even if the dataset has not been prepared * * 19.0404 update * Line #165: * run("Remove Outliers...", "radius=1 threshold=0 which=Dark"); // remove the thin 1 pixel border introduced by the hull * changed to * run("Remove Outliers...", "radius=1 threshold=0 which=Bright"); // remove the thin 1 pixel border introduced by the hull * owing to changes in default settings for FIJI * * 19.0415 update * Included preference settings, help menu, Crater TDF generator, merged output, autosave CSV's * */ /* Parameters */ version = 19.0415; /* */ macro "Enigma...[j]" { /* Load parameters from preferences file */ res = call("ij.Prefs.get", "SMM.Enigma.var_pixelresolution", pixelWidth); // resolution of scan in um colour_merge = call("ij.Prefs.get", "SMM.Enigma.var_colour_merege", false); // merge final result scaling = call("ij.Prefs.get", "SMM.Enigma.var_scaling", unit); // conversion from um to mm units = newArray("µm", "mm"); // unit array /* Preferences dialog box */ Dialog.create("Engima settings"); Dialog.addNumber("Pixel resolution (um):", res); Dialog.addChoice("Preferred volume unit:", units, scaling); Dialog.addCheckbox("Merge final stacks?:", colour_merge); Dialog.addChoice("Generate crater file?", newArray("No", "Yes"), "No"); str_help = "

Enigma - Version "+version+"

" +"

Crater position file example:

" +"" +"
Crater#PositionSliceStartSliceEndX1Y1X2Y2
1Pal_Low100174579685120
" +"
If using Excel, save as a TAB Delimited csv file" +"
If using Notepad (or similar) ensure that there is a tab between each value
and that there are no trailing carriage returns" +"

Contact acmm.analysis@sydney.edu.au for troubleshooting" +"
For more microscopy support please " + "visit the SMM website"; Dialog.addHelp(str_help); Dialog.show(); /* Preferences back to file */ res = Dialog.getNumber(); scaling = Dialog.getChoice(); colour_merge = Dialog.getCheckbox(); generate_cf = Dialog.getChoice(); call("ij.Prefs.set", "SMM.Enigma.var_pixelresolution", res); call("ij.Prefs.set", "SMM.Enigma.var_colour_merege", colour_merge); call("ij.Prefs.set", "SMM.Enigma.var_scaling", scaling); res = res*pow(10, index(units, scaling)*-3); // Converts to reported units setBatchMode(true); /* CF generator */ if(generate_cf=="Yes"){ showMessage("Save the following file somewhere\nOpen using Excel and edit as appropriate"); Table.create("Crater File"); Table.set("Crater#", 0, ""); Table.set("Name & Location", 0, ""); Table.set("SliceStart", 0, ""); Table.set("SliceEnd", 0, ""); Table.set("X1", 0, ""); Table.set("Y1", 0, ""); Table.set("X2", 0, ""); Table.set("Y2", 0, ""); Table.update; crater_save = getDirectory("Choose a Directory"); saveAs("Results", crater_save+File.separator+"Crater_DummyFile.csv"); close("Crater_DummyFile.csv"); exit("Use Crater_DummyFile.csv to define locations and re-run macro"); } /* Check if dataset is appropriate */ if(nSlices<2) exit("Error - no stack selected"); // Checks to ensure a stack is being analysed /* If count[0]+count[255] for a given slice != image size then exit with error*/ run("Select None"); getDimensions(width, height, channels, slices, frames); getPixelSize(unit, pixelWidth, pixelHeight); nPixels = width*height; for(n=1; n<=nSlices; n++){ setSlice(n); getHistogram(values, count, 256); if(count[0]+count[255] != nPixels) exit("8-bit binary image (0 and 255) required."); } /* Tidy up and begin */ if (isOpen("ROI Manager")) { selectWindow("ROI Manager"); run("Close"); } origWindow = getTitle(); // Store original filename dot = indexOf(origWindow, "."); if (dot >= 0) origWindow = substring(origWindow, 0, dot); rename(origWindow); run("Select None"); // Loads tab delimited file containing positions (CF file) /* * Note: The format of the CF file MUST MATCH THE FOLLOWING EXAMPLE * * Crater# Position SliceStart SliceEnd X1 Y1 X2 Y2 */ pathfile=File.openDialog("Choose the crater positions file:"); // Opens the tab delimited file filestring=File.openAsString(pathfile); rows=split(filestring, "\n"); // Splits the lines craterID = newArray(rows.length); cratLoc = newArray(rows.length); SliceStart = newArray(rows.length); SliceEnd = newArray(rows.length); X1 = newArray(rows.length); Y1 = newArray(rows.length); X2 = newArray(rows.length); Y2 = newArray(rows.length); for(i=0; i width) || (Y1max > height)){exit("Check your X1/Y1 values");}; if ((X2min <0) || (Y2min <0) || (X2max > width) || (Y2max > height)){exit("Check your X2/Y2 values");}; if ((SliceStartmin < 0) || (SliceStartmax > slices) || (SliceEndmin < 0) || (SliceEndmax > slices)){exit("Check your Slice values");} /* Results table preparation */ tablename1 = "Crater results"; f= "["+tablename1+"]"; if(!isOpen(tablename1)) {run("Table...", "name="+f+" width=600 height=250"); print(f, "\\Headings:File\tCrater Volume (pixels)\tCrater Volume ("+scaling+"^3)"); }; /* Define save location */ saveDir = getDirectory("Please select the saving directory"); if(saveDir=="") exit("No save directory found"); if(!File.exists(saveDir)){File.makeDirectory(saveDir);} saveDir = saveDir+File.separator+origWindow; if(!File.exists(saveDir)){File.makeDirectory(saveDir);} for (i=1; i< rows.length; i++){ extractCrater(i); enigma(i); saveCrater(i); if(colour_merge){ run("Merge Channels...", "c5="+cratLoc[i]+"_"+craterID[i]+"_orig c6="+cratLoc[i]+"_"+craterID[i]+"_Crater create keep"); rename(cratLoc[i]+"_"+craterID[i]+"_Merged"); fs = File.separator; saveAs("Tiff", saveDir+fs+getTitle()); } }; /* Save results */ selectWindow("Crater results"); saveAs("Text", saveDir+File.separator+origWindow+" Crater results.csv"); /* Return to original image */ selectWindow(origWindow); run("Select None"); showMessage("Extract & Enigma of \n \n"+origWindow+"\n \nis complete."); setBatchMode(false); /* * * FUNCTIONS * */ function extractCrater(n){ selectWindow(origWindow); makeRectangle(X1[n], Y1[n], X2[n]-X1[n], Y2[n]-Y1[n]); run("Duplicate...", "title=["+cratLoc[n]+"_"+craterID[n]+"] duplicate range="+SliceStart[n]+"-"+SliceEnd[n]); saveExtract(n); }; function saveExtract(n){ fs = File.separator; saveAs("Tiff", saveDir+fs+getTitle()); rename(substring(getTitle(), 0, lengthOf(getTitle())-4)); }; function saveCrater(n){ fs = File.separator; saveAs("Tiff", saveDir+fs+getTitle()+"_Crater"); rename(substring(getTitle(), 0, lengthOf(getTitle())-4)); }; function enigma(n){ selectWindow(cratLoc[n]+"_"+craterID[n]); run("Duplicate...", "title="+cratLoc[n]+"_"+craterID[n]+"_orig duplicate"); selectWindow(cratLoc[n]+"_"+craterID[n]); run("Analyze Particles...", "size=0-Infinity circularity=0.00-1.00 show=Nothing clear include add stack"); TotROI=nResults; roiManager("Show None"); for (i=0; i