def threshold_and_binarise(imp):
	"""Return thresholded stack"""
	print("performing segmentation on channel: " + imp.getTitle());
	stats = StackStatistics(imp);
	IJ.run(imp, "Subtract...", "value={} stack".format(stats.min));
	IJ.run(imp, "Divide...", "value={} stack".format((stats.max - stats.min)/255.0));
	WaitForUserDialog("pre 8-bit").show();
	imp = robust_convertStackToGray8(imp);
	WaitForUserDialog("post 8-bit").show();

	# Apply automatic THRESHOLD to differentiate cells from background
	histo = StackStatistics(imp).histogram;
	thresh_lev = AutoThresholder().getThreshold(AutoThresholder.Method.Default, histo);
	print(thresh_lev);
	min_volume = int(float(imp.getHeight() * imp.getWidth() * imp.getNSlices())/100);
	IJ.run(imp, "3D Simple Segmentation", "low_threshold=" + str(thresh_lev + 1) + 
												" min_size=" + str(min_volume) + " max_size=-1");
	fit_basis_imp = WM.getImage("Seg");
	bin_imp = WM.getImage("Bin");
	bin_imp.changes=False;
	bin_imp.close();
	IJ.setThreshold(fit_basis_imp, 1, 65535);
	IJ.run(fit_basis_imp, "Convert to Mask", "method=Default background=Dark list");
	#IJ.run(fit_basis_imp, "Fill Holes", "stack");
#	IJ.run("3D Fill Holes", "");
	return fit_basis_imp;
def normalise_to_fill_range(imp, max_val=255):
    """Return an imp with minimum=0 and maximum=max_val"""
    stats = StackStatistics(imp)
    IJ.run(imp, "Subtract...", "value=" + str(stats.min) + " stack")
    IJ.run(imp, "Multiply...",
           "value=" + str(float(max_val) / (stats.max - stats.min)) + " stack")
    return imp
예제 #3
0
def make_16bit_using_minmax(_imp):
  # ????? this does not make sense, or ???
  imp = _imp.duplicate()
  stats = StackStatistics(imp)
  IJ.setMinAndMax(imp, stats.min, stats.max)
  IJ.run(imp, "16-bit", "")
  IJ.setMinAndMax(imp, 0, 65535)
  return imp
예제 #4
0
def calcMedian(ip):
  hist = StackStatistics(ip).histogram16
  histsum = sum(hist)
  ii = 0
  for jj in range(0, 65536):
    ii += hist[jj]
    if ii > histsum / 2:
      break
  return jj
def extractChannel(imp, nChannel, nFrame):
    """extract a channel from the image, at a given frame returning a new imagePlus labelled with the channel name"""

    stack = imp.getImageStack()
    ch = ImageStack(imp.width, imp.height)
    for i in range(imp.getNSlices()):
        index = imp.getStackIndex(nChannel, i, nFrame)
        ch.addSlice(str(i), stack.getProcessor(index))
    imp3 = ImagePlus("Channel " + str(nChannel), ch).duplicate()
    stats = StackStatistics(imp3)
    IJ.setMinAndMax(imp3, stats.min, stats.max)
    return imp3
예제 #6
0
파일: display.py 프로젝트: toyo97/bcmeasure
def apply_lut(cs, cmap):
    # type: (CellStack, str) -> None
    """
Apply a different Look Up Table according to the given cmap name

    :param cmap: Can be 'fire'
    """
    stats = StackStatistics(cs)
    ll = LutLoader()
    if cmap == 'fire':
        cm = ll.open('luts/fire.lut')
        # print("Stats.max " + str(stats.max))
        lut = LUT(cm, stats.min, stats.max)
        cs.setLut(lut)
    else:
        IJ.error('Invalid color map: ' + cmap + '\nDefault LUT applied')
예제 #7
0
def getC1Projection(imp, norm):
    stack = imp.getStack()
    projStack = ImageStack(W,H)
    for t in range(1,T+1):
        proj = FloatProcessor(W,H)
        for z in range(1,Z+1):	#max intensity projection
            ip = stack.getProcessor(imp.getStackIndex(1,z,t)).convertToFloatProcessor()
            proj.copyBits(ip, 0,0, Blitter.MAX)
        projStack.addSlice(proj)

    if norm:	#Z normalise
        stats = StackStatistics(ImagePlus("wrapper",projStack))
        for t in range(1,T+1):
            ip = projStack.getProcessor(t)
            ip.subtract(stats.mean)
            ip.multiply( 1.0/(stats.stdDev) )

    return projStack
def threshold_and_binarise(imp,
                           z_xy_ratio,
                           approx_median=True,
                           prune_slicewise=True):
    """Return thresholded stack"""
    print("performing segmentation on channel: " + imp.getTitle())
    if approx_median:
        imp = utils.cross_planes_approx_median_filter(imp)
        imp = utils.robust_convertStackToGrayXbit(imp, x=8, normalise=True)
    else:
        filter_radius = 3.0
        IJ.run(
            imp, "Median 3D...", "x=" + str(filter_radius) + " y=" +
            str(math.ceil(filter_radius / z_xy_ratio)) + " z=" +
            str(filter_radius))
        IJ.run(imp, "8-bit", "")
    imp.show()

    # Apply automatic THRESHOLD to differentiate cells from background
    # get threshold value from stack histogram using otsu
    histo = StackStatistics(imp).histogram
    thresh_lev = AutoThresholder().getThreshold(
        AutoThresholder.Method.IJ_IsoData, histo)
    #thresh_lev = AutoThresholder().getThreshold(AutoThresholder.Method.Otsu, histo);
    max_voxel_volume = int(
        float(imp.getHeight() * imp.getWidth() * imp.getNSlices()) / 100)
    IJ.run(
        imp, "3D Simple Segmentation", "low_threshold=" + str(thresh_lev + 1) +
        " min_size=" + str(max_voxel_volume) + " max_size=-1")
    fit_basis_imp = WM.getImage("Seg")
    bin_imp = WM.getImage("Bin")
    bin_imp.changes = False
    bin_imp.close()
    IJ.setThreshold(fit_basis_imp, 1, 65535)
    IJ.run(fit_basis_imp, "Convert to Mask",
           "method=Default background=Dark list")
    #IJ.run(fit_basis_imp, "Fill Holes", "stack");
    IJ.run("3D Fill Holes", "")
    if prune_slicewise:
        fit_basis_imp = utils.keep_largest_blob(fit_basis_imp)
        # note this will be unstable if "branches" of approx equal x-section exist
    return fit_basis_imp
예제 #9
0
def signed2unsigned16(imp):
    stack = imp.getStack()
    if stack.isVirtual():
        IJ.error("Non-virtual stack required");
    cal = imp.getCalibration()
    if not cal.isSigned16Bit():
        return
        IJ.error("Signed 16-bit image required");
    cal.disableDensityCalibration()
    ip = imp.getProcessor()
    min = ip.getMin()
    max = ip.getMax()
    stats = StackStatistics(imp)
    minv = stats.min
    for i in range(stack.getSize()):
        ip = stack.getProcessor(i+1)
        ip.add(-minv)
    
    imp.setStack(stack)
    ip = imp.getProcessor()
    ip.setMinAndMax(min-minv, max-minv)
    imp.updateAndDraw()
def robust_convertStackToGrayXbit(imp, x=8, normalise=False):
	"""simplified from https://github.com/imagej/imagej1/blob/master/ij/process/StackConverter.java, 
	avoiding complications of scaling based on LUT taken from the current frame. Assumes conversion
	from grayscale image"""
	if x!=8 and x!=16 and x!=32:
		raise NotImplementedError("can't convert to the specified bit depth");
	if imp.getBitDepth()==x:
		return imp;
	if normalise:
		stats = StackStatistics(imp);
		offset = stats.min;
		maxtomin = stats.max - stats.min;
		IJ.run(imp, "Subtract...", "value={} stack".format(offset));
		IJ.run(imp, "Multiply...", "value={} stack".format(float(2**x - 1)/maxtomin));
	current_slice = imp.getCurrentSlice();
	stack = imp.getStack();
	out_stack = ImageStack(imp.getWidth(), imp.getHeight());
	n_z = imp.getNSlices();
	progress_inc = 1 if n_z/20 < 1 else n_z/20;
	for idx in range(n_z):
		# always use 1 as old stack index since we remove a slice at each iteration
		label = stack.getSliceLabel(1);
		ip = stack.getProcessor(1);
		stack.deleteSlice(1);
		if x==8:
			out_stack.addSlice(label, ip.convertToByte(False));
		elif x==16:
			out_stack.addSlice(label, ip.convertToShort(False));
		elif x==32:
			out_stack.addSlice(label, ip.convertToFloat());
		IJ.showProgress(float(idx)/n_z);
		if idx%progress_inc==0:
			IJ.showStatus("Converting stack to {}-bits: {}/{}".format(x, idx, n_z));
	imp.setStack(out_stack);
	IJ.showProgress(1.0);
	imp.setSlice(current_slice);
	return imp;
    thresholdImp.setCalibration(cal)
    thresholdImp.setTitle("Binary mask of " + originalTitle)

    #add the images to concatenated stacks
    conThresholdStack = concatStacks(conThresholdStack, thresholdImp)
    conlabelImpStack = concatStacks(conlabelImpStack, labelImp)
    table = quantify(gfx4, gfx5, table, nFrame, originalTitle)

    thresholdImp.close()
    labelImp.close()
    IJ.log("Processing timeframe: " + str(nFrame))
table.show("Results of " + originalTitle)
#Show the images and make the images pretty... I should have put in a function`

conThresholdImp = ImagePlus("Threshold image for " + originalTitle,
                            conThresholdStack)
conThresholdImp.setDimensions(1, imp1.getNSlices(), imp1.getNFrames())
IJ.setMinAndMax(conThresholdImp, 0, 1)
conThresholdImp.setCalibration(cal)
conThresholdImp = CompositeImage(conThresholdImp, CompositeImage.COMPOSITE)
conThresholdImp.show()

conlabelImp = ImagePlus("Label map " + originalTitle, conlabelImpStack)
conlabelImp.setDimensions(1, imp1.getNSlices(), imp1.getNFrames())
conlabelImp.setCalibration(cal)
stats = StackStatistics(conlabelImp)
conlabelImp = CompositeImage(conlabelImp, CompositeImage.COMPOSITE)
IJ.setMinAndMax(conlabelImp, 0, stats.max)
conlabelImp.show()
IJ.run("glasbey_inverted")
예제 #12
0
def make_8bit_using_min_max(_imp):
  imp = _imp.duplicate()
  stats = StackStatistics(imp)
  IJ.setMinAndMax(imp, stats.min, stats.max)
  ImageConverter(imp).convertToGray8() 
  return imp
예제 #13
0
def measureSumIntensity3D(imp):
  stats = StackStatistics(imp)
  return stats.mean * stats.pixelCount
예제 #14
0
def runOneFile(fullFilePath):

    global gNumChannels
    global gAlignBatchVersion

    if not os.path.isfile(fullFilePath):
        bPrintLog(
            '\nERROR: runOneFile() did not find file: ' + fullFilePath + '\n',
            0)
        return 0

    bPrintLog(
        time.strftime("%H:%M:%S") + ' starting runOneFile(): ' + fullFilePath,
        1)

    enclosingPath = os.path.dirname(fullFilePath)
    head, tail = os.path.split(enclosingPath)
    enclosingPath += '/'

    #make output folders
    destFolder = enclosingPath + tail + '_channels/'
    if not os.path.isdir(destFolder):
        os.makedirs(destFolder)
    destMaxFolder = destFolder + 'max/'
    if not os.path.isdir(destMaxFolder):
        os.makedirs(destMaxFolder)

    if gDoAlign:
        destAlignmentFolder = destFolder + 'alignment/'
        if not os.path.isdir(destAlignmentFolder):
            os.makedirs(destAlignmentFolder)

    if gSave8bit:
        eightBitFolder = destFolder + 'channels8/'
        if not os.path.isdir(eightBitFolder):
            os.makedirs(eightBitFolder)
        eightBitMaxFolder = eightBitFolder + 'max/'
        if not os.path.isdir(eightBitMaxFolder):
            os.makedirs(eightBitMaxFolder)

    # open image
    imp = Opener().openImage(fullFilePath)

    # get parameters of image
    (width, height, nChannels, nSlices, nFrames) = imp.getDimensions()
    bitDepth = imp.getBitDepth()
    infoStr = imp.getProperty("Info")  #get all .tif tags
    if not infoStr:
        infoStr = ''
    infoStr += 'bAlignBatch_Version=' + str(gAlignBatchVersion) + '\n'
    infoStr += 'bAlignBatch_Time=' + time.strftime(
        "%Y%m%d") + '_' + time.strftime("%H%M%S") + '\n'

    msgStr = 'w:' + str(width) + ' h:' + str(height) + ' slices:' + str(nSlices) \
       + ' channels:' + str(nChannels) + ' frames:' + str(nFrames) + ' bitDepth:' + str(bitDepth)
    bPrintLog(msgStr, 1)

    path, filename = os.path.split(fullFilePath)
    shortName, fileExtension = os.path.splitext(filename)

    #
    # look for num channels in ScanImage infoStr
    if gGetNumChanFromScanImage:
        for line in infoStr.split('\n'):
            #scanimage.SI4.channelsSave = [1;2]
            scanimage4 = find(line, 'scanimage.SI4.channelsSave =') == 0
            #state.acq.numberOfChannelsSave=2
            scanimage3 = find(line, 'state.acq.numberOfChannelsSave=') == 0
            if scanimage3:
                #print 'line:', line
                equalIdx = find(line, '=')
                line2 = line[equalIdx + 1:]
                if gGetNumChanFromScanImage:
                    gNumChannels = int(line2)
                    bPrintLog(
                        'over-riding gNumChannels with: ' + str(gNumChannels),
                        2)
            if scanimage4:
                #print '   we have a scanimage 4 file ... now i need to exptract the number of channel'
                #print 'line:', line
                equalIdx = find(line, '=')
                line2 = line[equalIdx + 1:]
                for delim in ';[]':
                    line2 = line2.replace(delim, ' ')
                if gGetNumChanFromScanImage:
                    gNumChannels = len(line2.split())
                    bPrintLog(
                        'over-riding gNumChannels with: ' + str(gNumChannels),
                        2)

    # show
    imp.show()
    # split channels if necc. and grab the original window names
    if gNumChannels == 1:
        origImpWinStr = imp.getTitle()  #use this when only one channel
        origImpWin = WindowManager.getWindow(
            origImpWinStr)  #returns java.awt.Window

    if gNumChannels == 2:
        winTitle = imp.getTitle()
        bPrintLog('Deinterleaving 2 channels...', 1)
        IJ.run('Deinterleave',
               'how=2 keep')  #makes ' #1' and ' #2', with ' #2' frontmost
        origCh1WinStr = winTitle + ' #1'
        origCh2WinStr = winTitle + ' #2'
        origCh1Imp = WindowManager.getImage(origCh1WinStr)
        origCh2Imp = WindowManager.getImage(origCh2WinStr)
        origCh1File = destFolder + shortName + '_ch1.tif'
        origCh2File = destFolder + shortName + '_ch2.tif'

    # work on a copy, mostly for alignment with cropping
    copy = Duplicator().run(imp)
    #copy.copyAttributes(imp) #don't copy attributes, it copies the name (which we do not want)
    copy.show()

    #
    # crop (on copy)
    if gDoCrop:
        bPrintLog('making cropping rectangle (left,top,width,height) ', 1)
        bPrintLog(
            str(gCropLeft) + ' ' + str(gCropTop) + ' ' + str(gCropWidth) +
            ' ' + str(gCropHeight), 2)

        roi = Roi(gCropLeft, gCropTop, gCropWidth,
                  gCropHeight)  #left,top,width,height
        copy.setRoi(roi)

        time.sleep(
            0.5
        )  # otherwise, crop SOMETIMES failes. WHAT THE F**K FIJI DEVELOPERS, REALLY, WHAT THE F**K

        #bPrintLog('cropping', 1)
        IJ.run('Crop')
        infoStr += 'bCropping=' + str(gCropLeft) + ',' + str(
            gCropTop) + ',' + str(gCropWidth) + ',' + str(gCropHeight) + '\n'

    #
    # remove calibration ( on original)
    if gRemoveCalibration:
        cal = imp.getCalibration()
        calCoeff = cal.getCoefficients()
        if calCoeff:
            msgStr = 'Calibration is y=a+bx' + ' a=' + str(
                calCoeff[0]) + ' b=' + str(calCoeff[1])
            bPrintLog(msgStr, 1)

            #remove calibration
            bPrintLog('\tRemoving Calibration', 2)
            imp.setCalibration(None)

            #without these, 8-bit conversion goes to all 0 !!! what the f**k !!!
            #bPrintLog('calling imp.resetStack() and imp.resetDisplayRange()', 2)
            imp.resetStack()
            imp.resetDisplayRange()

            #get and print out min/max
            origMin = StackStatistics(imp).min
            origMax = StackStatistics(imp).max
            msgStr = '\torig min=' + str(origMin) + ' max=' + str(origMax)
            bPrintLog(msgStr, 2)

            # 20150723, 'shift everybody over by linear calibration intercept calCoeff[0] - (magic number)
            if 1:
                # [1] was this
                #msgStr = 'Subtracting original min '+str(origMin) + ' from stack.'
                #bPrintLog(msgStr, 2)
                #subArgVal = 'value=%s stack' % (origMin,)
                #IJ.run('Subtract...', subArgVal)
                # [2] now this
                #msgStr = 'Adding calCoeff[0] '+str(calCoeff[0]) + ' from stack.'
                #bPrintLog(msgStr, 2)
                #addArgVal = 'value=%s stack' % (int(calCoeff[0]),)
                #IJ.run('Add...', addArgVal)
                # [3] subtract a magic number 2^15-2^7 = 32768 - 128
                magicNumber = gLinearShift  #2^15 - 128
                msgStr = 'Subtracting a magic number (linear shift) ' + str(
                    magicNumber) + ' from stack.'
                bPrintLog(msgStr, 2)
                infoStr += 'bLinearShift=' + str(gLinearShift) + '\n'
                subArgVal = 'value=%s stack' % (gLinearShift, )
            IJ.run(imp, 'Subtract...', subArgVal)

            # 20150701, set any pixel <0 to 0
            if 0:
                ip = imp.getProcessor()  # returns a reference
                pixels = ip.getPixels()  # returns a reference
                msgStr = '\tSet all pixels <0 to 0. This was added 20150701 ...'
                bPrintLog(msgStr, 2)
                pixels = map(lambda x: 0 if x < 0 else x, pixels)
                bPrintLog('\t\t... done', 2)

            #get and print out min/max
            newMin = StackStatistics(imp).min
            newMax = StackStatistics(imp).max
            msgStr = '\tnew min=' + str(newMin) + ' max=' + str(newMax)
            bPrintLog(msgStr, 2)

            #append calibration to info string
            infoStr += 'bCalibCoeff_a = ' + str(calCoeff[0]) + '\n'
            infoStr += 'bCalibCoeff_b = ' + str(calCoeff[1]) + '\n'
            infoStr += 'bNewMin = ' + str(newMin) + '\n'
            infoStr += 'bNewMax = ' + str(newMax) + '\n'

    #
    # set up
    if gNumChannels == 1:
        impWinStr = copy.getTitle()  #use this when only one channel
        impWin = WindowManager.getWindow(impWinStr)  #returns java.awt.Window

    if gNumChannels == 2:
        winTitle = copy.getTitle()
        bPrintLog('Deinterleaving 2 channels...', 1)
        IJ.run('Deinterleave',
               'how=2 keep')  #makes ' #1' and ' #2', with ' #2' frontmost
        ch1WinStr = winTitle + ' #1'
        ch2WinStr = winTitle + ' #2'
        ch1Imp = WindowManager.getImage(ch1WinStr)
        ch2Imp = WindowManager.getImage(ch2WinStr)
        ch1File = destFolder + shortName + '_ch1.tif'
        ch2File = destFolder + shortName + '_ch2.tif'

    #
    # alignment
    if gDoAlign and gNumChannels == 1 and copy.getNSlices() > 1:
        infoStr += 'AlignOnChannel=1' + '\n'
        #snap to middle slice
        if gAlignOnMiddleSlice:
            middleSlice = int(
                math.floor(copy.getNSlices() /
                           2))  #int() is necc., python is f*****g picky
        else:
            middleSlice = gAlignOnThisSlice
        copy.setSlice(middleSlice)

        transformationFile = destAlignmentFolder + shortName + '.txt'

        bPrintLog('MultiStackReg aligning:' + impWinStr, 1)
        stackRegParams = 'stack_1=[%s] action_1=Align file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body] save' % (
            impWin, transformationFile)
        IJ.run('MultiStackReg', stackRegParams)
        infoStr += 'AlignOnSlice=' + str(middleSlice) + '\n'

        #20150723, we just aligned on a cropped copy, apply alignment to original imp
        origImpTitle = imp.getTitle()
        stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' % (
            origImpTitle, transformationFile)
        IJ.run('MultiStackReg', stackRegParams)

    if gDoAlign and gNumChannels == 2 and ch1Imp.getNSlices(
    ) > 1 and ch2Imp.getNSlices() > 1:
        #apply to gAlignThisChannel
        alignThisWindow = ''
        applyAlignmentToThisWindow = ''
        if gAlignThisChannel == 1:
            infoStr += 'AlignOnChannel=1' + '\n'
            transformationFile = destAlignmentFolder + shortName + '_ch1.txt'
            alignThisWindow = ch1WinStr
            applyAlignmentToThisWindow = ch2WinStr
        else:
            infoStr += 'AlignOnChannel=2' + '\n'
            transformationFile = destAlignmentFolder + shortName + '_ch2.txt'
            alignThisWindow = ch2WinStr
            applyAlignmentToThisWindow = ch1WinStr

        alignThisImp = WindowManager.getImage(alignThisWindow)
        #snap to middle slice
        if gAlignOnMiddleSlice:
            middleSlice = int(
                math.floor(alignThisImp.getNSlices() /
                           2))  #int() is necc., python is f*****g picky
        else:
            middleSlice = gAlignOnThisSlice
        alignThisImp.setSlice(middleSlice)

        infoStr += 'bAlignOnSlice=' + str(middleSlice) + '\n'

        bPrintLog('MultiStackReg aligning:' + alignThisWindow, 1)
        stackRegParams = 'stack_1=[%s] action_1=Align file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body] save' % (
            alignThisWindow, transformationFile)
        IJ.run('MultiStackReg', stackRegParams)

        # 20150723, we just aligned on a copy, apply alignment to both channels of original
        # ch1
        bPrintLog('MultiStackReg applying alignment to:' + origCh1WinStr, 1)
        stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' % (
            origCh1WinStr, transformationFile)
        IJ.run('MultiStackReg', stackRegParams)
        # ch2
        bPrintLog('MultiStackReg applying alignment to:' + origCh2WinStr, 1)
        stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' % (
            origCh2WinStr, transformationFile)
        IJ.run('MultiStackReg', stackRegParams)

        #apply alignment to other window
        #bPrintLog('MultiStackReg applying alignment to:' + applyAlignmentToThisWindow, 1)
        #applyAlignThisImp = WindowManager.getImage(applyAlignmentToThisWindow)
        #stackRegParams = 'stack_1=[%s] action_1=[Load Transformation File] file_1=[%s] stack_2=None action_2=Ignore file_2=[] transformation=[Rigid Body]' %(applyAlignmentToThisWindow,transformationFile)
        #IJ.run('MultiStackReg', stackRegParams)
    elif gDoAlign:
        bPrintLog('Skipping alignment, there may be only one slice?', 3)

    #
    # save
    if gNumChannels == 1:
        imp.setProperty("Info", infoStr)
        impFile = destFolder + shortName + '.tif'
        #bPrintLog('Saving:' + impFile, 1)
        bSaveStack(imp, impFile)
        #max project
        bSaveZProject(imp, destMaxFolder, shortName)

    if gNumChannels == 2:
        #ch1
        origCh1Imp.setProperty("Info", infoStr)
        #bPrintLog('Saving:' + ch1File, 1)
        bSaveStack(origCh1Imp, ch1File)
        #max project
        bSaveZProject(origCh1Imp, destMaxFolder, shortName + '_ch1')

        #ch2
        origCh2Imp.setProperty("Info", infoStr)
        #bPrintLog('Saving:' + ch2File, 1)
        bSaveStack(origCh2Imp, ch2File)
        #max project
        bSaveZProject(origCh2Imp, destMaxFolder, shortName + '_ch2')

#
    # post convert to 8-bit and save
    if gSave8bit:
        if bitDepth == 16:
            if gNumChannels == 1:
                bPrintLog('Converting to 8-bit:' + impWinStr, 1)
                IJ.selectWindow(impWinStr)
                #IJ.run('resetMinAndMax()')
                IJ.run("8-bit")
                impFile = eightBitFolder + shortName + '.tif'
                bPrintLog('Saving 8-bit:' + impFile, 2)
                bSaveStack(imp, impFile)
                #max project
                bSaveZProject(imp, eightBitMaxFolder, shortName)

            if gNumChannels == 2:
                #
                bPrintLog('Converting to 8-bit:' + origCh1WinStr, 1)
                IJ.selectWindow(origCh1WinStr)

                IJ.run("8-bit")
                impFile = eightBitFolder + shortName + '_ch1.tif'
                bPrintLog('Saving 8-bit:' + impFile, 2)
                bSaveStack(origCh1Imp, impFile)
                #max project
                bSaveZProject(origCh1Imp, eightBitMaxFolder,
                              shortName + '_ch1')

                #
                bPrintLog('Converting to 8-bit:' + origCh2WinStr, 1)
                IJ.selectWindow(origCh2WinStr)
                #IJ.run('resetMinAndMax()')
                IJ.run("8-bit")
                impFile = eightBitFolder + shortName + '_ch2.tif'
                bPrintLog('Saving 8-bit:' + impFile, 2)
                bSaveStack(origCh2Imp, impFile)
                #max project
                bSaveZProject(origCh2Imp, eightBitMaxFolder,
                              shortName + '_ch2')

    #
    # close original window
    imp.changes = 0
    imp.close()
    #copy
    copy.changes = 0
    copy.close()

    #
    # close ch1/ch2
    if gNumChannels == 2:
        #original
        origCh1Imp.changes = 0
        origCh1Imp.close()
        origCh2Imp.changes = 0
        origCh2Imp.close()
        #copy
        ch1Imp.changes = 0
        ch1Imp.close()
        ch2Imp.changes = 0
        ch2Imp.close()

    bPrintLog(
        time.strftime("%H:%M:%S") + ' finished runOneFile(): ' + fullFilePath,
        1)
예제 #15
0
#@ ImagePlus imp  # take e.g. M51 Galaxy sample image
"""
Histo example from Jan Eglinger with some JRM mods
converted from groovy to python

"""

from ij.process import StackStatistics
from ij import IJ

simpleStats = StackStatistics(imp)

print("Image name: %s" % (imp.getTitle()))
print("Automatic bin size: %s" % (simpleStats.binSize))
print("Automatic hist min: %s" % (simpleStats.histMin))
print("Automatic hist max: %s" % (simpleStats.histMax))

binWidth = 2
min = 0
max = 1024

customStats = StackStatistics(imp, (int(max - min) / binWidth), min, max)

print("Custom bin size: %s" % (customStats.binSize))
print("Custom hist min: %s" % (customStats.histMin))
print("Custom hist max: %s" % (customStats.histMax))

IJ.run("Histogram", "bins=6000 x_min=0 x_max=12000")
예제 #16
0
#Show the images and make the images pretty... I should have put in a function`

conThresholdImp = ImagePlus("Threshold image for " + originalTitle,
                            conThresholdStack)
conThresholdImp.setDimensions(1, imp1.getNSlices(), imp1.getNFrames())
IJ.setMinAndMax(conThresholdImp, 0, 1)
conThresholdImp.setCalibration(cal)
conThresholdImp = CompositeImage(conThresholdImp, CompositeImage.COMPOSITE)
conThresholdImp.show()

conFRETImp2 = ImagePlus("Emission ratios X1000 of " + originalTitle,
                        conFRETImp2Stack)
conFRETImp2.setDimensions(1, imp1.getNSlices(), imp1.getNFrames())
conFRETImp2.setCalibration(cal)
stats = StackStatistics(conFRETImp2)
conFRETImp2 = CompositeImage(conFRETImp2, CompositeImage.COMPOSITE)
IJ.setMinAndMax(conFRETImp2, 500, 3000)
conFRETImp2.show()
IJ.run("16_colors")

conFRETProjImp = ImagePlus(
    "Max Z  projection of emission ratios X1000 of " + originalTitle,
    conFRETProjImpStack)
conFRETProjImp.setDimensions(1, 1, imp1.getNFrames())
conFRETProjImp.setCalibration(cal)
stats = StackStatistics(conFRETProjImp)
IJ.setMinAndMax(conFRETProjImp, 500, 3000)
conFRETProjImp = CompositeImage(conFRETProjImp, CompositeImage.COMPOSITE)
conFRETProjImp.show()
IJ.run("16_colors")
예제 #17
0
def run():
    print "===== Batch Convert Scan Image 4 ====="

    # Expecting one argument: the file path
    if len(sys.argv) < 2:
        print "   We need a hard-drive folder with .tif stacks as input"
        print "	  Usage: ./fiji-macosx bBatchConvertTo8Bitv3 <folder-path>/"

        # Prompt user for a folder
        sourceFolder = DirectoryChooser(
            "Please Choose A Directory Of .tif Files").getDirectory()
        if not sourceFolder:
            return
    else:
        sourceFolder = sys.argv[1]  #assuming it ends in '/'

    destFolder = sourceFolder + "scanimage4/"
    destMaxFolder = destFolder + "max/"

    #make destination directory
    if not os.path.isdir(destFolder):
        os.makedirs(destFolder)

    #make max destination directory
    if not os.path.isdir(destMaxFolder):
        os.makedirs(destMaxFolder)

    print "   Processing source folder: ", sourceFolder
    print "   Saving to destination folder: ", destFolder
    IJ.log("   ====== Starting Batch Convert Scan Image 4 ======")
    IJ.log("   Processing source folder: " + sourceFolder)
    IJ.log("   Saving to destination folder: " + destFolder)

    numOpened = 0
    numSaved = 0

    for filename in os.listdir(sourceFolder):
        startWithDot = filename.startswith(".")
        isMax = filename.endswith("max.tif")
        isTif = filename.endswith(".tif")

        if (not startWithDot) and (not isMax) and (isTif):
            shortName, fileExtension = os.path.splitext(filename)

            #source .tif output (after conversion)
            outPath = destFolder + filename

            #max projection output
            outMaxPath = destMaxFolder + "max_" + filename

            #before we open, check if eventual dest exists
            if os.path.exists(outPath):
                msgStr = "   Destination file exists, not processing the image:" + filename
                print msgStr
                IJ.log(msgStr)
                continue  #with next iteration

            print "   ===================================="
            msgStr = "   -> Opening " + sourceFolder + filename
            print msgStr
            IJ.log(msgStr)
            imp = IJ.openImage(sourceFolder + filename)
            if imp is None:
                msgStr = "	     ERROR: Could not open image from file: " + filename
                print msgStr
                IJ.log(msgStr)
                continue  #with next iteration

            imp.show()
            numOpened += 1

            msgStr = "      Original Image is: " + str(
                imp.width) + " X " + str(imp.height) + " X " + str(
                    imp.getNSlices())
            print msgStr
            IJ.log(msgStr)
            if 1:
                msgStr = "      Removing Calibration From ScanImage 4 .tif"
                print msgStr
                IJ.log(msgStr)

                #20140810, I CAN'T BELIEVE I FINALLY FOUND THIS !!!
                infoStr = imp.getProperty("Info")
                #print infoStr

                #scanimage4 has a linear Calibration Function: y = a+bx
                #  a: -32768.000000
                #  b: 1.000000
                #  Unit: "Gray Value"
                #for some reason scanimage4 is setting a linear image calibration, we see negative values but there are NOT there
                cal = imp.getCalibration()
                calCoeff = cal.getCoefficients()
                msgStr = '        calibration is y=ax+b' + ' a=' + str(
                    calCoeff[0]) + ' b=' + str(calCoeff[1])
                print msgStr
                IJ.log(msgStr)

                #append calibration to info string
                imp.setCalibration(None)
                infoStr += 'calibCoeff_a = ' + str(calCoeff[0]) + '\n'
                infoStr += 'calibCoeff_b = ' + str(calCoeff[1]) + '\n'

                #i have appended to Info, update it
                #found this burried here: http://code.google.com/p/fiji-bi/source/browse/ij/ImagePlus.java?repo=imageja&name=imagej
                imp.setProperty("Info", infoStr)

                #get and print out min/max
                theMin = StackStatistics(imp).min
                theMax = StackStatistics(imp).max
                msgStr = '        min=' + str(theMin) + ' max=' + str(theMax)
                print msgStr
                IJ.log(msgStr)

                #subtract the linear calibration slope 'a' (what about intercept 'b' ?)
                #coefficient 'a' is normally negative, this is what we are using 'Add'
                #run("Subtract...", "value=32768 stack");
                subArgVal = 'value=%s stack' % (calCoeff[0], )
                IJ.run('Add...', subArgVal)

                #save file
                fs = FileSaver(imp)
                msgStr = "      Saving File to" + outPath
                print msgStr
                IJ.log(msgStr)

                numSlices = imp.getNSlices()

                if (numSlices > 1):
                    fs.saveAsTiffStack(outPath)
                else:
                    fs.saveAsTiff(outPath)
                numSaved += 1

                #max
                if (numSlices > 1):
                    maxCmdParams = 'start=1' + ' stop=' + str(
                        numSlices) + ' projection=[Max Intensity]'
                    IJ.run("Z Project...", maxCmdParams)

                impMax = IJ.getImage()
                fs = FileSaver(impMax)
                print "      Saving Max File to", outMaxPath
                fs.saveAsTiff(outMaxPath)

                #close max
                impMax.changes = 0
                impMax.close()

                #close original
                imp.changes = 0
                imp.close()

            else:
                print "   File was not 16 bit???"

            imp.close()  #close original

        else:
            if (not startWithDot) and isTif:
                #print "   ===================================="
                print filename
                msgStr = "   -> Ignoring .tif:" + filename
                print msgStr
                IJ.log(msgStr)

    msgStr = "   Batch Convert Scan Image 4 is Done, Number Opened " + str(
        numOpened) + ", Number Saved " + str(numSaved)
    print "   ==="
    print msgStr
    print "   ==="
    IJ.log(msgStr)
예제 #18
0
    # Read out the options    
    beta = gd.getNextNumber()
    patchradius = gd.getNextNumber()
    searchradius = gd.getNextNumber()     
    return beta, patchradius, searchradius  
 


# get input image 
InputImg = IJ.openImage();




# Get Input Image Statistics  
InStats = StackStatistics(InputImg)
print "mean:", InStats.mean, "minimum:", InStats.min, "maximum:", InStats.max

options = getOptions()  
if options is not None:  
    beta, patchradius, searchradius = options  
    


 
# get the image stack within the ImagePlus 
InputStack = InputImg.getStack()
z = InputImg.getNSlices() 
print "number of slices:", z

    
예제 #19
0
    imp7 = imp7.flatten()

    return imp7


# *****************************body of code starts****************************************

clij2 = CLIJ2.getInstance()
clij2.clear()

imp1 = IJ.getImage()
height = imp1.getHeight()
width = imp1.getWidth()
depth = imp1.getStackSize()

stats = StackStatistics(imp1)

labelColorBarImp = createLabelColorBar()
categories = 11
#print dir(WM)
test = dialog(imp1, labelColorBarImp)

names, imageName, resultsName, imageOrTable = selectionDialog(
    categories, labelColorBarImp)

listOfNames = ["Unnamed"] * len(test.labelValues)

for key in test.labelDict.keys():

    for value in test.labelDict[key]:
        listOfNames[value] = names[key]
예제 #20
0
    def __init__(self, imp1, slider1, slider2, gd):
        self.height = imp1.getHeight()
        self.width = imp1.getWidth()
        self.depth = imp1.getStackSize()

        self.stats = StackStatistics(imp1)
        self.src = clij2.push(imp1)
        self.cal = imp1.getCalibration()
        self.size = int(self.stats.max)
        self.labelValues = [1] * int(self.size + 1)
        self.labelValues[0] = 0

        self.nucleiLabels = range(self.size + 1)
        self.results = ResultsTable()

        self.renderPreview(1)
        #self.results.show("results")
        self.labelDict = {
            0: [0],
            1: sorted(self.nucleiLabels[1:]),
            2: [],
            3: [],
            4: [],
            5: [],
            6: [],
            7: [],
            8: [],
            9: [],
            10: []
        }

        self.identifiers = []
        self.xs = []
        self.ys = []
        self.zs = []
        self.bbz = []
        self.bbze = []

        for i in range(int(self.size + 1)):
            try:

                self.xs.append(int(self.results.getValue("CENTROID_X", i)))
                self.ys.append(int(self.results.getValue("CENTROID_Y", i)))
                self.zs.append(int(self.results.getValue("CENTROID_Z", i)))
                self.bbz.append(self.results.getValue("BOUNDING_BOX_Z", i) + 1)
                self.bbze.append(
                    self.results.getValue("BOUNDING_BOX_END_Z", i) + 1)
                self.identifiers.append(self.results.getValue("IDENTIFIER", i))
            except:
                print i
                self.identifiers.append(self.results.getValue("IDENTIFIER", i))
                self.xs.append(int(width / 2))
                self.ys.append(int(height / 2))
                self.zs.append(int(depth / 2))
                self.bbz.append(1)
                self.bbze.append(1)

        self.nucLoc = map(lambda i: self.ys[i] * width + self.xs[i],
                          range(len(self.xs)))
        """labelPreviewImp -  label image preview; maxZPreviewImp - maxZ label preview; maxYPreviewImp - maxY label preview"""

        self.slider1 = slider1
        self.slider2 = slider2
        self.gd = gd
        self.current = self.labelPreviewImp.getCurrentSlice()
def process_imgdir( directory, close_after ) :
    print( 'Processing: ' + directory )

    original_image_filename = directory + '/uniform.tif'
    probabilities_image_filename = directory + '/probabilities.tif'
    cube_rois_filename = directory + '/CubeROIs.csv'

    cubes = []
    f = open(cube_rois_filename)
    lines = f.readlines()
    for line in lines[1:]:
        #els = [ int(el)-1 for el in line.strip().split(',') ]
        els = [ int(el) for el in line.strip().split(',') ]
        cubes += [ { 'idx': els[0], 'class': els[1], 'x1':min(els[2],els[5]), 'y1':min(els[3],els[6]), 'z1':min(els[4],els[7]), 'x2':max(els[5],els[2]), 'y2':max(els[6],els[3]), 'z2':max(els[4],els[7]) } ]
    f.close()
    print( 'Read ' + str(len(cubes)) + ' cubes from file' )

    #for cube in cubes:
    #for cube_idx in range( len( cubes ) ):
    for cube_idx in [0]:
        cube = cubes[cube_idx]
        print( cube )

        all_edt_histograms['name'] += [ directory.split( '/' )[-1] + '_' + str(cube_idx) ]
        all_skeleton_edt_histograms['name'] += [ directory.split( '/' )[-1] + '_' + str(cube_idx) ]

        cube_basename = directory + '/cube_' + str(cube_idx) + '_'

        # Check if we have a parameters file, and evaluate it if so, otherwise make one with defaults
        param_filename = cube_basename + 'parameters.py'
        # Make a default to start with
        no_params_set = False
        if not os.path.isfile( param_filename ):
            f = open( param_filename, 'w' )
            f.write( 'mesh_thresh=200\n' )
            f.write( 'interior_coords=[ (1,1,1) ]\n' )
            f.close()
            no_params_set = True

        if os.path.isfile( param_filename ):
            f = open( param_filename )
            lines = f.readlines()
            for line in lines:
                if 'mesh_thresh' in line:
                    mesh_thresh = eval(line.split('=')[1])
                if 'interior_coords' in line:
                    interior_coords = eval(line.split('=')[1])

        load_uniform = True
        if load_uniform:
            #open uniform
            uniform = IJ.openImage( original_image_filename )

            #crop uniform
            uniform.setRoi( cube['x1'], cube['y1'], cube['x2'], cube['y2'] )
            IJ.run( uniform, "Crop", "")
            IJ.run( uniform, "Make Substack...", "slices=" + str(cube['z1']) + '-' + str(cube['z2']) )
            uniform.close()
            uniform = IJ.getImage()
            IJ.saveAsTiff( uniform, cube_basename + 'raw.tif' )

            #save max_projection of uniform
            IJ.run(uniform, "Z Project...", "projection=[Max Intensity]")
            uniform_mp = IJ.getImage()
            IJ.run(uniform_mp, "Enhance Contrast", "saturated=0.35")
            IJ.saveAsTiff( uniform_mp, cube_basename + 'raw_maxproj.tif' )

        #open probabilites
        probabilities = IJ.openImage( probabilities_image_filename )

        #crop probabilites
        probabilities.setRoi( cube['x1'], cube['y1'], cube['x2'], cube['y2'] )
        IJ.run( probabilities, "Crop", "")
        IJ.run( probabilities, "Make Substack...", "slices=" + str(cube['z1']) + '-' + str(cube['z2']) )
        time.sleep( 5 )
        probabilities.close()
        probabilities = IJ.getImage()
        #IJ.saveAsTiff( probabilities, cube_basename + 'probabilities.tif' )

        time.sleep( 5 )

        #save max_projection of probabilites
        IJ.run(probabilities, "Z Project...", "projection=[Max Intensity]")
        probabilities_mp = IJ.getImage()
        IJ.run(probabilities_mp, "Enhance Contrast", "saturated=0.35")
        IJ.saveAsTiff( probabilities_mp, cube_basename + 'probabilities_maxproj.tif' )

        time.sleep( 5 )

        # blur probabilities to help smooth the isosurfaces
        blur_radius = 2
        IJ.run( probabilities, "Gaussian Blur 3D...", 'x=' + str(blur_radius) + ' y=' + str(blur_radius) + ' z=' + str(blur_radius) )

        #threshold probabilities
        #IJ.run(probabilities, "Enhance Contrast", "saturated=0.35")
        IJ.run( probabilities, "8-bit", "")
        #IJ.saveAsTiff( probabilities, cube_basename + 'probabilities.tif' )
        #for k in range( probabilities.getNSlices() ):
        #    probabilities.setSlice(k+1)
        #    probabilities.getProcessor().setThreshold( mesh_thresh - 1, mesh_thresh + 1, 0 )
        #IJ.run( probabilities, 'Convert to Mask', 'method=Default background=Dark black')
        #time.sleep( 5 )
        IJ.saveAsTiff( probabilities, cube_basename + 'probabilities.tif' )

        time.sleep( 5 )

        #mesh binary_probabilities
        #IJ.run( "3D Viewer", "")


        threedType = 2
        threedName = 'cube_' + str(cube_idx)

        IJ.runPlugIn( "ij3d.ImageJ3DViewer", probabilities.getTitle() )
        univ = Image3DUniverse.universes.get(0)
        univ.addContent( probabilities, Color3f(1,1,1), threedName, mesh_thresh, [True, False, False], 2, threedType )
        ImageJ3DViewer.select( threedName )
        ImageJ3DViewer.exportContent( 'wavefront', cube_basename + 'mesh.obj' )

        #smooth mesh
        c = univ.getSelected()
        n = c.getContent()
        ctm = n.getMesh()
        fim = customnode.FullInfoMesh( ctm.getMesh() )
        ec = customnode.EdgeContraction( fim, False )

        initial_num_verts = ec.getVertexCount()
        num_to_remove = int( initial_num_verts * 0.1 )

        #v = InteractiveMeshDecimation.simplify( ec, num_to_remove )

        enable_smoothing = False
        if enable_smoothing:
            part = num_to_remove / 10
            last = num_to_remove % 10
            ret = 0
            for i in range(10):
                IJ.showProgress(i + 1, 10)
                ret = ec.removeNext(part)
            if (last != 0):
                ret = ec.removeNext(last)
            IJ.showProgress(1)

            ctm.setMesh( fim.getMesh() )
            ImageJ3DViewer.exportContent( 'wavefront', cube_basename + 'smooth_mesh.obj' )

        # 3d viewer screenshot
        screenshot_3d = univ.takeSnapshot()
        IJ.saveAsTiff( screenshot_3d, cube_basename + 'mesh_screenshot.tif' )

        #voxelize mesh
        voxelizer = InteractiveMeshVoxelization()
        voxelizer.voxelize( ctm, probabilities.getWidth(), probabilities.getHeight(), probabilities.getStackSize() )

        #voxelization = WindowManager.getImage( ctm.getName() + '_voxelization' )
        voxelization = WindowManager.getImage( 'null_voxelization' )
        voxelization.setCalibration( probabilities.getCalibration().copy() )
        #manually 3D fill vasculature, fill with thresholdable-color
        #save selected vasculature

        #call('process3d.Flood_Fill.fill', x,y,z)
        if not no_params_set:
            fill_color = 100
            Flood_Fill.fill( voxelization, interior_coords[0][0], interior_coords[0][1], interior_coords[0][2], fill_color )

            # Threshold to extract
            #IJ.setAutoThreshold( voxelization, 'Default dark' )
            #Prefs.blackBackground = true
            #IJ.run( voxelization, 'Convert to Mask', 'method=Default background=Dark black')

            for k in range( voxelization.getNSlices() ):
                voxelization.setSlice(k+1)
                voxelization.getProcessor().setThreshold( fill_color - 1, fill_color + 1, 0 )
            IJ.run( voxelization, 'Convert to Mask', 'method=Default background=Dark black')
            IJ.saveAsTiff( voxelization, cube_basename + 'voxelization.tif' )

            # Calculate and record volume HERE

            IJ.run(voxelization, "Z Project...", "projection=[Max Intensity]")
            voxelization_mp = IJ.getImage()
            IJ.run(voxelization_mp, "Enhance Contrast", "saturated=0.35")
            IJ.saveAsTiff( voxelization_mp, cube_basename + 'voxelization_maxproj.tif' )

            # Calculate EDT
            IJ.run( voxelization, "Exact Euclidean Distance Transform (3D)", "" )
            edt = WindowManager.getImage( 'EDT' )
            IJ.run( edt, 'Fire', '' )

            # Get the histogram data in an array

            hist_nBins = int( ( hist_max - hist_min ) / hist_step )
            #edt_stats = edt.getStatistics( Measurements.MEDIAN, hist_nBins, hist_min, hist_max )
            edt_stats = StackStatistics( edt, hist_nBins, hist_min, hist_max )
            hist_data = edt_stats.getHistogram()
            hist_binLabels = [ ( hist_min + hist_step * el ) for el in range( hist_nBins ) ]

            max_radius = 20
            IJ.run( edt, 'Histogram', 'bins=' + str(hist_nBins) + ' x_min=' + str(hist_min) + ' x_max=' + str(hist_max) + ' y_max=Auto stack' )
            edt_histogram = WindowManager.getImage( 'Histogram of EDT' )
            IJ.saveAsTiff( edt_histogram, cube_basename + 'edt_histogram.tif' )

            x_unit_scale = uniform.getCalibration().getX(1)
            y_unit_scale = uniform.getCalibration().getY(1)
            z_unit_scale = uniform.getCalibration().getZ(1)

            f = open( cube_basename + 'edt_histogram.csv', 'w' )
            for k in range( len( hist_data ) ):
                f.write( str(hist_binLabels[k]) + '\t' + str(hist_data[k]*x_unit_scale*y_unit_scale*z_unit_scale) + '\n' )
                #f.write( str(hist_binLabels[k]) + '\t' + str(hist_data[k]) + '\n' )
                all_edt_histograms[hist_binLabels[k]] += [ hist_data[k] ]

            f.close()

            # Handling skeletons
            IJ.run( voxelization, "Skeletonize (2D/3D)", "")
            skeleton = voxelization # For simplicity later, but note that voxelization has been mutated
            IJ.run(skeleton, "32-bit", "")
            IJ.run(skeleton, "Calculator Plus", 'i1=' + str(skeleton.getTitle()) + ' i2=' + str(skeleton.getTitle()) + ' operation=[Scale: i2 = i1 x k1 + k2] k1=0.003921568627 k2=0' )

            IJ.run(skeleton, "Z Project...", "projection=[Max Intensity]")
            skeleton_mp = IJ.getImage()
            IJ.run(skeleton_mp, "Enhance Contrast", "saturated=0.35")
            IJ.saveAsTiff( skeleton_mp, cube_basename + 'skeleton_maxproj.tif' )

            ic = ImageCalculator()
            skeleton_edt = ic.run("Multiply 32-bit stack", edt, skeleton)
            IJ.run( skeleton_edt, 'Fire', '' )


            # Get the histogram data in an array
            hist_nBins = int( ( hist_max - hist_min ) / hist_step )
            #skeleton_edt_stats = edt.getStatistics( Measurements.MEDIAN, hist_nBins, hist_min, hist_max )
            skeleton_edt_stats = StackStatistics( edt, hist_nBins, hist_min, hist_max )
            hist_data = skeleton_edt_stats.getHistogram()
            hist_binLabels = [ ( hist_min + hist_step * el ) for el in range( hist_nBins ) ]

            IJ.run( skeleton_edt, 'Histogram', 'bins=' + str(hist_nBins) + ' x_min=' + str(hist_min) + ' x_max=' + str(hist_max) + ' y_max=Auto stack' )
            skeleton_edt_histogram = WindowManager.getImage( 'Histogram of EDT' )
            IJ.saveAsTiff( skeleton_edt_histogram, cube_basename + 'skeleton_edt_histogram.tif' )

            unit_scale = uniform.getCalibration().getX(1)

            f = open( cube_basename + 'skeleton_edt_histogram.csv', 'w' )
            for k in range( len( hist_data ) ):
                f.write( str(hist_binLabels[k]) + '\t' + str(hist_data[k] * unit_scale) + '\n' )
                all_skeleton_edt_histograms[hist_binLabels[k]] += [ hist_data[k] * unit_scale ]
            f.close()

        else:
            IJ.saveAsTiff( voxelization, cube_basename + 'voxelization.tif' )

        # Free up resources
        if close_after:
            ImageJ3DViewer.close()
            IJ.run( 'Close All', '' )
            IJ.freeMemory()