def analyze(imp, min_area): MAXSIZE = 1000000000000 MINCIRCULARITY = 0.0 MAXCIRCULARITY = 1. options = PA.SHOW_MASKS temp_results = ResultsTable() p = PA(options, PA.AREA + PA.MEAN, temp_results, min_area, MAXSIZE, MINCIRCULARITY, MAXCIRCULARITY) p.setHideOutputImage(True) p.analyze(imp) if temp_results.getCounter() == 0: areas = [] signals = [] else: areas = list(temp_results.getColumn(0)) signals = list(temp_results.getColumn(1)) count = len(areas) area = sum(areas) total = 0 if area > 0: total = sum([a*s for a,s in zip(areas, signals)]) / area return p.getOutputImage(), count, area, total
def threshold(imPlus, edgeThreshold=2500): mask = Duplicator().run(imPlus) mask_stk = mask.getStack() # First, we threshold based on edges IJ.setThreshold(mask, edgeThreshold, 100000, "No Update") for i in range(mask.getImageStackSize()): mask_stk.getProcessor(i + 1).findEdges() IJ.run(mask, "Make Binary", "method=Default background=Default black") # Now, we need to clean up the binary images morphologically IJ.run(mask, "Dilate", "stack") IJ.run(mask, "Fill Holes", "stack") IJ.run(mask, "Erode", "stack") IJ.run(mask, "Erode", "stack") # Finally, remove the small particles stk = ImageStack(mask.getWidth(), mask.getHeight()) p = PA(PA.SHOW_MASKS, 0, None, 200, 100000) p.setHideOutputImage(True) for i in range(mask_stk.getSize()): mask.setSliceWithoutUpdate(i + 1) p.analyze(mask) mmap = p.getOutputImage() stk.addSlice(mmap.getProcessor()) mask.setStack(stk) mask.setSliceWithoutUpdate(1) mask.setTitle(mask_title(imPlus.getTitle())) mask.show() return mask
def segmentNuc(impc2): impdup = Duplicator().run(impc2) IJ.run(impdup, "8-bit", "") IJ.run(impdup, "Gaussian Blur...", "sigma=1.5 stack") # AutoThresholder().getThreshold(AutoThresholder.Method.valuOf('Otsu'), int[] histogram) IJ.setAutoThreshold(impdup, "Otsu dark") IJ.run(impdup, "Convert to Mask", "stack") #IJ.setAutoThreshold(impdup, "Otsu dark") #opt = PA.SHOW_MASKS + PA.SHOW_RESULTS + PA.EXCLUDE_EDGE_PARTICLES + PA.INCLUDE_HOLES # option for stack missing opt = PA.SHOW_MASKS + PA.EXCLUDE_EDGE_PARTICLES + PA.INCLUDE_HOLES # option for stack missing ##area mean centroid bounding integrated stack redirect=None decimal=4 meas = Meas.AREA + Meas.MEAN + Meas.CENTROID + Meas.RECT + Meas.INTEGRATED_DENSITY + Meas.STACK_POSITION rt = ResultsTable().getResultsTable() pa = PA(opt, meas, rt, 10.0, 300000.0, 0, 1.0) PA.processStack = True pa.setHideOutputImage(True) ##run("Analyze Particles...", "size=800-Infinity circularity=0.00-1.00 pixel show=Masks display exclude include stack"); outstack = ImageStack(impdup.getWidth(), impdup.getHeight()) for i in range(1,impdup.getStackSize()+1): impdup.setSlice(i) pa.analyze(impdup) impbin = pa.getOutputImage() outstack.addSlice(impbin.getProcessor()) impbin = ImagePlus("out", outstack) IJ.run(impbin, "Invert LUT", "") #IJ.run(impbin, "Fill Holes", "stack") return impbin, rt
def analyzeParticles(imp, minsize, maxsize, mincirc, maxcirc, filename='Test.czi', addROIManager=True, headless=True, exclude=True): if addROIManager is True: if exclude is False: options = PA.SHOW_ROI_MASKS \ + PA.SHOW_RESULTS \ + PA.DISPLAY_SUMMARY \ + PA.ADD_TO_MANAGER \ + PA.ADD_TO_OVERLAY \ if exclude is True: options = PA.SHOW_ROI_MASKS \ + PA.SHOW_RESULTS \ + PA.DISPLAY_SUMMARY \ + PA.ADD_TO_MANAGER \ + PA.ADD_TO_OVERLAY \ + PA.EXCLUDE_EDGE_PARTICLES if addROIManager is False: if exclude is False: options = PA.SHOW_ROI_MASKS \ + PA.SHOW_RESULTS \ + PA.DISPLAY_SUMMARY \ + PA.ADD_TO_OVERLAY \ if exclude is True: options = PA.SHOW_ROI_MASKS \ + PA.SHOW_RESULTS \ + PA.DISPLAY_SUMMARY \ + PA.ADD_TO_OVERLAY \ + PA.EXCLUDE_EDGE_PARTICLES measurements = PA.STACK_POSITION \ + PA.LABELS \ + PA.AREA \ + PA.RECT \ results = ResultsTable() p = PA(options, measurements, results, minsize, maxsize, mincirc, maxcirc) p.setHideOutputImage(True) particlestack = ImageStack(imp.getWidth(), imp.getHeight()) for i in range(imp.getStackSize()): imp.setSliceWithoutUpdate(i + 1) ip = imp.getProcessor() #IJ.run(imp, "Convert to Mask", "") p.analyze(imp, ip) mmap = p.getOutputImage() particlestack.addSlice(mmap.getProcessor()) return particlestack, results
def process(inputpath, outputpath): imp = IJ.openImage(inputpath) IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) IJ.setThreshold(imp, t1, 255) #imp.show() #WaitForUserDialog("Title", "Look at image").show() IJ.run(imp, "Convert to Mask", "") IJ.run(imp, "Watershed", "") # Counts and measures the area of particles and adds them to a table called areas. Also adds them to the ROI manager table = ResultsTable() roim = RoiManager(True) ParticleAnalyzer.setRoiManager(roim) pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 50, 9999999999999999, 0.2, 1.0) pa.setHideOutputImage(True) pa.analyze(imp) imp.changes = False imp.close() areas = table.getColumn(0) summary = {} if areas: summary['Image'] = filename summary['Nuclei.count'] = len(areas) summary['Area.Covered'] = sum(areas) fieldnames = list(summary.keys()) with open(outputpath, 'a') as csvfile: writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', lineterminator='\n') if os.path.getsize(outputDirectory + "/" + outputname + ".csv") < 1: writer.writeheader() writer.writerow(summary)
def countParticles(imp, roim, minSize, maxSize, minCircularity, maxCircularity): # Create a table to store the results table = ResultsTable() # Create the particle analyzer pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA|Measurements.MEAN, table, minSize, maxSize, minCircularity, maxCircularity) #pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA|Measurements.MEAN, table, 10, Double.POSITIVE_INFINITY, 0.5, 1.0) #pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA|Measurements.MEAN, table, 5, 6, 0.5, 1.0) pa.setRoiManager(roim) pa.setHideOutputImage(True) if pa.analyze(imp): print "All ok" else: print "There was a problem in analyzing", blobs areas = table.getColumn(0) intensities = table.getColumn(1) if ( (areas!=None) and (intensities!=None)): for area, intensity in zip(areas,intensities): print str(area)+": "+str(intensity)
def countParticles(imp, roim, minSize, maxSize, minCircularity, maxCircularity): # Create a table to store the results table = ResultsTable() # Create the particle analyzer pa = ParticleAnalyzer( ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA | Measurements.MEAN | Measurements.ELLIPSE, table, minSize, maxSize, minCircularity, maxCircularity) pa.setRoiManager(roim) pa.setHideOutputImage(True) if pa.analyze(imp): print "All ok" else: print "There was a problem in analyzing", blobs areas = table.getColumn(0) intensities = table.getColumn(1) majors = table.getColumn(2)
def getParticleCenters(imp): # Create a table to store the results rt = ResultsTable() paOpts = PA.SHOW_OUTLINES \ + PA.INCLUDE_HOLES \ + PA.EXCLUDE_EDGE_PARTICLES measurements = PA.CENTROID + PA.CENTER_OF_MASS MINSIZE = 1000 MAXSIZE = Double.POSITIVE_INFINITY pa = PA(paOpts,measurements, rt, MINSIZE, MAXSIZE) pa.setHideOutputImage(True) if not pa.analyze(imp): print "There was a problem in analyzing", imp # The measured centroids are listed in the first column of the results table, as a float array: centroids_x = rt.getColumn(rt.X_CENTROID) centroids_y = rt.getColumn(rt.Y_CENTROID) coms_x = rt.getColumn(rt.X_CENTER_OF_MASS) coms_y = rt.getColumn(rt.Y_CENTER_OF_MASS) return (centroids_x,centroids_y, coms_x, coms_y)
def removeSmallCCs(image): MINSIZE = 1000 MAXSIZE = 1000000 options = PA.SHOW_ROI_MASKS results = ResultsTable() p = PA(options, PA.STACK_POSITION + PA.LABELS + PA.AREA + PA.PERIMETER + PA.CIRCULARITY, results, MINSIZE, MAXSIZE) p.setHideOutputImage(True) p.analyze(image) mmap = p.getOutputImage() mip = mmap.getProcessor() mip.threshold(0) img = ImagePlus("rods_processed", mip) IJ.run(img, "8-bit", "") IJ.run(img, "Make Binary", "method=Default background=Dark black") return img
def process(subFolder, outputDirectory, filename): imp = IJ.openImage(inputDirectory + subFolder + '/' + rreplace(filename, "_ch00.tif", ".tif")) IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) ic = ImageConverter(imp) ic.convertToGray8() IJ.setThreshold(imp, 2, 255) IJ.run(imp, "Convert to Mask", "") IJ.run(imp, "Remove Outliers...", "radius=5" + " threshold=50" + " which=Dark") IJ.run(imp, "Remove Outliers...", "radius=5" + " threshold=50" + " which=Bright") imp.getProcessor().invert() rm = RoiManager(True) imp.getProcessor().setThreshold(0, 0, ImageProcessor.NO_LUT_UPDATE) boundroi = ThresholdToSelection.run(imp) rm.addRoi(boundroi) if not displayImages: imp.changes = False imp.close() images = [None] * 5 intensities = [None] * 5 blobsarea = [None] * 5 blobsnuclei = [None] * 5 bigAreas = [None] * 5 for chan in channels: v, x = chan images[x] = IJ.openImage(inputDirectory + subFolder + '/' + rreplace(filename, "_ch00.tif", "_ch0" + str(x) + ".tif")) imp = images[x] for roi in rm.getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.MEAN | Measurements.AREA) intensities[x] = stats.mean bigAreas[x] = stats.area rm.close() # Opens the ch00 image and sets default properties imp = IJ.openImage(inputDirectory + subFolder + '/' + filename) IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) # Sets the threshold and watersheds. for more details on image processing, see https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html ic = ImageConverter(imp) ic.convertToGray8() IJ.run(imp, "Remove Outliers...", "radius=2" + " threshold=50" + " which=Dark") IJ.run(imp, "Gaussian Blur...", "sigma=" + str(blur)) IJ.setThreshold(imp, lowerBounds[0], 255) if displayImages: imp.show() IJ.run(imp, "Convert to Mask", "") IJ.run(imp, "Watershed", "") if not displayImages: imp.changes = False imp.close() # Counts and measures the area of particles and adds them to a table called areas. Also adds them to the ROI manager table = ResultsTable() roim = RoiManager(True) ParticleAnalyzer.setRoiManager(roim) pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 15, 9999999999999999, 0.2, 1.0) pa.setHideOutputImage(True) #imp = impM # imp.getProcessor().invert() pa.analyze(imp) areas = table.getColumn(0) # This loop goes through the remaining channels for the other markers, by replacing the ch00 at the end with its corresponding channel # It will save all the area fractions into a 2d array called areaFractionsArray areaFractionsArray = [None] * 5 for chan in channels: v, x = chan # Opens each image and thresholds imp = images[x] IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) ic = ImageConverter(imp) ic.convertToGray8() IJ.setThreshold(imp, lowerBounds[x], 255) if displayImages: imp.show() WaitForUserDialog("Title", "Adjust Threshold for Marker " + v).show() IJ.run(imp, "Convert to Mask", "") # Measures the area fraction of the new image for each ROI from the ROI manager. areaFractions = [] for roi in roim.getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.AREA_FRACTION) areaFractions.append(stats.areaFraction) # Saves the results in areaFractionArray areaFractionsArray[x] = areaFractions roim.close() for chan in channels: v, x = chan imp = images[x] imp.deleteRoi() roim = RoiManager(True) ParticleAnalyzer.setRoiManager(roim) pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 15, 9999999999999999, 0.2, 1.0) pa.analyze(imp) blobs = [] for roi in roim.getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.AREA) blobs.append(stats.area) blobsarea[x] = sum(blobs) blobsnuclei[x] = len(blobs) if not displayImages: imp.changes = False imp.close() roim.reset() roim.close() # Creates the summary dictionary which will correspond to a single row in the output csv, with each key being a column summary = {} summary['Image'] = filename summary['Directory'] = subFolder # Adds usual columns summary['size-average'] = 0 summary['#nuclei'] = 0 summary['all-negative'] = 0 summary['too-big-(>' + str(tooBigThreshold) + ')'] = 0 summary['too-small-(<' + str(tooSmallThreshold) + ')'] = 0 # Creates the fieldnames variable needed to create the csv file at the end. fieldnames = [ 'Name', 'Directory', 'Image', 'size-average', 'too-big-(>' + str(tooBigThreshold) + ')', 'too-small-(<' + str(tooSmallThreshold) + ')', '#nuclei', 'all-negative' ] # Adds the columns for each individual marker (ignoring Dapi since it was used to count nuclei) summary["organoid-area"] = bigAreas[x] fieldnames.append("organoid-area") for chan in channels: v, x = chan summary[v + "-positive"] = 0 fieldnames.append(v + "-positive") summary[v + "-intensity"] = intensities[x] fieldnames.append(v + "-intensity") summary[v + "-blobsarea"] = blobsarea[x] fieldnames.append(v + "-blobsarea") summary[v + "-blobsnuclei"] = blobsnuclei[x] fieldnames.append(v + "-blobsnuclei") # Adds the column for colocalization between first and second marker if len(channels) > 2: summary[channels[1][0] + '-' + channels[2][0] + '-positive'] = 0 fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-positive') # Adds the columns for colocalization between all three markers if len(channels) > 3: summary[channels[1][0] + '-' + channels[3][0] + '-positive'] = 0 summary[channels[2][0] + '-' + channels[3][0] + '-positive'] = 0 summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] = 0 fieldnames.append(channels[1][0] + '-' + channels[3][0] + '-positive') fieldnames.append(channels[2][0] + '-' + channels[3][0] + '-positive') fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive') # Loops through each particle and adds it to each field that it is True for. areaCounter = 0 for z, area in enumerate(areas): log.write(str(area)) log.write("\n") if area > tooBigThreshold: summary['too-big-(>' + str(tooBigThreshold) + ')'] += 1 elif area < tooSmallThreshold: summary['too-small-(<' + str(tooSmallThreshold) + ')'] += 1 else: summary['#nuclei'] += 1 areaCounter += area temp = 0 for chan in channels: v, x = chan if areaFractionsArray[x][z] > areaFractionThreshold[ 0]: #theres an error here im not sure why. i remember fixing it before summary[chan[0] + '-positive'] += 1 if x != 0: temp += 1 if temp == 0: summary['all-negative'] += 1 if len(channels) > 2: if areaFractionsArray[1][z] > areaFractionThreshold[1]: if areaFractionsArray[2][z] > areaFractionThreshold[2]: summary[channels[1][0] + '-' + channels[2][0] + '-positive'] += 1 if len(channels) > 3: if areaFractionsArray[1][z] > areaFractionThreshold[1]: if areaFractionsArray[3][z] > areaFractionThreshold[3]: summary[channels[1][0] + '-' + channels[3][0] + '-positive'] += 1 if areaFractionsArray[2][z] > areaFractionThreshold[2]: if areaFractionsArray[3][z] > areaFractionThreshold[3]: summary[channels[2][0] + '-' + channels[3][0] + '-positive'] += 1 if areaFractionsArray[1][z] > areaFractionThreshold[1]: summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] += 1 # Calculate the average of the particles sizes if float(summary['#nuclei']) > 0: summary['size-average'] = round(areaCounter / summary['#nuclei'], 2) # Opens and appends one line on the final csv file for the subfolder (remember that this is still inside the loop that goes through each image) with open(outputDirectory + "/" + outputName + ".csv", 'a') as csvfile: writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', lineterminator='\n') if os.path.getsize(outputDirectory + "/" + outputName + ".csv") < 1: writer.writeheader() writer.writerow(summary)
summary[color[i] + "-threshold-used"] = ImageProcessor.getMinThreshold(channel.getProcessor()) #Threshold and watershed IJ.run(channel, "Convert to Mask", "") IJ.run(channel, "Watershed", "") table = ResultsTable() roim = RoiManager(True) ParticleAnalyzer.setRoiManager(roim) #Analyses particles: finds all the objects that match criteria pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER | ParticleAnalyzer.EXCLUDE_EDGE_PARTICLES, Measurements.AREA, table, minimum_size, maximum_size, 0.1, 1.0) pa.setHideOutputImage(True) pa.analyze(channel) if thresholdMode: channel.show() WaitForUserDialog("Title", "Look at threshold for" + color[i]).show() #adds count to summary if table.getColumnIndex("Area") != -1: summary[color[i] + "-ROI-count"] = len(table.getColumn(table.getColumnIndex("Area"))) channel.changes = False channel.close()
dupes.append(x) seen[x] += 1 print(dupes) for dupe in dupes: # get centroidys rt = ResultsTable(); #rm = RoiManager.getInstance(); #print(rm) rm = RoiManager(False); pa = ParticleAnalyzer((ParticleAnalyzer.ADD_TO_MANAGER | ParticleAnalyzer.SHOW_MASKS), (Measurements.CENTROID | Measurements.STACK_POSITION), rt, 500, 30000, 0.0, 1.0) pa.setHideOutputImage(False) keep_rois = []; pa.analyze(imp); IJ.run("Set Measurements...", "centroid redirect=None decimal=3"); frames = imp.getNFrames(); for fridx in range(0, frames): rt.reset(); imp.setSliceWithoutUpdate(fridx + 1); ip = imp.getProcessor(); if not pa.analyze(imp, ip): raise Exception("something went wrong analysing particles!") rt.show("centroids"); rm = RoiManager.getInstance(); if rm.getCount() > 0: rois = rm.getRoisAsArray();
binorg.show() # Count nucleus setting MAXSIZE = imp3.getWidth()*imp3.getHeight(); MINSIZE = 100; #options = PA.SHOW_ROI_MASKS \ # + PA.EXCLUDE_EDGE_PARTICLES \ # + PA.INCLUDE_HOLES \ # + PA.SHOW_RESULTS \ options = PA.INCLUDE_HOLES \ + PA.CLEAR_WORKSHEET \ # + PA.SHOW_RESULTS \ rt = ResultsTable() p = PA(options, PA.AREA + PA.STACK_POSITION, rt, MINSIZE, MAXSIZE) p.setHideOutputImage(True) # Morphological dilate binner.setup('dilate', None) clusters = 0 initialCells = 0 # dilate by 'SAMPLEITER' for i in range(SAMPLEITER+1): p.analyze(binimp) cellcounts = rt.getCounter() if i == 0: initialCells = cellcounts #IJ.log("iter:" + str(i) + " -- cell counts: " + str(cellcounts))
def __calRois(self, imp, indice) : """ Returns the ROIs of a slice given (identified with its n°) in a stack """ ##imp=self.__dictImages[nameimages] # IL FAUT RÉCUPÉRER L'IMAGE DU STACK !!!!! #if self.__batch : imp.hide() #else : imp.show() #imp.hide() imp.show() if self.__batch : imp.hide() imp.setSlice(indice) imp.killRoi() ip = imp.getProcessor() bs=BackgroundSubtracter() #if str(self.__subback) == "0" or str(self.__subback) == "1" : self.__subback = bool(int(self.__subback)) #if self.__subback == True : IJ.run(imp, "Subtract Background...", "rolling="+str(self.__radius)+" light") if self.__subback == True : bs.rollingBallBackground(ip, self.__radius, False, True, False, True, False) if self.__runmacro : imp.show() imp.setSlice(indice) imp.updateAndDraw() IJ.runMacroFile(self.__macropath, imp.getTitle()) imp.updateAndDraw() #if str(self.__manthresh) == "0" or str(self.__manthresh) == "1" : self.__manthresh = bool(int(self.__manthresh)) #if self.__manthresh : IJ.setThreshold(imp, self.__minthr, self.__maxthr) if self.__manthresh : ip.setThreshold(self.__minthr, self.__maxthr, ImageProcessor.RED_LUT) else : self.__setThreshold(imp, indice) rt=ResultsTable() pa1=ParticleAnalyzer(ParticleAnalyzer.SHOW_MASKS+ParticleAnalyzer.EXCLUDE_EDGE_PARTICLES , Measurements.AREA, rt, self.__minArea, self.__maxArea, self.__minCirc, self.__maxCirc) pa1.setHideOutputImage(True) pa1.analyze(imp) masks=pa1.getOutputImage() masks.getProcessor().erode() masks.getProcessor().dilate() masks.getProcessor().invertLut() masks.getProcessor().threshold(1) rm = RoiManager.getInstance() if (rm==None): rm = RoiManager() rm.runCommand("reset") #rm.hide() pa2=ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER+ParticleAnalyzer.CLEAR_WORKSHEET+ParticleAnalyzer.EXCLUDE_EDGE_PARTICLES , Measurements.AREA, rt, self.__minArea, self.__maxArea, self.__minCirc, self.__maxCirc) pa2.analyze(masks) masks.close() temparray=rm.getRoisAsArray() for r in temparray : tempnameroi=r.getName() r.setPosition(indice) r.setName(str(indice)+"-"+tempnameroi) r.setStrokeWidth(1) if len(self.__params) > 0 : for k in self.__params: #if k[0]=="Area": self.__minArea, self.__maxArea = str(k[1]), str(k[2]) if k[0]=="Area": self.__minArea, self.__maxArea = k[1], k[2] for k in self.__params: #if k[0]=="Circ": self.__minCirc, self.__maxCirc = str(k[1]), str(k[2]) if (k[0]=="Circ") and k[3] : self.__minCirc, self.__maxCirc = k[1], k[2] else : self.__minCirc, self.__maxCirc = 0, 1 self.__rr.setRoisarray(temparray, imp) self.__rr.setRange(indice, self.__params) return self.__rr.includeRois else : return temparray
def process(subDir, subsubDir, outputDirectory, filename): subFolder = subDir + "/" + subsubDir # Opens the d0 image and sets default properties imp = IJ.openImage(inputDirectory + subFolder + '/' + filename) IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) # Sets the threshold and watersheds. for more details on image processing, see https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html ic = ImageConverter(imp) ic.convertToGray8() imp.updateAndDraw() dup = imp.duplicate() IJ.run( dup, "Convolve...", "text1=[-1 -1 -1 -1 -1\n-1 -1 -1 -1 -1\n-1 -1 24 -1 -1\n-1 -1 -1 -1 -1\n-1 -1 -1 -1 -1\n] normalize" ) stats = dup.getStatistics(Measurements.MEAN | Measurements.MIN_MAX | Measurements.STD_DEV) dup.close() blurry = (stats.mean < 18 and stats.stdDev < 22) or stats.max < 250 IJ.setThreshold(imp, lowerBounds[0], 255) IJ.run(imp, "Convert to Mask", "") IJ.run(imp, "Watershed", "") if displayImages: imp.show() WaitForUserDialog("Title", "Look at image").show() # Counts and measures the area of particles and adds them to a table called areas. Also adds them to the ROI manager table = ResultsTable() roim = RoiManager(True) ParticleAnalyzer.setRoiManager(roim) pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 15, 9999999999999999, 0.2, 1.0) pa.setHideOutputImage(True) pa.analyze(imp) if not displayImages: imp.changes = False imp.close() areas = table.getColumn(0) # This loop goes through the remaining channels for the other markers, by replacing the d0 at the end with its corresponding channel # It will save all the area fractions into a 2d array called areaFractionsArray areaFractionsArray = [] areaMeansArray = [] means = [] totalAreas = [] for chan in channels: v, x = chan # Opens each image and thresholds imp = IJ.openImage(inputDirectory + subFolder + '/' + filename.replace("d0.TIF", "d" + str(x) + ".TIF")) IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) ic = ImageConverter(imp) ic.convertToGray8() imp.updateAndDraw() stats = imp.getStatistics(Measurements.MEAN) means.append(stats.mean) areaMeans = [] for roi in roim.getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.MEAN) areaMeans.append(stats.mean) IJ.setThreshold(imp, lowerBounds[x], 255) IJ.run(imp, "Convert to Mask", "") if displayImages: imp.show() WaitForUserDialog("Title", "Look at image").show() stats = imp.getStatistics(Measurements.AREA_FRACTION) totalAreas.append(stats.areaFraction) # Measures the area fraction of the new image for each ROI from the ROI manager. areaFractions = [] for roi in roim.getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.AREA_FRACTION) areaFractions.append(stats.areaFraction) # Saves the results in areaFractionArray areaFractionsArray.append(areaFractions) areaMeansArray.append(sum(areaMeans) / len(areaMeans)) if not displayImages: imp.changes = False imp.close() roim.close() # Figures out what well the image is a part of ind = filename.index("p00_0_") row = filename[ind + 6:ind + 7] column = str(int(filename[ind + 7:ind + 9])) # Creates the summary dictionary which will correspond to a single row in the output csv, with each key being a column summary = {} # Finds the name of the well from the nameArray 2d array if row in nameArray: if column in nameArray[row]: summary['Name'] = nameArray[row][column] summary['Image'] = filename summary['Directory'] = subDir summary['SubDirectory'] = subsubDir summary['Row'] = row summary['Column'] = column # Adds usual columns summary['size-average'] = 0 summary['#nuclei'] = 0 summary['all-negative'] = 0 summary['too-big-(>' + str(tooBigThreshold) + ')'] = 0 summary['too-small-(<' + str(tooSmallThreshold) + ')'] = 0 summary['image-quality'] = blurry # Creates the fieldnames variable needed to create the csv file at the end. fieldnames = [ 'Name', 'Directory', 'SubDirectory', 'Image', 'Row', 'Column', 'size-average', 'image-quality', 'too-big-(>' + str(tooBigThreshold) + ')', 'too-small-(<' + str(tooSmallThreshold) + ')', '#nuclei', 'all-negative' ] # Adds the columns for each individual marker (ignoring Dapi since it was used to count nuclei) for chan in channels: v, x = chan summary[v + "-positive"] = 0 summary[v + "-intensity"] = means[x] summary[v + "-area"] = totalAreas[x] summary[v + "-intensity-in-nuclei"] = areaMeansArray[x] summary[v + "-area-fraction-in-nuclei"] = sum( areaFractionsArray[x]) / len(areaFractionsArray[x]) fieldnames.append(v + "-positive") fieldnames.append(v + "-intensity") fieldnames.append(v + "-area") fieldnames.append(v + "-intensity-in-nuclei") fieldnames.append(v + "-area-fraction-in-nuclei") # Adds the column for colocalization between first and second marker if len(channels) > 2: summary[channels[1][0] + '-' + channels[2][0] + '-positive'] = 0 fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-positive') # Adds the columns for colocalization between all three markers if len(channels) > 3: summary[channels[1][0] + '-' + channels[3][0] + '-positive'] = 0 summary[channels[2][0] + '-' + channels[3][0] + '-positive'] = 0 summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] = 0 fieldnames.append(channels[1][0] + '-' + channels[3][0] + '-positive') fieldnames.append(channels[2][0] + '-' + channels[3][0] + '-positive') fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive') # Loops through each particle and adds it to each field that it is True for. areaCounter = 0 if not (areas is None): for z, area in enumerate(areas): if not (area is None or summary is None): if area > tooBigThreshold: summary['too-big-(>' + str(tooBigThreshold) + ')'] += 1 elif area < tooSmallThreshold: summary['too-small-(<' + str(tooSmallThreshold) + ')'] += 1 else: summary['#nuclei'] += 1 areaCounter += area temp = 0 for y, chan in enumerate(channels): v, x = chan if areaFractionsArray[y][z] > areaFractionThreshold: summary[chan[0] + '-positive'] += 1 if x != 0: temp += 1 if temp == 0: summary['all-negative'] += 1 if len(channels) > 2: if areaFractionsArray[1][z] > areaFractionThreshold: if areaFractionsArray[2][z] > areaFractionThreshold: summary[channels[1][0] + '-' + channels[2][0] + '-positive'] += 1 if len(channels) > 3: if areaFractionsArray[1][z] > areaFractionThreshold: if areaFractionsArray[3][z] > areaFractionThreshold: summary[channels[1][0] + '-' + channels[3][0] + '-positive'] += 1 if areaFractionsArray[2][z] > areaFractionThreshold: if areaFractionsArray[3][z] > areaFractionThreshold: summary[channels[2][0] + '-' + channels[3][0] + '-positive'] += 1 if areaFractionsArray[1][ z] > areaFractionThreshold: summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] += 1 # Calculate the average of the particles sizes if float(summary['#nuclei']) > 0: summary['size-average'] = round(areaCounter / summary['#nuclei'], 2) # Opens and appends one line on the final csv file for the subfolder (remember that this is still inside the loop that goes through each image) with open(outputDirectory + "/" + outputName + ".csv", 'a') as csvfile: writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', lineterminator='\n') if os.path.getsize(outputDirectory + "/" + outputName + ".csv") < 1: writer.writeheader() writer.writerow(summary)
def process(subFolder, outputDirectory, filename): imp = IJ.openImage(inputDirectory + subFolder + '/' + filename) imp.show() IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) ic = ImageConverter(imp) dup = imp.duplicate() dup_title = dup.getTitle() ic.convertToGray8() imp.updateAndDraw() IJ.run("Threshold...") IJ.setThreshold(218, 245) IJ.run(imp, "Convert to Mask", "") rm = RoiManager() imp.getProcessor().setThreshold(0, 0, ImageProcessor.NO_LUT_UPDATE) boundroi = ThresholdToSelection.run(imp) rm.addRoi(boundroi) imp.changes = False imp.close() images = [None] * 5 intensities = [None] * 5 blobsarea = [None] * 5 blobsnuclei = [None] * 5 cells = [None] * 5 bigareas = [None] * 5 IJ.run(dup, "Colour Deconvolution", "vectors=[H DAB]") images[0] = getImage(dup_title + "-(Colour_1)") images[1] = getImage(dup_title + "-(Colour_2)") images[2] = getImage(dup_title + "-(Colour_3)") images[2].close() for chan in channels: v, x = chan imp = images[x] imp.show() for roi in rm.getRoiManager().getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.MEAN | Measurements.AREA) intensities[x] = stats.mean bigareas[x] = stats.area rm.runCommand(imp, "Show None") rm.close() # Opens the ch00 image and sets default properties imp = images[0].duplicate() IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) # Sets the threshold and watersheds. for more details on image processing, see https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html imp.show() setTempCurrentImage(imp) ic = ImageConverter(imp) imp.updateAndDraw() IJ.run(imp, "Gaussian Blur...", "sigma=" + str(blur)) imp.updateAndDraw() imp.show() IJ.run("Threshold...") IJ.setThreshold(30, lowerBounds[0]) if displayImages: imp.show() WaitForUserDialog( "Title", "Adjust threshold for nuclei. Current region is: " + region).show() IJ.run(imp, "Convert to Mask", "") # Counts and measures the area of particles and adds them to a table called areas. Also adds them to the ROI manager table = ResultsTable() roim = RoiManager() pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 5, 9999999999999999, 0.05, 1.0) pa.setHideOutputImage(True) imp = IJ.getImage() # imp.getProcessor().invert() pa.analyze(imp) imp.changes = False imp.close() areas = table.getColumn(0) # This loop goes through the remaining channels for the other markers, by replacing the ch00 at the end with its corresponding channel # It will save all the area fractions into a 2d array called areaFractionsArray areaFractionsArray = [None] * 5 maxThresholds = [] for chan in channels: v, x = chan # Opens each image and thresholds imp = images[x] IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) imp.show() setTempCurrentImage(imp) ic = ImageConverter(imp) ic.convertToGray8() imp.updateAndDraw() rm.runCommand(imp, "Show None") rm.runCommand(imp, "Show All") rm.runCommand(imp, "Show None") imp.show() IJ.selectWindow(imp.getTitle()) IJ.run("Threshold...") IJ.setThreshold(20, lowerBounds[x]) if displayImages: WaitForUserDialog( "Title", "Adjust threshold for " + v + ". Current region is: " + region).show() ip = imp.getProcessor() maxThresholds.append(ip.getMaxThreshold()) IJ.run(imp, "Convert to Mask", "") # Measures the area fraction of the new image for each ROI from the ROI manager. areaFractions = [] for roi in roim.getRoiManager().getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.AREA_FRACTION) areaFractions.append(stats.areaFraction) # Saves the results in areaFractionArray areaFractionsArray[x] = areaFractions roim.close() for chan in channels: v, x = chan imp = images[x] imp.deleteRoi() imp.updateAndDraw() setTempCurrentImage(imp) roim = RoiManager() pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 15, 9999999999999999, 0.2, 1.0) pa.analyze(imp) blobs = [] cell = [] for roi in roim.getRoiManager().getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.AREA) blobs.append(stats.area) if stats.area > tooSmallThresholdDAB and stats.area < tooBigThresholdDAB: cell.append(stats.area) blobsarea[x] = sum(blobs) blobsnuclei[x] = len(blobs) cells[x] = len(cell) imp.changes = False imp.close() roim.reset() roim.close() # Creates the summary dictionary which will correspond to a single row in the output csv, with each key being a column summary = {} summary['Image'] = filename summary['Directory'] = subFolder # Adds usual columns summary['size-average'] = 0 summary['#nuclei'] = 0 summary['all-negative'] = 0 summary['too-big-(>' + str(tooBigThreshold) + ')'] = 0 summary['too-small-(<' + str(tooSmallThreshold) + ')'] = 0 # Creates the fieldnames variable needed to create the csv file at the end. fieldnames = [ 'Directory', 'Image', 'size-average', 'too-big-(>' + str(tooBigThreshold) + ')', 'too-small-(<' + str(tooSmallThreshold) + ')', '#nuclei', 'all-negative' ] for row in info: if row['Animal ID'] == filename.replace('s', '-').replace( 'p', '-').split('-')[0]: for key, value in row.items(): fieldnames.insert(0, key) summary[key] = value # Adds the columns for each individual marker (ignoring Dapi since it was used to count nuclei) summary["tissue-area"] = bigareas[0] fieldnames.append("tissue-area") for chan in channels: v, x = chan summary[v + "-HEMO-cells"] = 0 fieldnames.append(v + "-HEMO-cells") summary[v + "-intensity"] = intensities[x] fieldnames.append(v + "-intensity") summary[v + "-area"] = blobsarea[x] fieldnames.append(v + "-area") summary[v + "-area/tissue-area"] = blobsarea[x] / bigareas[0] fieldnames.append(v + "-area/tissue-area") summary[v + "-particles"] = blobsnuclei[x] fieldnames.append(v + "-particles") summary[v + "-cells"] = cells[x] fieldnames.append(v + "-cells") summary[v + "-particles/tissue-area"] = blobsnuclei[x] / bigareas[0] fieldnames.append(v + "-particles/tissue-area") fieldnames.append(v + "-HEMO-Cells/tissue-area") # Adds the column for colocalization between first and second marker if len(channels) > 2: summary[channels[1][0] + '-' + channels[2][0] + '-positive'] = 0 fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-positive') # Adds the columns for colocalization between all three markers if len(channels) > 3: summary[channels[1][0] + '-' + channels[3][0] + '-positive'] = 0 summary[channels[2][0] + '-' + channels[3][0] + '-positive'] = 0 summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] = 0 fieldnames.append(channels[1][0] + '-' + channels[3][0] + '-positive') fieldnames.append(channels[2][0] + '-' + channels[3][0] + '-positive') fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive') # Loops through each particle and adds it to each field that it is True for. areaCounter = 0 for z, area in enumerate(areas): if area > tooBigThreshold: summary['too-big-(>' + str(tooBigThreshold) + ')'] += 1 elif area < tooSmallThreshold: summary['too-small-(<' + str(tooSmallThreshold) + ')'] += 1 else: summary['#nuclei'] += 1 areaCounter += area temp = 0 for chan in channels: v, x = chan if areaFractionsArray[x][z] > areaFractionThreshold[0]: summary[chan[0] + '-HEMO-cells'] += 1 if x != 0: temp += 1 if temp == 0: summary['all-negative'] += 1 if len(channels) > 2: if areaFractionsArray[1][z] > areaFractionThreshold[1]: if areaFractionsArray[2][z] > areaFractionThreshold[2]: summary[channels[1][0] + '-' + channels[2][0] + '-positive'] += 1 if len(channels) > 3: if areaFractionsArray[1][z] > areaFractionThreshold[1]: if areaFractionsArray[3][z] > areaFractionThreshold[3]: summary[channels[1][0] + '-' + channels[3][0] + '-positive'] += 1 if areaFractionsArray[2][z] > areaFractionThreshold[2]: if areaFractionsArray[3][z] > areaFractionThreshold[3]: summary[channels[2][0] + '-' + channels[3][0] + '-positive'] += 1 if areaFractionsArray[1][z] > areaFractionThreshold[1]: summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] += 1 # Calculate the average of the particles sizes for chan in channels: v, x = chan summary[v + "-cells/tissue-area"] = summary[v + "-cells"] / bigareas[0] if float(summary['#nuclei']) > 0: summary['size-average'] = round(areaCounter / summary['#nuclei'], 2) if displayImages: fieldnames = ["Directory", "Image"] for chan in channels: v, x = chan summary[v + "-threshold"] = maxThresholds[x] fieldnames.append(v + "-threshold") allMaxThresholds[v + "-" + region].append(maxThresholds[x]) # Opens and appends one line on the final csv file for the subfolder (remember that this is still inside the loop that goes through each image) with open(outputName, 'a') as csvfile: writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', lineterminator='\n') if os.path.getsize(outputName) < 1: writer.writeheader() writer.writerow(summary)
def process(subFolder, outputDirectory, filename): #IJ.close() imp = IJ.openImage(inputDirectory + subFolder + '/' + rreplace(filename, "_ch00.tif", ".tif")) imp.show() # Get the pixel values from the xml file for file in os.listdir(inputDirectory + subFolder): if file.endswith('.xml'): xml = os.path.join(inputDirectory + subFolder, file) xml = "C:/Users/Harris/Desktop/test_xml_for_parsing_pixel.xml" element_tree = ET.parse(xml) root = element_tree.getroot() for dimensions in root.iter('DimensionDescription'): num_pixels = int(dimensions.attrib['NumberOfElements']) if dimensions.attrib['Unit'] == "m": length = float(dimensions.attrib['Length']) * 1000000 else: length = float(dimensions.attrib['Length']) pixel_length = length / num_pixels else: pixel_length = 0.8777017 IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=" + str(pixel_length) + " pixel_height=" + str(pixel_length) + " voxel_depth=25400.0508001") ic = ImageConverter(imp) ic.convertToGray8() #IJ.setThreshold(imp, 2, 255) #Automatically selects the area of the organoid based on automated thresholding and creates a mask to be applied on #all other images IJ.setAutoThreshold(imp, "Mean dark no-reset") IJ.run(imp, "Convert to Mask", "") IJ.run(imp, "Analyze Particles...", "size=100000-Infinity add select") rm = RoiManager.getInstance() num_roi = rm.getCount() for i in num_roi: imp = getCurrentImage() rm.select(imp, i) IJ.setBackgroundColor(0, 0, 0) IJ.run(imp, "Clear Outside", "") IJ.run(imp, "Convert to Mask", "") IJ.run(imp, "Remove Outliers...", "radius=5" + " threshold=50" + " which=Dark") IJ.run(imp, "Remove Outliers...", "radius=5" + " threshold=50" + " which=Bright") # Save the mask and open it IJ.saveAs("tiff", inputDirectory + '/mask' + i) mask = IJ.openImage(inputDirectory + '/mask' + i + '.tif') if not displayImages: imp.changes = False imp.close() images = [None] * 5 intensities = [None] * 5 blobsarea = [None] * 5 blobsnuclei = [None] * 5 bigAreas = [None] * 5 imp.close() # Loop to open all the channel images for chan in channels: v, x = chan images[x] = IJ.openImage(inputDirectory + subFolder + '/' + rreplace(filename, "_ch00.tif", "_ch0" + str(x) + ".tif")) # Apply Mask on all the images and save them into an array apply_mask = ImageCalculator() images[x] = apply_mask.run("Multiply create 32 bit", mask, images[x]) ic = ImageConverter(images[x]) ic.convertToGray8() imp = images[x] # Calculate the intensities for each channel as well as the organoid area for roi in rm.getRoisAsArray(): imp.setRoi(roi) stats_i = imp.getStatistics(Measurements.MEAN | Measurements.AREA) intensities[x] = stats_i.mean bigAreas[x] = stats_i.area rm.close() # Opens the ch00 image and sets default properties #Get the pixel values from the xml file for file in os.listdir(subFolder): if file.endswith('.xml'): xml = os.path.join(inputDirectory + subFolder, file) xml = "C:/Users/Harris/Desktop/test_xml_for_parsing_pixel.xml" element_tree = ET.parse(xml) root = element_tree.getroot() for dimensions in root.iter('DimensionDescription'): num_pixels = int(dimensions.attrib['NumberOfElements']) if dimensions.attrib['Unit'] == "m": length = float(dimensions.attrib['Length']) * 1000000 else: length = float(dimensions.attrib['Length']) pixel_length = length / num_pixels else: pixel_length = 0.8777017 imp = IJ.openImage(inputDirectory + subFolder + '/' + filename) imp = apply_mask.run("Multiply create 32 bit", mask, imp) IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=" + str(pixel_length) + "pixel_height=" + str(pixel_length) + "voxel_depth=25400.0508001") # Sets the threshold and watersheds. for more details on image processing, see https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html ic = ImageConverter(imp) ic.convertToGray8() IJ.run(imp, "Remove Outliers...", "radius=2" + " threshold=50" + " which=Dark") IJ.run(imp, "Gaussian Blur...", "sigma=" + str(blur)) IJ.setThreshold(imp, lowerBounds[0], 255) if displayImages: imp.show() IJ.run(imp, "Convert to Mask", "") IJ.run(imp, "Watershed", "") if not displayImages: imp.changes = False imp.close() # Counts and measures the area of particles and adds them to a table called areas. Also adds them to the ROI manager table = ResultsTable() roim = RoiManager(True) ParticleAnalyzer.setRoiManager(roim) pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 15, 9999999999999999, 0.2, 1.0) pa.setHideOutputImage(True) # imp = impM # imp.getProcessor().invert() pa.analyze(imp) areas = table.getColumn(0) # This loop goes through the remaining channels for the other markers, by replacing the ch00 at the end with its corresponding channel # It will save all the area fractions into a 2d array called areaFractionsArray areaFractionsArray = [None] * 5 for chan in channels: v, x = chan # Opens each image and thresholds imp = images[x] IJ.run( imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=0.8777017 pixel_height=0.8777017 voxel_depth=25400.0508001" ) ic = ImageConverter(imp) ic.convertToGray8() IJ.setThreshold(imp, lowerBounds[x], 255) if displayImages: imp.show() WaitForUserDialog("Title", "Adjust Threshold for Marker " + v).show() IJ.run(imp, "Convert to Mask", "") # Measures the area fraction of the new image for each ROI from the ROI manager. areaFractions = [] for roi in roim.getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.AREA_FRACTION) areaFractions.append(stats.areaFraction) # Saves the results in areaFractionArray areaFractionsArray[x] = areaFractions roim.close() for chan in channels: v, x = chan imp = images[x] imp.deleteRoi() roim = RoiManager(True) ParticleAnalyzer.setRoiManager(roim) pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, Measurements.AREA, table, 15, 9999999999999999, 0.2, 1.0) pa.analyze(imp) blobs = [] for roi in roim.getRoisAsArray(): imp.setRoi(roi) stats = imp.getStatistics(Measurements.AREA) blobs.append(stats.area) blobsarea[x] = sum( blobs ) #take this out and use intial mask tissue area from the beginning blobsnuclei[x] = len(blobs) if not displayImages: imp.changes = False imp.close() roim.reset() roim.close() imp.close() # Creates the summary dictionary which will correspond to a single row in the output csv, with each key being a column summary = {} summary['Image'] = filename summary['Directory'] = subFolder # Adds usual columns summary['size-average'] = 0 summary['#nuclei'] = 0 summary['all-negative'] = 0 summary['too-big-(>' + str(tooBigThreshold) + ')'] = 0 summary['too-small-(<' + str(tooSmallThreshold) + ')'] = 0 # Creates the fieldnames variable needed to create the csv file at the end. fieldnames = [ 'Name', 'Directory', 'Image', 'size-average', 'too-big-(>' + str(tooBigThreshold) + ')', 'too-small-(<' + str(tooSmallThreshold) + ')', '#nuclei', 'all-negative' ] # Adds the columns for each individual marker (ignoring Dapi since it was used to count nuclei) summary["organoid-area"] = bigAreas[x] fieldnames.append("organoid-area") for chan in channels: v, x = chan summary[v + "-positive"] = 0 fieldnames.append(v + "-positive") summary[v + "-intensity"] = intensities[x] fieldnames.append(v + "-intensity") summary[v + "-blobsarea"] = blobsarea[x] fieldnames.append(v + "-blobsarea") summary[v + "-blobsnuclei"] = blobsnuclei[x] fieldnames.append(v + "-blobsnuclei") # Adds the column for colocalization between first and second marker if len(channels) > 2: summary[channels[1][0] + '-' + channels[2][0] + '-positive'] = 0 fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-positive') # Adds the columns for colocalization between all three markers if len(channels) > 3: summary[channels[1][0] + '-' + channels[3][0] + '-positive'] = 0 summary[channels[2][0] + '-' + channels[3][0] + '-positive'] = 0 summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] = 0 fieldnames.append(channels[1][0] + '-' + channels[3][0] + '-positive') fieldnames.append(channels[2][0] + '-' + channels[3][0] + '-positive') fieldnames.append(channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive') # Loops through each particle and adds it to each field that it is True for. areaCounter = 0 for z, area in enumerate(areas): log.write(str(area)) log.write("\n") if area > tooBigThreshold: summary['too-big-(>' + str(tooBigThreshold) + ')'] += 1 elif area < tooSmallThreshold: summary['too-small-(<' + str(tooSmallThreshold) + ')'] += 1 else: summary['#nuclei'] += 1 areaCounter += area temp = 0 for chan in channels: v, x = chan if areaFractionsArray[x][z] > areaFractionThreshold[ 0]: # theres an error here im not sure why. i remember fixing it before summary[chan[0] + '-positive'] += 1 if x != 0: temp += 1 if temp == 0: summary['all-negative'] += 1 if len(channels) > 2: if areaFractionsArray[1][z] > areaFractionThreshold[1]: if areaFractionsArray[2][z] > areaFractionThreshold[2]: summary[channels[1][0] + '-' + channels[2][0] + '-positive'] += 1 if len(channels) > 3: if areaFractionsArray[1][z] > areaFractionThreshold[1]: if areaFractionsArray[3][z] > areaFractionThreshold[3]: summary[channels[1][0] + '-' + channels[3][0] + '-positive'] += 1 if areaFractionsArray[2][z] > areaFractionThreshold[2]: if areaFractionsArray[3][z] > areaFractionThreshold[3]: summary[channels[2][0] + '-' + channels[3][0] + '-positive'] += 1 if areaFractionsArray[1][z] > areaFractionThreshold[1]: summary[channels[1][0] + '-' + channels[2][0] + '-' + channels[3][0] + '-positive'] += 1 # Calculate the average of the particles sizes if float(summary['#nuclei']) > 0: summary['size-average'] = round(areaCounter / summary['#nuclei'], 2) # Opens and appends one line on the final csv file for the subfolder (remember that this is still inside the loop that goes through each image) with open(outputDirectory + "/" + outputName + ".csv", 'a') as csvfile: writer = csv.DictWriter(csvfile, fieldnames=fieldnames, extrasaction='ignore', lineterminator='\n') if os.path.getsize(outputDirectory + "/" + outputName + ".csv") < 1: writer.writeheader() writer.writerow(summary) IJ.run(imp, "Close All", "")
def analyzeParticles(imp, minsize, maxsize, mincirc, maxcirc, #filename='Test.czi', addROIManager=False, #headless=False, exclude=True): if GraphicsEnvironment.isHeadless(): print('Headless Mode detected. Do not use ROI Manager.') addROIManager = False if addROIManager: # get the ROI manager instance rm = RoiManager.getInstance() if rm is None: rm = RoiManager() rm.runCommand("Associate", "true") if not exclude: options = PA.SHOW_ROI_MASKS \ + PA.SHOW_RESULTS \ + PA.DISPLAY_SUMMARY \ + PA.ADD_TO_MANAGER \ + PA.ADD_TO_OVERLAY \ if exclude: options = PA.SHOW_ROI_MASKS \ + PA.SHOW_RESULTS \ + PA.DISPLAY_SUMMARY \ + PA.ADD_TO_MANAGER \ + PA.ADD_TO_OVERLAY \ + PA.EXCLUDE_EDGE_PARTICLES if not addROIManager: if not exclude: options = PA.SHOW_ROI_MASKS \ + PA.SHOW_RESULTS \ + PA.DISPLAY_SUMMARY \ + PA.ADD_TO_OVERLAY \ if exclude: options = PA.SHOW_ROI_MASKS \ + PA.SHOW_RESULTS \ + PA.DISPLAY_SUMMARY \ + PA.ADD_TO_OVERLAY \ + PA.EXCLUDE_EDGE_PARTICLES measurements = PA.STACK_POSITION \ + PA.LABELS \ + PA.AREA \ + PA.RECT \ + PA.PERIMETER \ + PA.SLICE \ + PA.SHAPE_DESCRIPTORS \ + PA.CENTER_OF_MASS \ + PA.CENTROID results = ResultsTable() p = PA(options, measurements, results, minsize, maxsize, mincirc, maxcirc) p.setHideOutputImage(True) particlestack = ImageStack(imp.getWidth(), imp.getHeight()) for i in range(imp.getStackSize()): imp.setSliceWithoutUpdate(i + 1) ip = imp.getProcessor() # convert to a mask for the particle analyzer ip.invert() # do the particle analysis p.analyze(imp, ip) mmap = p.getOutputImage() # add the slide to the full stack particlestack.addSlice(mmap.getProcessor()) return particlestack, results
def analyze_homogeneity(image_title): IJ.selectWindow(image_title) raw_imp = IJ.getImage() IJ.run(raw_imp, "Duplicate...", "title=Homogeneity duplicate") IJ.selectWindow('Homogeneity') hg_imp = IJ.getImage() # Get a 2D image if hg_imp.getNSlices() > 1: IJ.run(hg_imp, "Z Project...", "projection=[Average Intensity]") hg_imp.close() IJ.selectWindow('MAX_Homogeneity') hg_imp = IJ.getImage() hg_imp.setTitle('Homogeneity') # Blur and BG correct the image IJ.run(hg_imp, 'Gaussian Blur...', 'sigma=' + str(HOMOGENEITY_RADIUS) + ' stack') # Detect the spots IJ.setAutoThreshold(hg_imp, HOMOGENEITY_THRESHOLD + " dark") rm = RoiManager(True) table = ResultsTable() pa = ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, ParticleAnalyzer.EXCLUDE_EDGE_PARTICLES, Measurements.AREA, # measurements table, # Output table 0, # MinSize 500, # MaxSize 0.0, # minCirc 1.0) # maxCirc pa.setHideOutputImage(True) pa.analyze(hg_imp) areas = table.getColumn(table.getHeadings().index('Area')) median_areas = compute_median(areas) st_dev_areas = compute_std_dev(areas, median_areas) thresholds_areas = (median_areas - (2 * st_dev_areas), median_areas + (2 * st_dev_areas)) roi_measurements = {'integrated_density': [], 'max': [], 'area': []} IJ.setForegroundColor(0, 0, 0) for roi in rm.getRoisAsArray(): hg_imp.setRoi(roi) if REMOVE_CROSS and hg_imp.getStatistics().AREA > thresholds_areas[1]: rm.runCommand('Fill') else: roi_measurements['integrated_density'].append(hg_imp.getStatistics().INTEGRATED_DENSITY) roi_measurements['max'].append(hg_imp.getStatistics().MIN_MAX) roi_measurements['integrated_densities'].append(hg_imp.getStatistics().AREA) rm.runCommand('Delete') measuremnts = {'mean_integrated_density': compute_mean(roi_measurements['integrated_density']), 'median_integrated_density': compute_median(roi_measurements['integrated_density']), 'std_dev_integrated_density': compute_std_dev(roi_measurements['integrated_density']), 'mean_max': compute_mean(roi_measurements['max']), 'median_max': compute_median(roi_measurements['max']), 'std_dev_max': compute_std_dev(roi_measurements['max']), 'mean_area': compute_mean(roi_measurements['max']), 'median_area': compute_median(roi_measurements['max']), 'std_dev_area': compute_std_dev(roi_measurements['max']), } # generate homogeinity image # calculate interpoint distance in pixels nr_point_columns = int(sqrt(len(measuremnts['mean_max']))) # TODO: This is a rough estimation that does not take into account margins or rectangular FOVs inter_point_dist = hg_imp.getWidth() / nr_point_columns IJ.run(hg_imp, "Maximum...", "radius="+(inter_point_dist*1.22)) # Normalize to 100 IJ.run(hg_imp, "Divide...", "value=" + max(roi_measurements['max'] / 100)) IJ.run(hg_imp, "Gaussian Blur...", "sigma=" + (inter_point_dist/2)) hg_imp.getProcessor.setMinAndMax(0, 255) # Create a LUT based on a predefined threshold red = zeros(256, 'b') green = zeros(256, 'b') blue = zeros(256, 'b') acceptance_threshold = HOMOGENEITY_ACCEPTANCE_THRESHOLD * 256 / 100 for i in range(256): red[i] = (i - acceptance_threshold) green[i] = (i) homogeneity_LUT = LUT(red, green, blue) hg_imp.setLut(homogeneity_LUT) return hg_imp, measuremnts
def nucleusSegmentation(imp2): """ Segmentation of nucleus image. Nucleus are selected that: 1. No overlapping with dilated regions 2. close to circular shape. Deformed nuclei are rejected. Outputs a binary image. """ #Convert to 8bit ImageConverter(imp2).convertToGray8() #blur slightly using Gaussian Blur radius = 2.0 accuracy = 0.01 GaussianBlur().blurGaussian( imp2.getProcessor(), radius, radius, accuracy) # Auto Local Thresholding imps = ALT().exec(imp2, "Bernsen", 15, 0, 0, True) imp2 = imps[0] #ParticleAnalysis 0: prefiltering by size and circularity rt = ResultsTable() paOpt = PA.CLEAR_WORKSHEET +\ PA.SHOW_MASKS +\ PA.EXCLUDE_EDGE_PARTICLES +\ PA.INCLUDE_HOLES #+ \ # PA.SHOW_RESULTS measOpt = PA.AREA + PA.STD_DEV + PA.SHAPE_DESCRIPTORS + PA.INTEGRATED_DENSITY MINSIZE = 20 MAXSIZE = 10000 pa0 = PA(paOpt, measOpt, rt, MINSIZE, MAXSIZE, 0.8, 1.0) pa0.setHideOutputImage(True) pa0.analyze(imp2) imp2 = pa0.getOutputImage() # Overwrite imp2.getProcessor().invertLut() #impNuc = imp2.duplicate() ## for the ring. impNuc = Duplicator().run(imp2) #Dilate the Nucleus Area ## this should be 40 pixels in Cihan's method, but should be smaller. #for i in range(20): # IJ.run(imp2, "Dilate", "") rf = RankFilters() rf.rank(imp2.getProcessor(), RIMSIZE, RankFilters.MAX) #Particle Analysis 1: get distribution of sizes. paOpt = PA.CLEAR_WORKSHEET +\ PA.SHOW_NONE +\ PA.EXCLUDE_EDGE_PARTICLES +\ PA.INCLUDE_HOLES #+ \ # PA.SHOW_RESULTS measOpt = PA.AREA + PA.STD_DEV + PA.SHAPE_DESCRIPTORS + PA.INTEGRATED_DENSITY rt1 = ResultsTable() MINSIZE = 20 MAXSIZE = 10000 pa = PA(paOpt, measOpt, rt1, MINSIZE, MAXSIZE) pa.analyze(imp2) #rt.show('after PA 1') #particle Analysis 2: filter nucleus by size and circularity. #print rt1.getHeadings() if (rt1.getColumnIndex('Area') > -1): q1, q3, outlier_offset = getOutlierBound(rt1) else: q1 = MINSIZE q3 = MAXSIZE outlier_offset = 0 print imp2.getTitle(), ": no Nucleus segmented,probably too many overlaps" paOpt = PA.CLEAR_WORKSHEET +\ PA.SHOW_MASKS +\ PA.EXCLUDE_EDGE_PARTICLES +\ PA.INCLUDE_HOLES #+ \ # PA.SHOW_RESULTS rt2 = ResultsTable() #pa = PA(paOpt, measOpt, rt, q1-outlier_offset, q3+outlier_offset, circq1-circoutlier_offset, circq3+circoutlier_offset) pa = PA(paOpt, measOpt, rt2, q1-outlier_offset, q3+outlier_offset, 0.8, 1.0) pa.setHideOutputImage(True) pa.analyze(imp2) impDilatedNuc = pa.getOutputImage() #filter original nucleus filteredNuc = ImageCalculator().run("AND create", impDilatedNuc, impNuc) return filteredNuc