def get_no_nuclei_fully_enclosed(roi, full_nuclei_imp, overlap_threshold=0.65): """for a given cell roi and ImagePlus with binary nuclei, return how many nuclei lie ENTIRELY within the cell""" bbox = roi.getBounds() full_nuclei_imp.setRoi(roi) cropped_nuc_imp = full_nuclei_imp.crop() roi.setLocation(0, 0) cropped_nuc_imp.setRoi(roi) cropped_nuc_imp.killRoi() roim = RoiManager(False) mxsz = cropped_nuc_imp.getWidth() * cropped_nuc_imp.getHeight() pa = ParticleAnalyzer( ParticleAnalyzer.ADD_TO_MANAGER, ParticleAnalyzer.AREA | ParticleAnalyzer.SLICE | ParticleAnalyzer.CENTROID, None, 0, mxsz) pa.setRoiManager(roim) pa.analyze(cropped_nuc_imp) cell_imp = IJ.createImage("Cell binary", cropped_nuc_imp.getWidth(), cropped_nuc_imp.getHeight(), 1, 8) IJ.run(cell_imp, "Select All", "") IJ.run(cell_imp, "Set...", "value=0 slice") cell_imp.setRoi(roi) IJ.run(cell_imp, "Set...", "value=255 slice") no_enclosed_nuclei = 0 for idx, nuc_roi in enumerate(roim.getRoisAsArray()): test_imp = Duplicator().run(cell_imp) test_imp.setRoi(nuc_roi) IJ.run(test_imp, "Set...", "value=255 slice") test_imp.killRoi() IJ.run(test_imp, "Create Selection", "") IJ.run(test_imp, "Make Inverse", "") test_roi = test_imp.getRoi() test_roi_stats = test_roi.getStatistics() cell_roi_stats = roi.getStatistics() nuc_roi_stats = nuc_roi.getStatistics() if test_roi_stats.area < ( cell_roi_stats.area + (1 - overlap_threshold) * nuc_roi_stats.area ): # i.e. if more than (100*overlap_threshold)% of nucleus is inside cell... no_enclosed_nuclei += 1 test_imp.changes = False test_imp.close() roi.setLocation(bbox.getX(), bbox.getY()) cropped_nuc_imp.changes = False cropped_nuc_imp.close() cell_imp.changes = False cell_imp.close() return no_enclosed_nuclei
def do_angular_projection(imp, max_r_pix=60, min_r_pix=10, generate_roi_stack=True): """perform ray-based projection of vessel wall, c.f. ICY TubeSkinner (Lancino 2018)""" Prefs.blackBackground = True print("do angular projection input imp = " + str(imp)) split_chs = ChannelSplitter().split(imp) mch_imp = split_chs[0] IJ.setAutoThreshold(mch_imp, "IsoData dark stack") egfp_imp = split_chs[1] proj_imp = Duplicator().run(egfp_imp) cl_imp = split_chs[2] if generate_roi_stack: egfp_imp_disp = Duplicator().run(egfp_imp) roi_stack = IJ.createImage("rois", egfp_imp.getWidth(), egfp_imp.getHeight(), egfp_imp.getNSlices(), 16) centres = [] projected_im_pix = [] ring_rois = [] for zidx in range(cl_imp.getNSlices()): if ((zidx + 1) % 100) == 0: print("Progress = " + str(round(100 * (float(zidx + 1) / cl_imp.getNSlices())))) projected_im_row = [] proj_imp.setZ(zidx + 1) mch_imp.setZ(zidx + 1) bp = mch_imp.createThresholdMask() bp.dilate() bp.erode() bp.erode() bp.erode() mask_imp = ImagePlus("mask", bp) IJ.run(mask_imp, "Create Selection", "") roi = mask_imp.getRoi() proj_imp.setRoi(roi) IJ.run(proj_imp, "Set...", "value=0 slice") IJ.run(proj_imp, "Make Inverse", "") roi = proj_imp.getRoi() centre = (roi.getStatistics().xCentroid, roi.getStatistics().yCentroid) centres.append(centre) ring_roi_xs = [] ring_roi_ys = [] for theta in range(360): pt1 = (centre[0] + min_r_pix * math.cos(math.radians(theta)), centre[1] + min_r_pix * math.sin(math.radians(theta))) pt2 = (centre[0] + max_r_pix * math.cos(math.radians(theta)), centre[1] + max_r_pix * math.sin(math.radians(theta))) roi = Line(pt1[0], pt1[1], pt2[0], pt2[1]) proj_imp.setRoi(roi) profile = roi.getPixels() projected_im_row.append(max(profile)) try: ring_roi_xs.append(roi.getContainedPoints()[profile.index( max(profile))].x) except IndexError: ring_roi_xs.append(pt2[0]) try: ring_roi_ys.append(roi.getContainedPoints()[profile.index( max(profile))].y) except IndexError: ring_roi_ys.append(pt2[1]) proj_imp.killRoi() ring_roi = PolygonRoi(ring_roi_xs, ring_roi_ys, Roi.FREELINE) ring_rois.append(ring_roi) if generate_roi_stack: roi_stack.setZ(zidx + 1) roi_stack.setRoi(ring_roi) IJ.run(roi_stack, "Line to Area", "") IJ.run( roi_stack, "Set...", "value=" + str(roi_stack.getProcessor().maxValue()) + " slice") #egfp_imp.setRoi(ring_roi); projected_im_pix.append(projected_im_row) # for ch in split_chs: # ch.close(); out_imp = ImagePlus( "projected", FloatProcessor([list(x) for x in zip(*projected_im_pix)])) if generate_roi_stack: roi_stack.show() egfp_imp_disp.show() # merge? else: roi_stack = None return out_imp, roi_stack, ring_rois, centres
def generate_background_rois(input_mask_imp, params, membrane_edges, dilations=5, threshold_method=None, membrane_imp=None): """automatically identify background region based on auto-thresholded image, existing membrane edges and position of midpoint anchor""" if input_mask_imp is None and membrane_imp is not None: segmentation_imp = Duplicator().run(membrane_imp) # do thresholding using either previous method if threhsold_method is None or using (less conservative?) threshold method if (threshold_method is None or not (threshold_method in params.listThresholdMethods())): mask_imp = make_and_clean_binary(segmentation_imp, params.threshold_method) else: mask_imp = make_and_clean_binary(segmentation_imp, threshold_method) segmentation_imp.close() else: input_mask_imp.killRoi() mask_imp = Duplicator().run(input_mask_imp) rois = [] IJ.setForegroundColor(0, 0, 0) roim = RoiManager(True) rt = ResultsTable() for fridx in range(mask_imp.getNFrames()): mask_imp.setT(fridx + 1) # add extra bit to binary mask from loaded membrane in case user refined edges... # flip midpoint anchor across the line joining the two extremes of the membrane, # and fill in the triangle made by this new point and those extremes poly = membrane_edges[fridx].getPolygon() l1 = (poly.xpoints[0], poly.ypoints[0]) l2 = (poly.xpoints[-1], poly.ypoints[-1]) M = (0.5 * (l1[0] + l2[0]), 0.5 * (l1[1] + l2[1])) Mp1 = (params.manual_anchor_midpoint[0][0] - M[0], params.manual_anchor_midpoint[0][1] - M[1]) p2 = (M[0] - Mp1[0], M[1] - Mp1[1]) new_poly_x = list(poly.xpoints) new_poly_x.append(p2[0]) new_poly_y = list(poly.ypoints) new_poly_y.append(p2[1]) mask_imp.setRoi(PolygonRoi(new_poly_x, new_poly_y, PolygonRoi.POLYGON)) IJ.run(mask_imp, "Fill", "slice") mask_imp.killRoi() # now dilate the masked image and identify the unmasked region closest to the midpoint anchor ip = mask_imp.getProcessor() dilations = 5 for d in range(dilations): ip.dilate() ip.invert() mask_imp.setProcessor(ip) mxsz = mask_imp.getWidth() * mask_imp.getHeight() pa = ParticleAnalyzer( ParticleAnalyzer.ADD_TO_MANAGER | ParticleAnalyzer.SHOW_PROGRESS, ParticleAnalyzer.CENTROID, rt, 0, mxsz) pa.setRoiManager(roim) pa.analyze(mask_imp) ds_to_anchor = [ math.sqrt((x - params.manual_anchor_midpoint[0][0])**2 + (y - params.manual_anchor_midpoint[0][1])**2) for x, y in zip( rt.getColumn(rt.getColumnIndex("X")).tolist(), rt.getColumn(rt.getColumnIndex("Y")).tolist()) ] if len(ds_to_anchor) > 0: roi = roim.getRoi(ds_to_anchor.index(min(ds_to_anchor))) rois.append(roi) else: rois.append(None) roim.reset() rt.reset() roim.close() mask_imp.close() return rois