Created
April 24, 2020 13:14
-
-
Save NicoKiaru/cca76914de5905c965cfe485e11175fb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#@ImagePlus stack | |
#@Integer(label = "Channel DAPI") chDAPI = 1 | |
//Integer(label = "Channel Cytoplasm") chCyto = 3 | |
#@Integer(label = "Channel Measured") chAnalyzed = 2 | |
#@Integer(label = "Nucleus Enlargement in Pixel") enlarge_nucleus_px = 30 | |
#@Boolean(label = "Load Previous ROIS") loadPreviousRois = false | |
#@Boolean(label = "Save ROIS") saveDetectedRois = false | |
#@Boolean(label = "Erase previously existing ROIS") erase = false | |
#@Boolean(label = "Test mode") testMode = false | |
// Requires MorpholibJ | |
import ij.IJ | |
import org.apache.commons.io.FilenameUtils | |
import ij.plugin.frame.RoiManager | |
import ij.plugin.ZProjector | |
import ij.* | |
import ij.gui.* | |
import ij.process.* | |
import inra.ijpb.binary.* | |
import inra.ijpb.morphology.strel.* | |
import inra.ijpb.morphology.* | |
import ij.plugin.ImageCalculator | |
import ij.plugin.frame.RoiManager | |
import ij.plugin.filter.ThresholdToSelection; | |
import ij.process.ImageStatistics | |
import ij.gui.ShapeRoi | |
import java.util.HashMap; | |
import java.util.Map; | |
import ij.plugin.RoiEnlarger; | |
import java.awt.Color | |
// Removes any preexisting selection | |
IJ.run(stack, "Select None", "") | |
// Gets current RoiManager instance or creates it | |
RoiManager rm = RoiManager.getRoiManager(); | |
if (rm==null) { | |
rm = new RoiManager(); | |
} | |
if ((loadPreviousRois==false)||(loadRois(rm)==false)) { | |
// ------------ Extract DAPI channel | |
IJ.run(stack, "Duplicate...", "duplicate channels="+chDAPI); | |
IJ.run("Grays"); | |
dapiImage = IJ.getImage(); | |
// Segments it with median filtering and autothreshold | |
IJ.run(dapiImage, "Median...", "radius=2"); | |
IJ.setAutoThreshold(dapiImage, "Huang dark"); | |
IJ.run(dapiImage, "Analyze Particles...", "size=10-Infinity show=Masks clear add"); | |
// Transforms the mask image into a list of ROIs | |
dapiMaskImage = IJ.getImage(); | |
IJ.run(dapiMaskImage, "Invert", ""); | |
ArrayList<Roi> nuclei = new ArrayList<>(); | |
for (Roi roi : rm.getRoisAsArray()) { | |
nuclei.add(roi); | |
} | |
// ------------ Gets the voronoi areas of the nuclei | |
IJ.run(dapiMaskImage, "Make Binary",""); | |
IJ.run(dapiMaskImage, "Voronoi", ""); | |
dapiImage.setTitle("dapiImage"); | |
dapiMaskImage.setTitle("dapiMaskImage"); | |
dapiMaskImage.getProcessor().setThreshold(1, 255, ImageProcessor.NO_LUT_UPDATE) | |
dapiMaskImage.setProcessor(dapiMaskImage.getProcessor().createMask()) | |
dapiMaskImage.getProcessor().invert() | |
// Gets label image of voronoi regions | |
def voronoi_labels = BinaryImages.componentsLabeling(dapiMaskImage, 8, 16) | |
// ------------ Extract Cytoplasm of all cells | |
//IJ.run(stack, "Duplicate...", "duplicate channels="+chCyto); | |
//IJ.run("Grays"); | |
//cytoImage = IJ.getImage(); | |
cytoImage = ZProjector.run(stack,"sum"); | |
IJ.run(cytoImage, "Median...", "radius=20"); | |
IJ.setAutoThreshold(cytoImage, "Percentile dark"); | |
maskRoi = (new ThresholdToSelection()).convert(cytoImage.getProcessor()) | |
rm.addRoi(maskRoi); | |
srMaskRoi = new ShapeRoi(maskRoi); | |
voronoi_labels.show(); | |
rm.reset(); | |
// For each nucleus | |
nuclei.eachWithIndex{ r,idx -> | |
// Identifies voronoi label region thanks to the pixel value at the center of the nucleus | |
int xp = r.getBounds().x+r.getBounds().width/2; | |
int yp = r.getBounds().y+r.getBounds().height/2; | |
int label = voronoi_labels.getProcessor().getf(xp,yp); | |
// Transform voronoi label region into a ROI | |
IJ.setRawThreshold(voronoi_labels, label,label, null); | |
def maskLabel = (new ThresholdToSelection()).convert(voronoi_labels.getProcessor()) | |
// Transform all rois into ShapeRois for simple operation (AND OR XOR) | |
srNucleus = new ShapeRoi(r); // Nucleus | |
srAreaVoronoi = new ShapeRoi(maskLabel); // Voronoi | |
// Full cytoplasm = Mask Cyto AND area Voronoi MINUS Nucleus | |
rcyto = srAreaVoronoi.and(srMaskRoi).not(srNucleus); | |
rcyto.setName("Cyto_"+idx); | |
rcyto.setStrokeColor(Color.RED); | |
rm.addRoi(rcyto); | |
// Cytoplasm next to the nucleus = (Mask Cyto AND area Voronoi MINUS Nucleus) AND Enlarged nucleus | |
rcytonn = srAreaVoronoi.and(srMaskRoi).and(new ShapeRoi(RoiEnlarger.enlarge(r,enlarge_nucleus_px)).not(srNucleus)); | |
rcytonn.setName("CytoNearNucleus_"+idx); | |
rcytonn.setStrokeColor(Color.GREEN); | |
if (enlarge_nucleus_px>0) { | |
rm.addRoi(rcytonn); | |
} | |
r.setName("Nucleus_"+idx); | |
r.setStrokeColor(Color.BLUE); | |
rm.addRoi(r); | |
} | |
// Closes all intermediate images | |
voronoi_labels.show(); | |
voronoi_labels.setTitle("voronoi_labels"); | |
voronoi_labels.changes = false; | |
if (!testMode) voronoi_labels.close(); | |
dapiImage.setTitle("dapiImage"); | |
dapiImage.changes=false; | |
if (!testMode) dapiImage.close(); | |
dapiMaskImage.setTitle("dapiMaskImage"); | |
dapiMaskImage.changes = false; | |
if (!testMode) dapiMaskImage.close(); | |
cytoImage.setTitle("cytoImage"); | |
cytoImage.changes = false; | |
if (!testMode) cytoImage.close(); | |
// Saved currently defined ROIs | |
if (saveDetectedRois) {saveRois(rm);} | |
} | |
// Perform measurements | |
//rm.runCommand(stack,"multi-measure measure_all one append"); | |
//rt = rm.multiMeasure(stack, rm.getRoisAsArray(),true); | |
//rt.show("Results"); | |
//rm.runCommand(stack,"Show All"); | |
// ------------ Extract Measured channel | |
IJ.run(stack, "Duplicate...", "duplicate channels="+chAnalyzed); | |
IJ.run("Grays"); | |
measuredImage = IJ.getImage(); | |
for (int i=0;i<rm.getCount();i++) { | |
rm.select(i); | |
IJ.run(measuredImage, "Measure", ""); | |
} | |
measuredImage.close() | |
// ---------------------------------------------------------------------------------------- | |
// Loads rois in BIOP conventional subfolder with conventional name, if they already exist | |
boolean loadRois(RoiManager rm) { | |
def info = stack.getOriginalFileInfo() | |
def dir = info.directory | |
def fileName = info.fileName | |
// create an output dir ,and prepare output file path | |
def output_dir = new File( dir , "ROI Sets" ) | |
output_dir.mkdirs() | |
def output_path = new File ( output_dir , FilenameUtils.removeExtension(fileName) +".zip" ) // BIOP BASICS compatible | |
if ((output_path.exists()) && (!erase)) { | |
rm.reset() | |
rm.runCommand("Open", output_path.toString()); | |
return true; | |
} else { | |
return false; | |
} | |
} | |
// Saves rois in BIOP conventional subfolder with conventional name | |
void saveRois(RoiManager rm) { | |
def info = stack.getOriginalFileInfo() | |
def dir = info.directory | |
def fileName = info.fileName | |
// create an output dir ,and prepare output file path | |
def output_dir = new File( dir , "ROI Sets" ) | |
output_dir.mkdirs() | |
def output_path = new File ( output_dir , FilenameUtils.removeExtension(fileName) +".zip" ) // BIOP BASICS compatible | |
rm.runCommand("Save", output_path.toString()); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment