/* Enigma+ Version 23.0829
* 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
*
* 23.0829 update
* Included
* getPixelSize(unit, pixelWidth, pixelHeight);
* line to address issue with undefined variables
*
* 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 = 23.0829;
/* */
macro "Enigma...[j]" {
getPixelSize(unit, pixelWidth, pixelHeight);
/* 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_merge", 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# | Position | SliceStart | SliceEnd | X1 | Y1 | X2 | Y2 |
"
+"| 1 | Pal_Low | 100 | 174 | 57 | 96 | 85 | 120 |
"
+"
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