Skip to content

Instantly share code, notes, and snippets.

@NicoKiaru
Created April 24, 2020 13:14
Show Gist options
  • Save NicoKiaru/cca76914de5905c965cfe485e11175fb to your computer and use it in GitHub Desktop.
Save NicoKiaru/cca76914de5905c965cfe485e11175fb to your computer and use it in GitHub Desktop.
#@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