// FAST (Fluorescence image AnalysiS Tool) - Cyril TURIÈS - Comments or improvements are welcome (mailto: cyril.turies@ineris.fr)
// Image processing pipeline:
// - List all files containing user-defined extension (.czi .zvi .nd2 or .tif) within selected directory and sub-directories
// - Apply the user-defined threshold (default 290) then analyse particles above the threshold
// - Group all pixels above the threshold in one Region Of Interest and save this ROI in a zip file within work directory
// - Open images one by one to check the auto-selected area
// - User can confirm the ROI, modify it directly or remove image from further analysis
// - result table is automatically copied to clipboard at the end of the macro
// List of updates:
// - 10/2014 added help message accessible from dialogBox to explain tickboxes
// - 10/2014 added silent mode for new measurement of existing data without prompt
// - 10/2014 CSV saving option in work directory
// - 10/2014 added upper/lower case image selection
// - 01/2015 fixed bug reseting result table
// - 01/2015 add new Zeiss ZEN .czi file format and Dialog.setLocation()
// - 06/2016 Restart Mode to restart analysis after interruption of auto processing
// - 02/2018 added Nikon .nd2 file type
// - 07/2018 Former name "Cyp19a1b-GFP Analysis" changed to FAST (Fluorescence image AnalysiS Tool)
// - 08/2018 Saves user threshold and file type in ImageJ Prefs
// - 08/2018 Added "Other" for supported Bio-Formats file types not listed in startup options
v = "v2.4";
date = "08/2018";
requires("1.49o"); // 1.49o23
run("Bio-Formats Macro Extensions");
// DialogBox Help message
help = ""
+"
FAST (Fluorescence image AnalysiS Tool) help
"
+"Threshold : set threshold value for pixel intensity, segmenting the image
into features of interest (above threshold) and background.
"
+"File type : select image type or extension between CZI (ZEN Zeiss format)
"
+"ZVI (Zeiss Vision Image), ND2 Nikon file and TIFF (Tagged Image File Format),
'Other' allow to enter a specific file extension.
"
+"Create ROIs : Step 1, Analyse pixels above the user-defined threshold value
"
+"and automatically saves Regions Of Interest zip file in the image directory.
"
+"Measure ROIs : Step 2 of image analysis to check individually
and measure previously created ROIs.
"
+"(With Step 1 unchecked and Step 2 checked, user can reanalyse previous data).
"
+"Overwrite existing ROIs : if selected, the macro will overwrite ROIs zip files
without prompting the user every time.
"
+"Silent Mode : if selected, the macro will measure the ROI of all images
without prompting the user every time. (Useful for reanalysis of previous data).
"
+"Restart Mode : when auto processing is cancelled accidentally,
this mode checks the last ROI created and restarts analysis from this point.
"
+"*ROI = Region Of Interest
"
+"For a detailed description see: http://imagej.net/FAST
"
+"-> Any comment/improvement is welcome cyril.turies@ineris.fr"
+v+" - "+date
+"";
// Recover User variables from ImageJ Prefs
UserThr = call("ij.Prefs.get", "FAST.user.thr", "unset");
if (UserThr == "unset") UserThr = 290;
UserFtype = call("ij.Prefs.get", "FAST.user.ftype", "unset");
if (UserFtype == "unset") UserFtype = ".czi";
UserOTHtype = call("ij.Prefs.get", "FAST.user.othtype", "unset");
if (UserOTHtype == "unset") UserOTHtype = ".nd2";
// DialogBox to set options
Dialog.create("FAST "+v+" options");
Dialog.addChoice("File type", newArray(".czi",".zvi",".tif",".nd2","Other"), UserFtype);
Dialog.addNumber("Threshold value:", UserThr);
Dialog.setInsets(0, 0, 0);
Dialog.addMessage("Images auto processing:");
Dialog.setInsets(0, 20, 0);
Dialog.addCheckbox("Create Regions Of Interest (Step 1)", true);
Dialog.addCheckbox("Measure ROIs (Step 2)", true);
Dialog.setInsets(0, 0, 0);
Dialog.addMessage("Specific parameters: (see Help)");
Dialog.setInsets(0, 40, 0);
Dialog.addCheckbox("Overwrite existing ROIs", false);
Dialog.setInsets(0, 40, 0);
Dialog.addCheckbox("Silent Mode", false);
Dialog.setInsets(0, 40, 0);
Dialog.addCheckbox("Restart Mode", false);
Dialog.addHelp(help);
Dialog.show();
ext = Dialog.getChoice();
thr = Dialog.getNumber();
def = Dialog.getCheckbox();
mes = Dialog.getCheckbox();
overwrt = Dialog.getCheckbox();
silent = Dialog.getCheckbox();
resume = Dialog.getCheckbox();
// Save User preferences in ImageJ.Pref
call("ij.Prefs.set", "FAST.user.thr", thr);
call("ij.Prefs.set", "FAST.user.ftype", ext);
// Get extension not listed in File types
if (ext == "Other") {
Dialog.create("Please enter file extension");
Dialog.setInsets(0, 20, 0);
Dialog.addString("Extension:", UserOTHtype);
Dialog.addMessage("DO NOT remove the . before extension");
Dialog.show();
ext = Dialog.getString();
call("ij.Prefs.set", "FAST.user.othtype", ext);
}
// Select work directory
dir = getDirectory("Choose a Directory ");
svdir = dir;
k = 1;
// Reset ROI Manager
c = roiManager("count");
if (c != 0) {
showMessageWithCancel("Warning!","Content of ROI manager will be erased\nContinue?");
roiManager("reset");
}
// test for upper-case extension
upext = toUpperCase(ext);
// Auto threshold, select ROI and autosave
setBatchMode(true);
if (def == true) listFiles(dir);
setBatchMode(false);
// Goto image 1 to check each ROI
k = 1;
run("Set Measurements...", "area mean standard min integrated limit display redirect=None decimal=0");
// Reset result table
if (nResults != 0) {
// showMessageWithCancel("Warning!","Content of Result Table will be erased");
run("Clear Results");
}
// Individual check of ROI
if (mes == true) {
// Activate batchmode to stop blinking of images
if (silent == 1){
setBatchMode(true);
checkFiles(dir);
setBatchMode(false);
} else {
checkFiles(dir);
}
updateResults();
if (nResults == 0) {
print("No image corresponding to extention, found in selected directory");
print("OR");
print("File extension is not supported by Bio-Formats");
} else {
svchoice = getBoolean("Do you want to save the\nResult table to work directory?");
selectWindow("Results");
if (svchoice == 1) {
if (File.exists(svdir+"Results.csv")) {
choice = getBoolean("A file named Results.csv\nalready exists. Overwrite?");
if (choice == 1) saveAs("Results", svdir+"Results.csv");
if (choice == 0) {
newdir = getDirectory("Save to");
saveAs("Results", newdir+"Results.csv");
}
} else saveAs("Results", svdir+"Results.csv");
}
}
}
///////////////////////////////////
// Fonction "listfile" to select pixel area above user-defined threshold and auto save of ROI into [imagename].zip file
function listFiles(dir) {
list = getFileList(dir);
for (i=0; i1) {
roiManager("deselect");
roiManager("XOR");
roiManager("add");
for (j=1; j0) {
// check of existing ROI.zip
if (File.exists(dir+prefix+".zip")) {
if (overwrt == 1) {
roiManager("Save", dir+prefix+".zip");
} else {
choice = getBoolean("A file named "+prefix+".zip already exists.\nOverwrite?");
if (choice == 1) roiManager("Save", dir+prefix+".zip");
}
} else {
roiManager("Save", dir+prefix+".zip");
}
roiManager("reset");
}
close();
}
}
}
}
}
// Fonction "checkfiles" to individually check pixel area above user-defined threshold
function checkFiles(dir) {
list = getFileList(dir);
for (i=0; i "+prefix);
items = newArray("Yes", "No");
Dialog.addRadioButtonGroup("Exclude image from analysis:", items, 1, 2, "No");
Dialog.addRadioButtonGroup("Redefine area manually:", items, 1, 2, "No");
Dialog.setLocation(x+width,y);
Dialog.show;
skip = Dialog.getRadioButton;
area = Dialog.getRadioButton;
if (skip == "Yes") {
close();
roiManager("reset");
} else {
if (area == "Yes") {
roiManager("reset");
resetThreshold;
getMinAndMax(min, max);
setThreshold(thr, max, "over/under");
run("Analyze Particles...", "size=2-Infinity exclude include add");
setTool("freehand");
waitForUser("ROI edition","Edit area before you click on OK\n\nPress and hold key:\n ALT = Substract selected area \n SHIFT = Add selected area");
if (selectionType() == -1) waitForUser("WARNING","Without selection this image will be excluded from analysis\n \n=> Select area then click on -OK-");
if (selectionType() != -1) {
roiManager("add");
roiManager("Save", dir+prefix+".zip");
roiManager("deselect");
roiManager("Measure");
roiManager("reset");
setResult("Label", nResults-1, list[i]);
}
}
if (area == "No") {
resetThreshold;
getMinAndMax(min, max);
setThreshold(thr, max, "over/under");
roiManager("deselect");
roiManager("Measure");
roiManager("reset");
setResult("Label", nResults-1, list[i]);
}
updateResults();
close();
}
}
} else {
// Silent mode if no ROI is found
if (silent == 1){
print("No ROI.zip for: "+dir+prefix);
close();
// Normal mode if no pixel found in ROI
} else {
choice = getBoolean("No pixel area >> threshold found on the image.\n \nExclude image from analysis?\n| Yes | = Exclude\n| No | = Redefine area");
if (choice == 0) {
roiManager("reset");
resetThreshold;
run("Select None");
getMinAndMax(min, max);
setThreshold(thr, max, "over/under");
setTool("freehand");
waitForUser("Area selection","Select new area\nbefore you click on OK");
if (selectionType() == -1) waitForUser("WARNING","Without selection this image will be excluded from analysis\n \n=> Select area then click on -OK-");
if (selectionType() != -1) {
roiManager("add");
roiManager("Save", dir+prefix+".zip");
roiManager("deselect");
roiManager("Measure");
roiManager("reset");
setResult("Label", nResults-1, list[i]);
updateResults();
}
close();
}
if (choice == 1) {
close();
}
}
}
}
}
}
}