Beispiel #1
0
def cvt_32_bit_to_8_bit(imp):
    """
	cvt_32_bit_to_8_bit(imp)

	Convert a 32 bit image to an 8-bit grayscale

	Parameters
	==========
	imp:	ImagePlus
		The ImagePlus of a 32 bit/px image to convert

	Returns
	=======
	wrk:	ImagePlus
		The ImagePlus with the 8-bit/px image
		
	"""
    imp.show()
    wrk = imp.duplicate()
    ic = ImageConverter(wrk)
    ic.convertToGray8()
    title = imp.getTitle()
    wrk.setTitle(title + "_g8")
    wrk.updateImage()
    return wrk
def cvt_32_bit_to_8_bit(imp):
	"""
	cvt_32_bit_to_8_bit(imp)

	Convert a 32 bit image to an 8-bit grayscale

	Parameters
	==========
	imp:	ImagePlus
		The ImagePlus of a 32 bit/px image to convert

	Returns
	=======
	wrk:	ImagePlus
		The ImagePlus with the 8-bit/px image
		
	"""
	imp.show()
	wrk = imp.duplicate()
	ic = ImageConverter(wrk)
	ic.convertToGray8()
	title = imp.getTitle()
	wrk.setTitle(title + "_g8")
	wrk.updateImage()
	return wrk
Beispiel #3
0
def run():
    helpText = "This program will batch convert any tif image to 8-bit greyscale, " + \
               "and empty calibration infomation.\n\n" + \
               ">> Press OK to Select a directory of TIFF images."
    MessageDialog(IJ.getInstance(), "Empty Calibration Guide", helpText)

    srcDir = DirectoryChooser("Chose Source Dir").getDirectory()
    if srcDir is None:
        IJ.log("Choose Dir Canceled!")
        return

    for root, directories, filenames in os.walk(srcDir):
        for filename in filenames:
            if not filename.endswith(".tif"):
                continue
            imgPath = os.path.join(root, filename)
            outPath = os.path.join(root, "decal-" + filename)

            imp = IJ.openImage(imgPath)
            imp.setCalibration(Calibration())
            ic = ImageConverter(imp)
            ic.convertToGray8()
            IJ.saveAsTiff(imp, outPath)
            print "removed calibration and saved to ", os.path.basename(
                outPath)
Beispiel #4
0
def convertAndSaveFile(fullFilePath, convertTo8Bit=False, allowOverwrite=False):
	"""
	"""
	print('  convertAndSaveFile() fullFilePath:', fullFilePath)
	
	folderPath, fileName = os.path.split(fullFilePath)
	fileNameNoExtension = os.path.splitext(fileName)[0]
	saveFileNoExtension = os.path.join(folderPath, fileNameNoExtension)
	
	#
	# load file and build a dict of parameters like (channels, pixels, voxels)
	myFileInfo, imp = bSimpleFileInfo.myLoadFile(fullFilePath, doShow=True)
	
	if convertTo8Bit:
		# from (ImagePlus.GRAY8, ImagePlus.GRAY16, ImagePlus.GRAY32, ImagePlus.COLOR_256 or ImagePlus.COLOR_RGB)
		myType = imp.getType()
		if myType in [1,2]:
			ic = ImageConverter(imp) # converts channelImp in place
			scaleConversions = True
			ic.setDoScaling(scaleConversions) # scales inensities to fill 0...255
			ic.convertToGray8()		

	#
	# split channels
	channelArray = ChannelSplitter.split(imp) # returns an array of imp
	
	for channelIdx, channelImp in enumerate(channelArray):
		# channelImp is an imp, this will NOT have fileinfo (we just created it)
		#channelImp.show()
		
		saveFilePath = saveFileNoExtension + '_ch' + str(channelIdx+1) + '.tif'
		print('    ch:', channelIdx+1, 'saveFilePath:', saveFilePath)
		
		if not allowOverwrite and os.path.isfile(saveFilePath):
			print(' .   not saving, file already exists', saveFilePath)
		else:
			IJ.save(channelImp, saveFilePath)

	return myFileInfo
Beispiel #5
0
def run():
    helpText = "This program will batch convert any tif image to 8-bit greyscale, " + \
               "and empty calibration infomation.\n\n" + \
               ">> Press OK to Select a directory of TIFF images."
    MessageDialog(IJ.getInstance(),"Empty Calibration Guide", helpText)

    srcDir = DirectoryChooser("Chose Source Dir").getDirectory()
    if srcDir is None:
        IJ.log("Choose Dir Canceled!")
        return

    for root, directories, filenames in os.walk(srcDir):
        for filename in filenames:
            if not filename.endswith(".tif"):
                continue
            imgPath = os.path.join(root, filename)
            outPath = os.path.join(root, "decal-" + filename)

            imp = IJ.openImage(imgPath)
            imp.setCalibration(Calibration())
            ic = ImageConverter(imp)
            ic.convertToGray8()
            IJ.saveAsTiff(imp, outPath)
            print "removed calibration and saved to ", os.path.basename(outPath)
def getGrayScaleImage(currIP, c, chanName, cfg):
    if (cfg.hasValue(ELMConfig.upperLeftExclusionX)):
        ulExclusionX = cfg.getValue(ELMConfig.upperLeftExclusionX)
    else:
        ulExclusionX = 0

    if (cfg.hasValue(ELMConfig.upperLeftExclusionY)):
        ulExclusionY = cfg.getValue(ELMConfig.upperLeftExclusionY)
    else:
        ulExclusionY = 0

    if (cfg.hasValue(ELMConfig.lowerRightExclusionX)):
        lrExclusionX = cfg.getValue(ELMConfig.lowerRightExclusionX)
    else:
        lrExclusionX = currIP.getWidth()

    if (cfg.hasValue(ELMConfig.lowerRightExclusionY)):
        lrExclusionY = cfg.getValue(ELMConfig.lowerRightExclusionY)
    else:
        lrExclusionY = currIP.getHeight()

    imgType = currIP.getType()
    if (chanName in cfg.getValue(
            ELMConfig.chansToSkip)):  # Don't process skip channels
        currIP.close()
        return None
    elif imgType == ImagePlus.COLOR_RGB or imgType == ImagePlus.COLOR_256:
        if (chanName == ELMConfig.BRIGHTFIELD):
            toGray = ImageConverter(currIP)
            toGray.convertToGray8()
        elif (chanName == ELMConfig.BLUE) \
                or (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.RED) \
                or (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.GREEN): #
            chanIdx = 2
            if (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.RED):
                chanIdx = 0
            elif (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.GREEN):
                chanIdx = 1
            imgChanns = ChannelSplitter.split(currIP)
            currIP.close()
            currIP = imgChanns[chanIdx]

            # Clear the Exclusion zone, so it doesn't mess with  thresholding
            imgProc = currIP.getProcessor()
            imgProc.setColor(Color(0, 0, 0))
            imgProc.fillRect(lrExclusionX, lrExclusionY, currIP.getWidth(),
                             currIP.getHeight())
            imgProc.fillRect(0, 0, ulExclusionX, ulExclusionY)
        elif (chanName == ELMConfig.YELLOW):
            # Clear the Exclusion zone, so it doesn't mess with  thresholding
            imgProc = currIP.getProcessor()
            imgProc.setColor(Color(0, 0, 0))
            imgProc.fillRect(lrExclusionX, lrExclusionY, currIP.getWidth(),
                             currIP.getHeight())
            imgProc.fillRect(0, 0, ulExclusionX, ulExclusionY)

            # Create a new image that consists of the average of the red & green channels
            title = currIP.getTitle()
            width = currIP.getWidth()
            height = currIP.getHeight()
            newPix = ByteProcessor(width, height)
            for x in range(0, width):
                for y in range(0, height):
                    currPix = currIP.getPixel(x, y)
                    newPix.putPixel(x, y, (currPix[0] + currPix[1]) / 2)
            currIP.close()
            currIP = ImagePlus(title, newPix)
        else:
            print "ERROR: Unrecognized channel name! Name: " + chanName
            currIP.close()
            return None
    elif imgType == ImagePlus.GRAY16 or imgType == ImagePlus.GRAY32 or imgType == ImagePlus.GRAY8:
        if not imgType == ImagePlus.GRAY8:
            toGray = ImageConverter(currIP)
            toGray.convertToGray8()
    else:
        print "ERROR: Unrecognized channel name & image type! Channel: " + chanName + ", imgType: " + str(
            imgType)
        currIP.close()
        return None

    return currIP
def getThresholdedMask(currIP, c, z, t, chanName, cfg, wellPath, dbgOutDesc):
    if (cfg.hasValue(ELMConfig.upperLeftExclusionX)):
        ulExclusionX = cfg.getValue(ELMConfig.upperLeftExclusionX)
    else:
        ulExclusionX = 0

    if (cfg.hasValue(ELMConfig.upperLeftExclusionY)):
        ulExclusionY = cfg.getValue(ELMConfig.upperLeftExclusionY)
    else:
        ulExclusionY = 0

    if (cfg.hasValue(ELMConfig.lowerRightExclusionX)):
        lrExclusionX = cfg.getValue(ELMConfig.lowerRightExclusionX)
    else:
        lrExclusionX = currIP.getWidth()

    if (cfg.hasValue(ELMConfig.lowerRightExclusionY)):
        lrExclusionY = cfg.getValue(ELMConfig.lowerRightExclusionY)
    else:
        lrExclusionY = currIP.getHeight()

    imgType = currIP.getType()
    if (chanName in cfg.getValue(
            ELMConfig.chansToSkip)):  # Don't process skip channels
        currIP.close()
        return None
    elif imgType == ImagePlus.COLOR_RGB or imgType == ImagePlus.COLOR_256:
        if (chanName == ELMConfig.BRIGHTFIELD):
            toGray = ImageConverter(currIP)
            toGray.convertToGray8()
            if cfg.params[ELMConfig.imgType] == "png":
                darkBackground = True
            else:
                darkBackground = False
        elif (chanName == ELMConfig.BLUE) \
                or (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.RED) \
                or (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.GREEN): #
            chanIdx = 2
            if (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.RED):
                chanIdx = 0
            elif (cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.GREEN):
                chanIdx = 1
            imgChanns = ChannelSplitter.split(currIP)
            currIP.close()
            currIP = imgChanns[chanIdx]

            # Clear the Exclusion zone, so it doesn't mess with  thresholding
            imgProc = currIP.getProcessor()
            imgProc.setColor(Color(0, 0, 0))
            imgProc.fillRect(lrExclusionX, lrExclusionY, currIP.getWidth(),
                             currIP.getHeight())
            imgProc.fillRect(0, 0, ulExclusionX, ulExclusionY)
            darkBackground = True
        elif (chanName == ELMConfig.YELLOW):
            # Clear the Exclusion zone, so it doesn't mess with  thresholding
            imgProc = currIP.getProcessor()
            imgProc.setColor(Color(0, 0, 0))
            imgProc.fillRect(lrExclusionX, lrExclusionY, currIP.getWidth(),
                             currIP.getHeight())
            imgProc.fillRect(0, 0, ulExclusionX, ulExclusionY)

            # Create a new image that consists of the average of the red & green channels
            title = currIP.getTitle()
            width = currIP.getWidth()
            height = currIP.getHeight()
            newPix = ByteProcessor(width, height)
            for x in range(0, width):
                for y in range(0, height):
                    currPix = currIP.getPixel(x, y)
                    newPix.putPixel(x, y, (currPix[0] + currPix[1]) / 2)
            currIP.close()
            currIP = ImagePlus(title, newPix)
            darkBackground = True
        else:
            print "ERROR: Unrecognized channel name! Name: " + chanName
            currIP.close()
            return None
    elif imgType == ImagePlus.GRAY16 or imgType == ImagePlus.GRAY32 or imgType == ImagePlus.GRAY8:
        if (chanName == ELMConfig.BRIGHTFIELD):
            if cfg.params[ELMConfig.imgType] == "png":
                darkBackground = True
            else:
                darkBackground = False
        else:
            darkBackground = True

        if not imgType == ImagePlus.GRAY8:
            toGray = ImageConverter(currIP)
            toGray.convertToGray8()
    else:
        print "ERROR: Unrecognized channel name & image type! Channel: " + chanName + ", imgType: " + str(
            imgType)
        currIP.close()
        return None

    WindowManager.setTempCurrentImage(currIP)

    if cfg.getValue(ELMConfig.debugOutput):
        IJ.saveAs('png',
                  os.path.join(wellPath, "Processing_" + dbgOutDesc + ".png"))

    upperThreshImg = currIP.duplicate()

    # If threshold value is set, use it
    if (cfg.hasValue(ELMConfig.imageThreshold)):
        thresh = cfg.getValue(ELMConfig.imageThreshold)
        if (darkBackground):
            currIP.getProcessor().setThreshold(thresh, 255,
                                               ImageProcessor.NO_LUT_UPDATE)
        else:
            currIP.getProcessor().setThreshold(0, thresh,
                                               ImageProcessor.NO_LUT_UPDATE)
    else:  # Otherise, automatically compute threshold
        threshMethod = "Default"
        if cfg.hasValue(ELMConfig.thresholdMethod):
            threshMethod = cfg.getValue(ELMConfig.thresholdMethod)

        currIP.getProcessor().setAutoThreshold(threshMethod, darkBackground,
                                               ImageProcessor.NO_LUT_UPDATE)
        threshRange = currIP.getProcessor().getMaxThreshold(
        ) - currIP.getProcessor().getMinThreshold()
        #print "\t\tZ = " + str(z) + ", T = " + str(t) +  ", chan " + chanName + ": Using default threshold of minThresh: " + str(currIP.getProcessor().getMinThreshold()) + ", maxThresh: " + str(currIP.getProcessor().getMaxThreshold())
        if currIP.getType() != ImagePlus.GRAY8:
            print "\tChannel " + chanName + " is not GRAY8, instead type is %d" % currIP.getType(
            )
        if threshRange > cfg.getValue(ELMConfig.maxThreshRange):
            if (cfg.hasValue(ELMConfig.defaultThreshold)):
                thresh = cfg.getValue(ELMConfig.defaultThreshold)
                print "\t\tZ = " + str(z) + ", T = " + str(
                    t
                ) + ", chan " + chanName + ": Using default threshold of " + str(
                    thresh) + ", minThresh: " + str(currIP.getProcessor(
                    ).getMinThreshold()) + ", maxThresh: " + str(
                        currIP.getProcessor().getMaxThreshold())
                if (darkBackground):
                    currIP.getProcessor().setThreshold(
                        thresh, 255, ImageProcessor.NO_LUT_UPDATE)
                else:
                    currIP.getProcessor().setThreshold(
                        0, thresh, ImageProcessor.NO_LUT_UPDATE)
            else:
                print "\t\tZ = " + str(z) + ", T = " + str(
                    t
                ) + ", chan " + chanName + ": Ignored Objects due to threshold range! minThresh: " + str(
                    currIP.getProcessor().getMinThreshold(
                    )) + ", maxThresh: " + str(
                        currIP.getProcessor().getMaxThreshold())
                currIP.close()
                return None

    IJ.run(currIP, "Convert to Mask", "")

    # Clear out exclusion zones
    imgProc = currIP.getProcessor()
    imgProc.fillRect(lrExclusionX, lrExclusionY, currIP.getWidth(),
                     currIP.getHeight())
    imgProc.fillRect(0, 0, ulExclusionX, ulExclusionY)

    IJ.run(currIP, "Close-", "")

    # Brightfield has an additional thresholding step
    if cfg.getValue(ELMConfig.chanLabel)[c] == ELMConfig.BRIGHTFIELD:
        if cfg.getValue(ELMConfig.debugOutput):
            IJ.saveAs(
                'png', os.path.join(wellPath,
                                    "OrigMask_" + dbgOutDesc + ".png"))

        upperThresh = 255 * 0.95
        upperThreshImg.getProcessor().setThreshold(
            upperThresh, 255, ImageProcessor.NO_LUT_UPDATE)
        IJ.run(upperThreshImg, "Convert to Mask", "")
        IJ.run(upperThreshImg, "Close-", "")
        if cfg.getValue(ELMConfig.debugOutput):
            WindowManager.setTempCurrentImage(upperThreshImg)
            IJ.saveAs(
                'png',
                os.path.join(wellPath,
                             "UpperThreshMask_" + dbgOutDesc + ".png"))

        ic = ImageCalculator()
        compositeMask = ic.run("OR create", currIP, upperThreshImg)
        IJ.run(compositeMask, "Close-", "")
        currIP.close()
        currIP = compositeMask
        WindowManager.setTempCurrentImage(currIP)

    if cfg.getValue(ELMConfig.debugOutput):
        WindowManager.setTempCurrentImage(currIP)
        IJ.saveAs('png', os.path.join(wellPath,
                                      "Binary_" + dbgOutDesc + ".png"))

    upperThreshImg.close()
    return currIP
Beispiel #8
0
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 run(imagefile):

    # Opening the image
    log.info('Opening Image: ' + imagefile)

    # open image file and get a specific series
    imp, MetaInfo = ImportTools.openfile(imagefile)

    log.info('File Extension   : ' + MetaInfo['Extension'])
    if 'ResolutionCount' in MetaInfo:
        log.info('Resolution Count : ' + str(MetaInfo['ResolutionCount']))
    if 'SeriesCount' in MetaInfo:
        log.info('SeriesCount      : ' + str(MetaInfo['SeriesCount']))
    if 'SizeC' in MetaInfo:
        log.info('Channel Count    : ' + str(MetaInfo['SizeC']))

    # do the processing
    log.info('Start Processing ...')

    # get the correct channel
    if MetaInfo['SizeC'] > 1:
        log.info('Extract Channel  : ' + str(MetaInfo['ChannelCount']))
        imps = ChannelSplitter.split(imp)
        imp = imps[CHINDEX - 1]

    # convert to 8bit grayscale
    ic = ImageConverter(imp)
    ic.convertToGray8()

    if FILL_HOLES:
        # 3D fill holes
        log.info('3D Fill Holes ...')
        imp = Reconstruction3D.fillHoles(imp.getImageStack())

    if not FILL_HOLES:
        imp = imp.getImageStack()

    # run watershed on stack
    weights = ChamferWeights3D.BORGEFORS.getFloatWeights()
    normalize = True
    dynamic = 2
    connectivity = LABEL_CONNECT
    log.info('Applying Run Watershed to separate particles ...')
    #dist = BinaryImages.distanceMap(imp.getImageStack(), weights, normalize)
    dist = BinaryImages.distanceMap(imp, weights, normalize)
    Images3D.invert(dist)
    #imp = ExtendedMinimaWatershed.extendedMinimaWatershed(dist, imp.getImageStack(), dynamic, connectivity, 32, False )
    imp = ExtendedMinimaWatershed.extendedMinimaWatershed(
        dist, imp, dynamic, connectivity, 32, False)

    # extend borders
    log.info('Applying Border Extension ...')
    # create BorderManager and add Zeros in all dimensions
    bmType = BorderManager3D.Type.fromLabel("BLACK")
    bm = bmType.createBorderManager(imp)
    #bm = bmType.createBorderManager(imp.getStack())
    BorderExt = ExtendBordersPlugin()
    # extend border by always exb
    #imp = BorderExt.process(imp.getStack(), EXB, EXB, EXB, EXB, EXB, EXB, bm)
    imp = BorderExt.process(imp, EXB, EXB, EXB, EXB, EXB, EXB, bm)
    # convert back to ImgPlus
    pastack = ImagePlus('Particles', imp)

    # check for pixel in 3d by size
    log.info('Filtering VoxelSize - Minimum : ' + str(MINVOXSIZE))
    pastack = BinaryImages.volumeOpening(pastack.getStack(), MINVOXSIZE)
    imp = ImagePlus('Particles Filtered', pastack)
    pastack = BinaryImages.componentsLabeling(imp, LABEL_CONNECT,
                                              LABEL_BITDEPTH)

    # get the labels
    labels = LabelImages.findAllLabels(pastack)
    log.info('Labels Filtered : ' + str(len(labels)))

    # run 3D particle analysis
    log.info('3D Particle Analysis ...')
    PA3d = ParticleAnalysis3DPlugin()
    results = PA3d.process(pastack)

    # colorize the labels
    if LABEL_COLORIZE:

        log.info('Colorize Lables ...')
        #maxLabel = 255
        maxLabel = len(labels)
        bgColor = Color.BLACK
        shuffleLut = True
        lutName = CommonLabelMaps.GOLDEN_ANGLE.getLabel()

        # Create a new LUT from info in dialog
        lut = CommonLabelMaps.fromLabel(lutName).computeLut(
            maxLabel, shuffleLut)

        #  Create a new RGB image from index image and LUT options
        pastack_rgb = LabelImages.labelToRgb(pastack, lut, bgColor)

        # convert to rgb color
        IJ.run(pastack_rgb, "RGB Color", "slices")

    if LABEL_COLORIZE:
        return pastack_rgb, results, labels
    elif not LABEL_COLORIZE:
        return pastack, results, labels
Beispiel #10
0
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)
Beispiel #11
0
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)
Beispiel #12
0
def runEDM(imp=None):

    print('=== runEDM()')

    #
    # get info from original imp (make a copy below)
    myInfoDict = simpleFileInfo.getImpInfo(imp, '')
    print(json.dumps(myInfoDict, indent=4))
    filePath = myInfoDict['filePath']
    filePathNoExtension = filePath.split('.')[
        0]  # assuming folders in path DO NOT have '.'
    print(' .  filePathNoExtension:', filePathNoExtension)

    impOriginalWindowTitle = imp.getTitle()

    #
    # make a copy of imp
    print(imp)
    print(' . === making copy of imp')
    imp = imp.duplicate()
    imp.show()

    #
    # work on the copy image (mean and mask will be performed on this copy 'in place')
    impWindowTitle = imp.getTitle()
    impImage = impWindowTitle.split('.')[0]  # used by 3D Distance Map
    print(' .  impWindowTitle:', impWindowTitle)
    print('   impImage:', impImage)

    #
    # mean
    print(' . === mean 3D filter')
    IJ.run("Mean 3D...", "x=3 y=3 z=2")

    #
    # threshold
    #IJ.setAutoThreshold("Otsu dark")
    #IJ.setOption("BlackBackground", true);
    print(' . === Otsu threshold')
    IJ.run("Convert to Mask", "method=Otsu background=Dark calculate")

    # invert
    IJ.run("Invert LUT")

    #
    # fill holes
    print(' . === fill holes')
    IJ.run("3D Fill Holes")  # does not seem to do anything ???
    '''
	# 3d mean ch1
	...
	# convert ch1 to mask
	selectWindow("20200420_distalHEAD__ch1.tif");
	setAutoThreshold("Default dark");
	//run("Threshold...");
	setAutoThreshold("Otsu dark");
	setOption("BlackBackground", false);
	run("Convert to Mask", "method=Otsu background=Dark calculate");
	run("Close");
	#
	# run 3d distance map, outputs two windows (EVF, EDT)
	#
	# v1, I thought this was working ???
	run("3D Distance Map", "map=Both image=20200420_distalHEAD__ch1 mask=20200420_distalHEAD__ch2_mask threshold=1 inverse");
	convert output evf to 8-bit
	output evf has (maybe don't convert to 8-bit???)
		-1: where there was no mask in ch1 (after 8-bit is 128)
		0: where there was a mask in ch2 (after 8-bit is 0)
		value: distance between point in ch1 mask and nearest point in ch2 mask
	#
	# v2, now this seems to be working (neither mask has inverted LUT)
	# here, 20200420_distalHEAD__ch1-1 is a mask of channel
	# run("3D Distance Map", "map=Both image=20200420_distalHEAD__ch2_mask mask=20200420_distalHEAD__ch1-1 threshold=1 inverse");
	'''

    #
    # 3d distance map (makes EDT window)
    print(' . === 3d euclidean distance map (EDM) ... please wait')
    paramStr = 'map=EDT image=' + impImage + ' mask=Same threshold=1 inverse'  # inverse?
    #IJ.run("3D Distance Map", "map=EDT image=20200420_distalHEAD__ch2 mask=Same threshold=1 inverse")
    IJ.run("3D Distance Map", paramStr)

    edmImp = WindowManager.getCurrentImage()
    print(' .  edmImp:', edmImp)

    # convert 32-bit edm to 8-bit
    ic = ImageConverter(edmImp)  # converts channelImp in place
    scaleConversions = True
    ic.setDoScaling(scaleConversions)  # scales inensities to fill 0...255
    ic.convertToGray8()
    print(' .  edmImp:', edmImp)

    #
    # save
    IJ.selectWindow(impWindowTitle)
    maskPath = filePathNoExtension + '_mask.tif'
    print(' .  === saving maskPath:', maskPath)
    IJ.saveAs("Tiff", maskPath)

    IJ.selectWindow("EDT")
    edmPath = filePathNoExtension + '_edm.tif'
    print(' .  === saving edmPath:', edmPath)
    IJ.saveAs("Tiff", edmPath)

    #
    # set both (mask and edm) changes=false (we save them)
    imp.changes = False
    edmImp.changes = False

    #
    # output, merge channels into composite
    # contrast adjust edmp
    print(' .  === contrast adjust edm')
    edmPath, edmFile = os.path.split(edmPath)
    IJ.selectWindow(edmFile)
    IJ.run("Enhance Contrast", "saturated=0.35")
    # not sure how to calculate auto, 0.35 will be different !!!
    IJ.run("Apply LUT", "stack")
    # merge into composite
    print(' .  === merging into composite')
    #impOriginalWindowTitle was assigned right at start
    maskWindowTitle = imp.getTitle(
    )  # (mean, threshold) was done in place on copy
    edmWindowTitle = edmImp.getTitle()
    # run("Merge Channels...", "c1=20200420_distalHEAD__ch2.tif c2=20200420_distalHEAD__ch2_mask.tif c3=20200420_distalHEAD__ch2_edm.tif create keep ignore");
    paramStr = 'c1=' + impOriginalWindowTitle + ' c2=' + maskWindowTitle + ' c3=' + edmWindowTitle + ' create keep ignore'
    IJ.run("Merge Channels...", paramStr)
Beispiel #13
0
	#image = ImagePlus("test", twochannel_stack)
	#fs = FileSaver(image)
	#filepath = directory + "/" + filename + "_twochannel.tif" 
	#fs.saveAsTiff(filepath) 
	image_dapi = ImagePlus("dapi stack", dapi_stack)
	image_dapi.show()
	image_green = ImagePlus("green stack", green_stack)
	image_green.show()
	image = ImagePlus("two channel stack", twochannel_stack)
	image.show()
	

	
	if auto_thresh:
		con = ImageConverter(image)
		con.convertToGray8()
		IJ.run(image, "Auto Local Threshold", "method=Bernsen radius=15 parameter_1=0 parameter_2=0 white stack")
		#image = CompositeImage(image_two)
	#image = IJ.getImage()
	z_slices = image.getDimensions()[3] / 2
	
	print("order=xyczt(default) channels=2 slices="+ str(z_slices) + " frames=1 display=Color", image.getDimensions())
	image_two = HyperStackConverter.toHyperStack(image,2,z_slices,1)
	image = CompositeImage(image_two)
	image.show()
	
	rt = run_comdet(image)
	rt.save(directory+"/"+filename+"_results.csv" )
	
	image = IJ.getImage()
	if auto_cell:
Beispiel #14
0
    dapi_stack = retrieve_dapi(image, channel)
    image.close()
    #image = ImagePlus("test", twochannel_stack)
    #fs = FileSaver(image)
    #filepath = directory + "/" + filename + "_twochannel.tif"
    #fs.saveAsTiff(filepath)
    image_dapi = ImagePlus("dapi stack", dapi_stack)
    image_dapi.show()
    image_green = ImagePlus("green stack", green_stack)
    image_green.show()
    image = ImagePlus("two channel stack", twochannel_stack)
    image.show()

    if auto_thresh:
        con = ImageConverter(image)
        con.convertToGray8()
        IJ.run(
            image, "Auto Local Threshold",
            "method=Bernsen radius=15 parameter_1=0 parameter_2=0 white stack")
        #image = CompositeImage(image_two)
    #image = IJ.getImage()
    z_slices = image.getDimensions()[3] / 2

    print(
        "order=xyczt(default) channels=2 slices=" + str(z_slices) +
        " frames=1 display=Color", image.getDimensions())
    image_two = HyperStackConverter.toHyperStack(image, 2, z_slices, 1)
    image = CompositeImage(image_two)
    image.show()

    rt = run_comdet(image)
Beispiel #15
0
  frame_stack = channel_splitter.getChannel(frame, channel) # ImageStack
  frame = ImagePlus("Channel " + str(channel), frame_stack)

  # Map signal to entire 16-bit range
  contrast_enhancer.stretchHistogram(frame, 0.01)
  processor = frame.getProcessor()
  if(processor.getBitDepth() == 32):
    processor.setMinAndMax(0, 1.0)
  else:
    processor.setMinAndMax(0, processor.maxValue())

  frame = ImagePlus("Frame " + str(frame_i), processor)

  # Convert to 8-bit, grayscale
  converter = ImageConverter(frame)
  converter.convertToGray8()

  # Perform median filtering
  processor = frame.getProcessor()

  filters = RankFilters()
  filters.setup("median", frame)
  filters.rank(processor, filter_window, filters.MEDIAN)

  # Perform gamma correction
  processor.gamma(gamma)

  frame = ImagePlus("Frame " + str(frame_i), processor)

  # Rolling ball background subtraction
  processor = frame.getProcessor()
Beispiel #16
0
def analyse(cwd, user, imagefolder, stats, experiments, multi, Rloc2,
            subfoldernames, names, statsfolderPath, cwdR):
    """ Main image analysis
        Gets user image analysis settings from the .csv file.
        If multiple experiments have been selected by the user
        (multi) each subfolder will be looped through. A nested
        loop will then interate through each .tif image and
        analyse. A .csv file will be produced for each folder
        analysed with the name of each image and its % neurite
        density and % myelination. A summary csv file will also
        be produced with the average % neurite density and %
        myelination for each subfolder. If statistical analysis
        has been selected (stats) then MyelinJ's Rscript will be
        run via the command line. If multple experiments is not
        selected then all of the images within the selected
        folder will be analysed together and no summary .csv will
        be produced.
        Independ of the analysis settings defined, a processed
        myelin channel image and a processed neurite channel
        image will be saved. The images can be any number of
        subdirectories (folders within folders).
        Parameters
        ----------
        cwd : string
            Path for current working directory (location of
            MyelinJ folder in Fiji).
        user: string
            User name
        imagefolder: string
            Path to .tiff image folder(s) defined by user.
        stats: boolean
            Perform statistical analysing using R?
        experiments: 2D list of strings
            list of all the subfolders (experiments) that are in each
            experimental condition.
        multi: boolean
            Analyse multiple experiments?
        Rloc2: string
            file path to Rscript location
        subfoldernames: string
            name of each subfolder which denoates each individual
            experiment, if multple experiments are being analysed.
        names: array
            array of textfields for each experimental condition defined by
            user. User will enter the name of each experimental condition.
        statsfolderPath: string
            file path to the create statsfolder.
        cwdR: string
            file path to MyelinJstats.R
        """
    # read settings from the user name CSV
    bg = False
    readsettings = []
    imagenames = []
    neuritedensity = []
    myelinoverlay = []
    myelinaverage2 = []
    neuriteaverage2 = []
    root = cwd
    filename = user
    fullpath = os.path.join(root, filename)
    f = open(fullpath, 'rb')
    readCSV = csv.reader(f)
    for row in readCSV:
        readsettings.append(row[0])
        readsettings.append(row[1])
        readsettings.append(row[2])
        readsettings.append(row[3])
        readsettings.append(row[4])
        readsettings.append(row[5])
        readsettings.append(row[6])
    f.close()
    i = 0

    for i in range(len(subfoldernames)):
        # if multiple experimental conditions has been selected each folder is treated as a
        # separate experiment and looped through separately otherwise all folders will be
        # treated as one experiment this only works for sub directories within the main folder.
        # Further folders will be ignored (each image can be in its own folder for example)
        if multi is True:
            # if multiple experiments are being analysed the file path is changed to the
            # current subfolder
            settings2 = os.path.join(imagefolder, subfoldernames[i])
            if "Windows" in OS:
                settings2 = settings2 + "\\"
            elif "Mac" in OS:
                settings2 = settings2 + "/"
        else:
            settings2 = imagefolder
        # loop through all .tiff files in location
        for root, dirs, files in os.walk(settings2):
            for name in files:
                if name.endswith((".tif")):
                    imagenames.append(os.path.join(name))
                    # open .tiff image, split channels and
                    # convert to 8bit grey scale.
                    imp = IJ.openImage(os.path.join(root, name))
                    g = int(readsettings[4])
                    r = int(readsettings[5])
                    imp = ChannelSplitter.split(imp)
                    green = imp[g]
                    red = imp[r]
                    conv = ImageConverter(red)
                    conv.convertToGray8()
                    conv = ImageConverter(green)
                    conv.convertToGray8()

                    # thresholding to select cell bodies
                    green2 = green.duplicate()
                    if (readsettings[0] != "0") or (readsettings[1] != "0"):
                        bg = True
                        IJ.setAutoThreshold(green2, readsettings[2])
                        IJ.setRawThreshold(green2, int(readsettings[0]),
                                           int(readsettings[1]), None)
                        Prefs.blackBackground = True
                        IJ.run(green2, "Convert to Mask", "")
                        IJ.run(green2, "Invert LUT", "")
                        if readsettings[7] != "0":
                            IJ.run(green2, "Make Binary", "")
                            IJ.run(
                                green2, "Remove Outliers...", "radius=" +
                                readsettings[7] + " threshold=50 which=Dark")

                    # CLAHE and background subtraction
                    if readsettings[8] == "True":
                        mpicbg.ij.clahe.Flat.getFastInstance().run(
                            green, 127, 256, 3, None, False)
                    if readsettings[9] == "True":
                        calc = ImageCalculator()
                        green = calc.run("Subtract create", green, red)
                    elif readsettings[6] == "True":
                        IJ.run(green, "Subtract Background...", "rolling=50")
                    if readsettings[10] != "0":
                        IJ.run(green, "Subtract...",
                               "value=" + readsettings[10])

                    # run frangi vesselness
                    pixelwidth = str(green.getCalibration().pixelWidth)
                    IJ.run(
                        green, "Frangi Vesselness (imglib, experimental)",
                        "number=1 minimum=" + pixelwidth + " maximum=" +
                        pixelwidth)
                    green = IJ.getImage()

                    # convert frangi vesselness image to 8bit grey scale
                    conv = ImageConverter(green)
                    conv.convertToGray8()
                    IJ.run(green, "Convert to Mask", "")

                    # remove cell bodies
                    if bg is True:
                        green = ImageCalculator().run("Subtract create", green,
                                                      green2)

                    # run grey scale morphology filter from MorpholibJ
                    if readsettings[11] != "0":
                        green = green.getProcessor()
                        algo = BoxDiagonalOpeningQueue()
                        algo.setConnectivity(4)
                        result = algo.process(green, int(readsettings[11]))
                        green = ImagePlus("result", result)
                    IJ.run(green, "Invert LUT", "")

                    if len(readsettings) > 14:
                        # sparse neurite image analysis
                        if readsettings[15] == "True":
                            IJ.run(
                                red, "Enhance Local Contrast (CLAHE)",
                                "blocksize=127 histogram=256 maximum=3 mask=*None* fast_(less_accurate)"
                            )
                        if readsettings[14] == "True":
                            IJ.run(red, "Subtract Background...", "rolling=50")
                        IJ.setAutoThreshold(red, readsettings[16])
                        IJ.setRawThreshold(red, int(readsettings[17]),
                                           int(readsettings[18]), None)
                        IJ.run(red, "Convert to Mask", "")
                        IJ.run(red, "Invert LUT", "")
                    else:
                        # dense neurite image analysis
                        IJ.run(
                            red, "Normalize Local Contrast",
                            "block_radius_x=40 block_radius_y=40 standard_deviations="
                            + readsettings[12] + " center stretch")
                        IJ.run(red, "Auto Threshold", "method=Default white")
                        IJ.run(red, "Invert LUT", "")
                    if readsettings[3] == "True":
                        IJ.run(red, "Despeckle", "")

                    IJ.saveAs(red, "Jpeg", settings2 + name + "neurites")
                    # get number of neurite pixels

                    # get number of neurite pixels
                    statsneurite = red.getProcessor()
                    statsneurite = statsneurite.getHistogram()
                    neuritedensity.append(statsneurite[255])
                    IJ.saveAs(green, "Jpeg", settings2 + name + "myelinFinal")

                    # get number of myelin pixels
                    statsmyelin = green.getProcessor()
                    statsmyelin = statsmyelin.getHistogram()
                    myelinoverlay.append(statsmyelin[255])
                    closeallimages()

                    # get pixel total of image
                    whitepixels = (statsneurite[0])
                    blackpixels = (statsneurite[255])

        totalpixels = whitepixels + blackpixels
        totalpixels = [totalpixels] * len(neuritedensity)

        # for each image calculate % myelination as number of myelin pixels
        # divided by the number of neurite pixels * 100
        myelinoverlay = [
            x1 / x2 * 100 for (x1, x2) in zip(myelinoverlay, neuritedensity)
        ]
        myelinaverage = sum(myelinoverlay) / len(myelinoverlay)
        myelinaverage2.append(myelinaverage)

        # for each image calculate % neurite density as neurite pixels divided
        # by the total number of pixels in the image * 100.
        neuritedensity = [
            x1 / x2 * 100 for (x1, x2) in zip(neuritedensity, totalpixels)
        ]
        neuriteaverage = sum(neuritedensity) / len(neuritedensity)
        neuriteaverage2.append(neuriteaverage)
        name = "Image names"
        green = "% myelination"
        red = "% neurite density"
        imagenames = [name] + imagenames
        neuritedensity = [red] + neuritedensity
        myelinoverlay = [green] + myelinoverlay
        result = []
        result.append(imagenames)
        result.append(neuritedensity)
        result.append(myelinoverlay)

        root = settings2
        filename = "Results.csv"
        fullpath = os.path.join(root, filename)
        f = open(fullpath, 'wb')
        writer = csv.writer(f)
        for d in range(len(result)):
            row = [result[d]]
            writer.writerows(row)
        f.close()

        # must be reset to 0 for each iteration.
        y = 0
        r = 0

        # if statistical analysis is being performed the results .csv file
        # is also saved to a subfolder within the statistical analysis folder
        # which denotes the experimental condition the results belong to.
        if stats is True:
            # nested for loop to identify correct experimental condition
            # for the current subfolder being analysed.
            for y in range(0, len(experiments)):
                for r in range(0, len(experiments[0])):
                    if experiments[y][r] == subfoldernames[i]:
                        if "Windows" in OS:
                            root = imagefolder + "\\statistical analysis\\" + names[
                                y].getText()
                        elif "Mac" in OS:
                            root = imagefolder + "/statistical analysis/" + names[
                                y].getText()
                        filename = subfoldernames[i] + ".csv"
                        fullpath = os.path.join(root, filename)
                        f = open(fullpath, 'wb')
                        writer = csv.writer(f)
                        for e in range(len(result)):
                            row = [result[e]]
                            writer.writerows(row)
                        f.close()

                        break
        cwd2 = os.getcwd()
        for files in os.listdir(cwd2):
            if files.endswith(".csv"):
                os.remove(os.path.join(cwd2, files))
        imagenames = []
        myelinoverlay = []
        neuritedensity = []

    # create .csv summary sheet with average % neurite density
    # and average % myelination for each subfolder (experiment).
    if multi is True:
        name = "Folder name"
        imagenames = [name] + subfoldernames
        neuritedensity = [red] + neuriteaverage2
        myelinoverlay = [green] + myelinaverage2
        result = []
        result.append(imagenames)
        result.append(neuritedensity)
        result.append(myelinoverlay)
        if "Windows" in OS:
            root = imagefolder + "\\"
        elif "Mac" in OS:
            root = imagefolder + "/"
        filename = "Result-Summary.csv"
        fullpath = os.path.join(root, filename)
        f = open(fullpath, 'wb')
        writer = csv.writer(f)
        for p in range(len(result)):
            row = [result[p]]
            writer.writerows(row)
        f.close()
        imagenames = []
        myelinoverlay = []
        neuritedensity = []

    # Run Rscript for statistical analysis via the command line
    if stats is True:
        cmd = Rloc2 + " " + cwdR + " " + statsfolderPath
        Runtime.getRuntime().exec(cmd)
    Finished()
def process(subFolder, outputDirectory, filename):

    roim = RoiManager()
    roim.close()

    imp = IJ.openImage(inputDirectory + subFolder + '/' +
                       filename.replace("_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()
    imp.updateAndDraw()
    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()

    imp.changes = False
    imp.close()

    x_amount = 10
    y_amount = 10

    l = 0
    j = 0
    while l < x_amount:
        k = 0
        while k < y_amount:
            copy = IJ.openImage(inputDirectory + subFolder + '/' +
                                filename.replace("_ch00.tif", ".tif"))
            Xposition = (int)(round((imp.width / x_amount) * l))
            Yposition = (int)(round((imp.width / y_amount) * k))
            Width = (int)(round(imp.width / x_amount))
            Height = (int)(round(imp.height / y_amount))
            roi = Roi(Xposition, Yposition, Width, Height)
            copy.setRoi(roi)
            IJ.run(copy, "Crop", "")
            FileSaver(copy).saveAsTiff(outputDirectory + '/' + filename +
                                       "_crop_" + str(j) + ".tif")
            copy.changes = False
            copy.close()

            for chan in channels:
                v, x = chan
                image = IJ.openImage(inputDirectory + subFolder + '/' +
                                     filename.replace("ch00.tif", "ch0" +
                                                      str(x) + ".tif"))
                roi = Roi(Xposition, Yposition, Width, Height)
                image.setRoi(roi)
                IJ.run(image, "Crop", "")
                FileSaver(image).saveAsTiff(outputDirectory + '/' + filename +
                                            "_crop_" + str(j) + "_ch0" +
                                            str(x) + ".tif")
                image.changes = False
                image.close()

            roim.close()

            k = k + 1
            j = j + 1

        l = l + 1

    imp.getProcessor().setThreshold(0, 0, ImageProcessor.NO_LUT_UPDATE)
    boundroi = ThresholdToSelection.run(imp)

    rm = RoiManager()
    rm.addRoi(boundroi)

    images = [None] * 5
    intensities = [None] * 5
    blobsarea = [None] * 5
    blobsnuclei = [None] * 5
    areas = [None] * 5

    for chan in channels:
        v, x = chan
        images[x] = IJ.openImage(inputDirectory + subFolder + '/' +
                                 filename.replace("ch00.tif", "ch0" + str(x) +
                                                  ".tif"))
        imp = images[x]
        for roi in rm.getRoiManager().getRoisAsArray():
            imp.setRoi(roi)
            stats = imp.getStatistics(Measurements.MEAN | Measurements.AREA)
            intensities[x] = stats.mean
            areas[x] = stats.area

    rm.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

    # Creates the fieldnames variable needed to create the csv file at the end.

    fieldnames = ['Name', 'Directory', 'Image']

    # Adds the columns for each individual marker (ignoring Dapi since it was used to count nuclei)

    summary["organoid-area"] = areas[x]
    fieldnames.append("organoid-area")

    for chan in channels:
        v, x = chan

        summary[v + "-intensity"] = intensities[x]
        fieldnames.append(v + "-intensity")

    # 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)
Beispiel #18
0
	for subfolder in subfolders:

		#Opens each image

		for filename in os.listdir(inputDirectory + subfolder): 
			imp = IJ.openImage(inputDirectory + subfolder + '/' + filename)	

			if imp:
				# 10X objective
				IJ.run(imp, "Properties...", "channels=1 slices=1 frames=1 unit=um pixel_width=" +str(pix_width)+ " pixel_height=" +str(pix_height)+" voxel_depth=25400.0508001")			# Change to a GUI option later?

				# Threshold, fills hole and watershed

				ic = ImageConverter(imp);
				ic.convertToGray8();
				IJ.setAutoThreshold(imp, "Default dark")

				if thresholdMode:
					imp.show()
					IJ.run("Threshold...")
					WaitForUserDialog("Title", "Adjust threshold").show()
				IJ.run(imp, "Convert to Mask", "")
				
				if not inverted:
					IJ.run(imp, "Invert", "")
				
				IJ.run(imp, "Fill Holes", "")
				
				if watershedMode:
					IJ.run(imp, "Watershed", "")
def Overlayer(org_size, dirs):
	""" Overlays ROIs with appropriate color,
	    saves to .tif and animates aligned images to .gif """
    
    # Get colors.
	Colors, Colors_old = colorlist()

    # Get ROImanager.
	rm = RoiManager().getInstance()
	rois = rm.getCount()
	
	# Overlays ROI on aligned images, converts to 8-bit (for gif).
	for root, directories, filenames in os.walk(dirs["Composites_Aligned"]):
		for filename in filenames:
			imp = IJ.openImage(os.path.join(root, filename))
			converter = ImageConverter(imp)
			converter.setDoScaling(True)
			converter.convertToGray8()

			# Lookup table and local contrast enhancement for vizualisation.
			IJ.run(imp, "Rainbow RGB", "")
			IJ.run(imp, "Enhance Local Contrast (CLAHE)", 
			       "blocksize=127 histogram=256 maximum=3 mask=*None*")

			
			for roi in range(rois):
				roi_obj = rm.getRoi(roi)
				roi_obj.setStrokeWidth(2)		
				if roi < 19:
					roi_obj.setStrokeColor(Color(*Colors[roi][0:3]))
				else:
					roi_obj.setStrokeColor(eval(Colors_old[roi]))
			
			
			rm.moveRoisToOverlay(imp)

			IJ.saveAs(imp, "Tiff", os.path.join(dirs["Overlays"], filename))
			
	# Opens overlaid images, saves as tiff stack.
	overlay_stack = IJ.run("Image Sequence...", "open="+dirs["Overlays"]+
					       " number=3040 starting=0 increment=1 scale=300 file=.tif sort")
	
	# Takes care of spaces in titles. 
	tiftitle = Title.replace(" ", "_")
	tiftitle = tiftitle.replace(".", "_")
	
	# Gets dimensions for scalebar.
	imp = WindowManager.getImage("Overlays")
	dimensions = imp.getDimensions()
	size = dimensions[0] + dimensions[1]
	microns = org_size / size

	# Sets scale and writes scale-bar, flattens overlays. 
	IJ.run(imp, "Set Scale...", "distance=1 known="
	       +str(microns)+" pixel=1 unit=micron")
           
	IJ.run(imp, "Scale Bar...", 
	    "width=10 height=4 font=14 color=Yellow background=None location=[Lower Right] bold overlay")
    
	IJ.run(imp, "Flatten", "stack")
	IJ.saveAs(imp, "Tiff", os.path.join(dirs["Gifs"], tiftitle))
	
	# Animates tiff stack from directoy. 
	for root, directories, filenames in os.walk(dirs["Gifs"]):
		for filename in filenames:		
			if tiftitle in filename and filename.endswith(".tif"):
				# set=xx parameter controls gif speed.
				# for additional parameters run with macro recorder.
				try:
					print "Animating gif..."
					imp = WindowManager.getImage(tiftitle + ".tif")
					gif = IJ.run("Animated Gif ... ", 
					             "set=200 number=0 filename="
					             + os.path.join(dirs["Gifs"], tiftitle + ".gif"))
				
				except Exception, e:
					print str(e)
				
				print "gif animated."
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)
Beispiel #21
0
        for filename in os.listdir(inputDirectory + subfolder):
            imp = IJ.openImage(inputDirectory + subfolder + '/' + filename)

            if imp:
                # 10X objective
                IJ.run(imp, "Properties...",
                       "channels=1 slices=1 frames=1 unit=um pixel_width=" +
                       str(pix_width) + " pixel_height=" + str(pix_height) +
                       " voxel_depth=25400.0508001"
                       )  # Change to a GUI option later?

                # Threshold, fills hole and watershed

                ic = ImageConverter(imp)
                ic.convertToGray8()
                IJ.setAutoThreshold(imp, "Default dark")

                if thresholdMode:
                    imp.show()
                    IJ.run("Threshold...")
                    WaitForUserDialog("Title", "Adjust threshold").show()
                IJ.run(imp, "Convert to Mask", "")
                IJ.run(imp, "Invert", "")
                IJ.run(imp, "Fill Holes", "")
                if not thresholdMode:
                    IJ.run(imp, "Watershed", "")

                #Measure particles

                table = ResultsTable()