macro "Pomegranate Analysis Revision Tool" { versionFIJI = "1.52s"; requires(versionFIJI); // Title Pop Up showMessageWithCancel("Pomegranate Analysis Revision Tool", "" +"
Pomegranate
" +"
Analysis Revision Tool
" +"
" +"
Virginia Polytechnic Institute and State University
" +"
Department of Biological Sciences - Hauf Lab
" +"
" +"
Please read accompanying documentation
" +"
[Erod Keaton Baybay - erodb@vt.edu]
"); waitForUser("This macro performs a prerun clean up\nThis will close all currently open images without saving\nClick OK to Continue"); cleanAll(); roiManager("Associate", "true"); roiManager("UseNames", "true"); run("Options...", "iterations=1 count=1 black do=Nothing"); run("Set Measurements...", "area mean standard modal min centroid center perimeter fit shape feret's median stack limit display redirect=None decimal=3"); // ----------------------------------------------------------------------------------------------------------------------------------------------- // Designate Input Image Dialog.create("Input Image"); Dialog.addChoice("Input Method", newArray("Select Image from Directory","Manually Enter Path")); Dialog.show(); if (Dialog.getChoice() == "Select Image from Directory") imagePath = File.openDialog("Choose an Input File"); else imagePath = getString("Image Path", "/Users/hauflab/Documents"); imageName = File.getName(imagePath); // Save IDs getDateAndTime(year, month, dayOfWeek, dayOfMonth, hour, minute, second, msec); saveID = "" + year + "" + month + "" + dayOfMonth + "_" + hour + "" + minute + "_" + imageName; runID = "OID" + (year - 2000) + "" + month + "" + dayOfMonth + "" + hour + "" + minute; // Designate Existing Output File Dialog.create("Existing Results File"); Dialog.addChoice("Input Method", newArray("Select Existing Output File from Directory","Manually Enter Path")); Dialog.show(); if (Dialog.getChoice() == "Select Existing Output File from Directory") oldPath = getDirectory("Choose Existing Output File"); else oldPath = getString("File Path", "/Users/hauflab/Documents"); // Output Directory oldDirectoryMain = oldPath +"/"; // ROI Directory oldDirectoryROI = oldDirectoryMain + "ROIs/"; if (!File.exists(oldDirectoryROI)) exit("Error: Missing ROI Directory\nResponse: Ending Analysis"); // Open Old ROI roiFile = -1; roiList = getFileList(oldDirectoryROI); for (i = 0; i < roiList.length; i++) if (endsWith(roiList[i], "_Filtered.zip")) roiFile = roiList[i]; if (roiFile == -1) exit("Error: No Filtered ROI File\nResponse: Ending Analysis"); // Set Experiment Name expName = getString("Experiment Name", imageName); run("Bio-Formats Importer", "open=" + imagePath + " autoscale color_mode=Composite view=Hyperstack stack_order=XYCZT"); roiManager("Open", oldDirectoryROI + roiFile); roiManager("Sort"); // Run Mode Detection nucROIs = newArray(); wclROIs = newArray(); n = roiManager("Count"); for(i = 0; i < n; i++) { if (startsWith(call("ij.plugin.frame.RoiManager.getName", i), "N_OID")) nucROIs = Array.concat(nucROIs, i); if (startsWith(call("ij.plugin.frame.RoiManager.getName", i), "WC_OID")) wclROIs = Array.concat(wclROIs, i); } if ((nucROIs.length > 0) & (wclROIs.length > 0)) { runMode = "BOTH"; runModeText = "Detected Analysis Type: Both Wholecell and Nuclear"; } else if ((nucROIs.length > 0)) { runMode = "NUCL"; runModeText = "Detected Analysis Type: Nuclear Only"; } else if ((wclROIs.length > 0)) { runMode = "WLCL"; runModeText = "Detected Analysis Type: Whole Cell Only"; } transpMode = false; segMode = false; Dialog.create("Pomegranate Run Parameters"); Dialog.addMessage(runModeText); Dialog.addCheckbox("Segmentation Only", segMode); Dialog.addCheckbox("Transparent Mode", transpMode); Dialog.show() segMode = Dialog.getCheckbox(); transpMode = Dialog.getCheckbox(); // Designate Output Directory Dialog.create("Output Directory"); Dialog.addChoice("Output Method", newArray("Select Output Directory","Manually Enter Path")); Dialog.show(); if (Dialog.getChoice() == "Select Output Directory") outputPath = getDirectory("Select Output Directory"); else outputPath = getString("Output Path", "/Users/hauflab/Documents"); if (!isOpen(imageName)) { showMessageWithCancel("Pomegranate Error", "Error: Unable to Open Image\nResponse: Ending Analysis"); cleanAll(); exit(); } // Get Image Dimensions getDimensions(width, height, channels, slices, frames); getVoxelSize(vx, vy, vz, unit); // Voxel Size Management Dialog.create("Voxel Size Management"); Dialog.addNumber("Voxel Width (" + unit + ")", vx); Dialog.addNumber("Voxel Height (" + unit + ")", vy); Dialog.addNumber("Voxel Depth (" + unit + ")", vz); Dialog.show(); nvx = Dialog.getNumber(); nvy = Dialog.getNumber(); nvz = Dialog.getNumber(); selectImage(imageName); setVoxelSize(nvx, nvy, nvz, unit); // Quick Check getVoxelSize(vx, vy, vz, unit); print("Voxel Size: " + vx + " " + unit + ", " + vy + " " + unit + ", " + vz + " " + unit); if (channels > 1) { channelList = newArray(channels); for (i = 1; i <= channels; i++) channelList[i-1] = "" + i; assignChannelLock = true; // Assign Channels while (assignChannelLock) { Dialog.create("Channel Selection"); if (!segMode) Dialog.addChoice("Measurement Channel", channelList, 1); if (runMode != "WLCL") Dialog.addChoice("Nuclear Marker Channel", channelList, 1); if (runMode != "NUCL") Dialog.addChoice("Bright-Field Channel", channelList, 1); Dialog.show(); if (!segMode) msChannel = parseInt(Dialog.getChoice()); // Measurement Channel if (runMode != "WLCL") nmChannel = parseInt(Dialog.getChoice()); // Nuclear Marker Channel if (runMode != "NUCL") bfChannel = parseInt(Dialog.getChoice()); // Bright-Field Channel print("\n[Run Parameters]"); if (!segMode) print("Measurement Channel: " + msChannel); if (runMode != "WLCL") print("Nuclear Marker Channel: " + nmChannel); if (runMode != "NUCL") print("Bright-Field Channel: " + bfChannel); // Defaulting Omitted Variables if (segMode) msChannel = -1; if (runMode == "WLCL") nmChannel = -2; if (runMode == "NUCL") bfChannel = -3; // Only Generate Folders for Valid Inputs if ((nmChannel != bfChannel) && (msChannel != bfChannel) && (nmChannel != msChannel)) assignChannelLock = false; // * * * else showMessageWithCancel("Pomegranate Error", "Error: Invalid Channel Selection\nResponse: Returning to Channel Selection"); } } else if ((channels < 2) && (runMode == "BOTH")) { showMessageWithCancel("Pomegranate Error", "Error: Insufficient Channels for Analysis\nResponse: Ending Analysis"); cleanAll(); exit(); } else if ((channels < 2) && (!segMode)) { showMessageWithCancel("Pomegranate Error", "Error: Insufficient Channels for Analysis\nResponse: Ending Analysis"); cleanAll(); exit(); } // ----------------------------------------------------------------------------------------------------------------------------------------------- // Output Directory directoryMain = outputPath + saveID+"/"; if (!File.exists(directoryMain)) File.makeDirectory(directoryMain); // ROI Directory directoryROI = directoryMain + "ROIs/"; if (!File.exists(directoryROI)) File.makeDirectory(directoryROI); // Results Directory directoryResults = directoryMain + "Results/"; if (!File.exists(directoryResults)) File.makeDirectory(directoryResults); // Binary Directory directoryBinary = directoryMain + "Binaries/"; if (!File.exists(directoryBinary)) File.makeDirectory(directoryBinary); if (channels > 1) { run("Split Channels"); if (!segMode) msChannel = "C"+msChannel+"-"+imageName; if (runMode != "WLCL") nmChannel = "C"+nmChannel+"-"+imageName; if (runMode != "NUCL") bfChannel = "C"+bfChannel+"-"+imageName; } else { if (runMode != "WLCL") nmChannel = imageName; if (runMode != "NUCL") bfChannel = imageName; } // ----------------------------------------------------------------------------------------------------------------------------------------------- if (runMode != "WLCL") { oldNUCFile = directoryROI + replace(File.getName(imagePath),'.','_') + "_OLD_Nuclear_ROIs.zip"; roiManager("Select", nucROIs); if (!File.exists(oldNUCFile)) roiManager("Save Selected", oldNUCFile); } if (runMode != "NUCL") { oldWCFile = directoryROI + replace(File.getName(imagePath),'.','_') + "_OLD_Whole_Cell_ROIs.zip"; roiManager("Select", wclROIs); if (!File.exists(oldWCFile)) roiManager("Save Selected", oldWCFile); } // ----------------------------------------------------------------------------------------------------------------------------------------------- if (runMode != "NUCL") { if (getBoolean("Rerun Reconstruction Algorithm?")) { roiManager("Reset"); roiManager("Open", oldWCFile); // Isolate Midslices n = roiManager("Count"); deleteList = newArray(); for(i = 0; i < n; i++) { roiManager("Select", i); if (Roi.getProperty("Mid_Slice") != 1) deleteList = Array.concat(deleteList, i); else roiManager("Rename", "Z" + i + "_tempROI"); } if (deleteList.length > 0) { roiManager("Select", deleteList); roiManager("Delete"); } // Make Canvas Image run("Select None"); roiManager("Deselect"); run("Duplicate...", "duplicate"); run("Multiply...", "value=0 stack"); run("RGB Color"); rename("Canvas"); selectImage("Canvas"); // Project into 3D newImage("Binary_Filtered", "8-bit black", width, height, slices); n = roiManager("Count"); for (i = 0; i < n; i++) { selectImage("Binary_Filtered"); roiManager("Select", i); ID = Roi.getProperty("Object_ID"); currentColor = Roi.getProperty("ROI_Color"); if(ID == "") { ID = "OID_" + i; currentColor = randomHexColor(); Roi.setProperty("Object_ID", ID); Roi.setProperty("ROI_Color", currentColor); roiManager("Rename", "Y_" + ID); roiManager("Update"); } run("Enlarge...", "enlarge=-1 pixel"); fill(); } roiManager("Deselect"); run("Select None"); run("Make Binary", "method=Otsu background=Default calculate black"); // Distance Map selectImage("Binary_Filtered"); run("Duplicate...", "duplicate title=Distance_Map"); run("Distance Map", "stack"); // Skeleton Image selectImage("Binary_Filtered"); run("Duplicate...", "duplicate title=Skeleton"); run("Skeletonize", "stack"); // Skeleton Image AND Distance Map imageCalculator("AND create stack", "Distance_Map","Skeleton"); rename("Medial_Axis_Transform"); close("Skeleton"); close("Distance_Map"); selectImage("Medial_Axis_Transform"); n = roiManager("Count"); for (i = 0; i < n; i++) { selectImage("Medial_Axis_Transform"); roiManager("Select", i); ID = Roi.getProperty("Object_ID"); currentColor = Roi.getProperty("ROI_Color"); setColor(currentColor); mid = getSliceNumber(); Roi.getContainedPoints(wcxPoints, wcyPoints); distMapValues = newArray(wcxPoints.length); for (j = 0; j < wcxPoints.length; j++) distMapValues[j] = getPixel(wcxPoints[j], wcyPoints[j]); selectImage("Canvas"); for (k = 1; k <= nSlices; k++) { setSlice(k); for (j = 0; j < wcxPoints.length; j++) { efactor = vx/vz; rinput = distMapValues[j]; zinput = (mid - k) / efactor; segmentRadius = crossSectionRadius(rinput, zinput) + 1; if ((rinput != 0) & (!isNaN(segmentRadius))) print("Cell " + i + ", Slice " + k + ", Segment " + j + ") --- R0: " + rinput + ", RS: " + segmentRadius + ", Z: " + zinput ); if (segmentRadius > 2) { // Compound Selection setKeyDown("Shift"); makeOval(wcxPoints[j] - segmentRadius, wcyPoints[j] - segmentRadius, segmentRadius * 2, segmentRadius * 2); } } // Apply to Canvas and ROI Manager if (selectionType() != -1) { // ROI Smoothing run("Enlarge...", "enlarge=15 pixel"); run("Enlarge...", "enlarge=-15 pixel"); Roi.setProperty("Object_ID", ID); Roi.setProperty("ROI_Color", currentColor); Roi.setStrokeColor(currentColor); if ((mid - k) == 0) Roi.setProperty("Mid_Slice", true); else Roi.setProperty("Mid_Slice", false); Roi.setProperty("Data_Type", "Whole_Cell"); Roi.setName("WC_" + ID + "_" + k); roiManager("Add"); fill(); } run("Select None"); run("Remove Overlay"); } } close("Medial_Axis_Transform"); selectImage("Canvas"); // ROI Name Cleanup n = roiManager("Count"); deleteList = newArray(); for (i = 0; i < n; i++) if (!startsWith(call("ij.plugin.frame.RoiManager.getName", i), "WC")) deleteList = Array.concat(deleteList, i); // Delete Original ROIs if (deleteList.length > 0) { roiManager("Select", deleteList); roiManager("Delete"); } roiManager("Deselect"); // Image Export selectImage("Canvas"); run("Remove Overlay"); run("Select None"); wcbinary = directoryBinary+"/Whole_Cell_RGB.tif"; if (!File.exists(wcbinary)) saveAs(".tiff", wcbinary); // Whole Cell ROI Export showStatus("Pomegranate - Exporting Whole Cell ROis"); print("\n[Exporting Whole Cell ROIs]"); wcFile = directoryROI + replace(File.getName(imagePath),'.','_') + "_Whole_Cell_ROIs.zip"; if (!File.exists(wcFile)) roiManager("Save", wcFile); print("File Created: " + wcFile); // Retrieve Nuclear ROIs if (runMode != "WLCL") roiManager("Open", oldNUCFile); } } // ----------------------------------------------------------------------------------------------------------------------------------------------- roiManager("Sort"); roiManager("Show All Without Labels"); if (!segMode) selectImage(msChannel); // Hold waitForUser("Reconstruction complete.\nClick OK to proceed to manual ROI filtering."); // Manual Deletion manualDelete = getBoolean("Manually delete an ROI?\nClick NO to use current ROIs for quantification"); deleteList = newArray(); while (manualDelete) { selectWindow("ROI Manager"); roiManager("Show All With Labels"); waitForUser("Please select an ROI.\nClick OK to delete that ROI's object."); if (selectionType() != -1) { deleteList = newArray(); deleteID = Roi.getProperty("Object_ID"); deleteType = Roi.getProperty("Data_Type"); n = roiManager("Count"); for (i = 0; i < n; i++) { roiManager("Select", i); if ((Roi.getProperty("Object_ID") == deleteID) && (Roi.getProperty("Data_Type") == deleteType)) deleteList = Array.concat(deleteList, i); } // Clear Bad ROIs if (deleteList.length > 0) { roiManager("Select", deleteList); roiManager("Delete"); } roiManager("Deselect"); run("Select None"); manualDelete = getBoolean("Manually delete another ROI?\nClick NO to use current ROIs for quantification"); } else manualDelete = getBoolean("Invalid selection. Try again?\nClick NO to use current ROIs for quantification"); } if (transpMode) waitForUser("[Transparent Mode] Manual Filter"); // Filtered ROI Export showStatus("Pomegranate - Exporting Filtered ROIs"); print("\n[Exporting Filtered ROIs]"); clFile = directoryROI + replace(File.getName(imagePath),'.','_') + "_Filtered.zip"; if (!File.exists(clFile)) roiManager("Save", clFile); print("File Created: " + clFile); // ----------------------------------------------------------------------------------------------------------------------------------------------- // Measure Intensity showStatus("Pomegranate - Measuring Whole Cell ROIs"); setBatchMode(true); if (!segMode) selectImage(msChannel); else { if (runMode != "NUCL") selectImage(bfChannel); else if (runMode != "WLCL") selectImage(nmChannel); } roiManager("Deselect"); roiManager("Show All Without Labels"); roiManager("Measure"); // Append Additional Info to Output n = roiManager("Count"); for (i = 0; i < n; i++) { roiManager("Select", i); getSelectionCoordinates(xpos, ypos); ID = Roi.getProperty("Object_ID"); dType = Roi.getProperty("Data_Type"); midType = Roi.getProperty("Mid_Slice"); crad = Roi.getProperty("Cell_Radius"); setResult("Object_ID", i, ID); if (midType) setResult("ROI_Type", i, "MID"); else setResult("ROI_Type", i, "NONMID"); setResult("Data_Type", i, dType); setResult("Image", i, imageName); setResult("Experiment", i, expName); setResult("xpos", i, replace(String.join(xpos)," ","")); setResult("ypos", i, replace(String.join(ypos)," ","")); } // Results Export showStatus("Pomegranate - Exporting Whole Cell Measurements"); ResultFile = directoryResults + replace(File.getName(imagePath),'.','_') + "_Results_Full.csv"; if (!File.exists(ResultFile)) saveAs("Results", ResultFile); // ----------------------------------------------------------------------------------------------------------------------------------------------- // Log File Export logFile = directoryMain + replace(File.getName(imagePath),'.','_') + "_LOG.txt"; if (!File.exists(logFile)) { selectWindow("Log"); saveAs("Text", logFile); } // End Run Cleanup cleanAll(); close("Log"); close("Results"); run("Collect Garbage"); waitForUser("Done", "Analysis is complete\nPlease review files in your output directory"); } // Clean Up Function function cleanAll() { close('*'); run("Clear Results"); roiManager("Reset"); print("\\Clear"); } // Radius of Spherical Cross Sections in Z function crossSectionRadius(r,z) { return(sqrt(pow(r,2) - pow(z,2))); }