예제 #1
0
def joinPoints(results, subStacks=None, shiftPoints=True, **args):
    """Joins a list of points obtained from processing a stack in chunks
    
    Arguments:
        results (list): list of point results from the individual sub-processes
        subStacks (list or None): list of all sub-stack information, see :ref:`SubStack`
        shiftPoints (bool): if True shift points to refer to origin of the image stack considered
                            when range specification is given. If False, absolute 
                            position in entire image stack.
    
    Returns:
       tuple: joined points, joined intensities
    """

    nchunks = len(results)
    pointlist = [results[i][0] for i in range(nchunks)]
    intensities = [results[i][1] for i in range(nchunks)]

    results = []
    resultsi = []
    for i in range(nchunks):
        cts = pointlist[i]
        cti = intensities[i]

        if cts.size > 0:
            cts[:, 2] += subStacks[i]["z"][0]
            iid = numpy.logical_and(subStacks[i]["zCenters"][0] <= cts[:, 2],
                                    cts[:, 2] < subStacks[i]["zCenters"][1])
            cts = cts[iid, :]
            results.append(cts)
            if not cti is None:
                cti = cti[iid]
                resultsi.append(cti)

    if results == []:
        if not intensities is None:
            return (numpy.zeros((0, 3)), numpy.zeros((0)))
        else:
            return numpy.zeros((0, 3))
    else:
        points = numpy.concatenate(results)

        if shiftPoints:
            points = points + io.pointShiftFromRange(io.dataSize(
                subStacks[0]["source"]),
                                                     x=subStacks[0]["x"],
                                                     y=subStacks[0]["y"],
                                                     z=0)
        else:
            points = points - io.pointShiftFromRange(io.dataSize(
                subStacks[0]["source"]),
                                                     x=0,
                                                     y=0,
                                                     z=subStacks[0]["z"])
            #absolute offset is added initially via zranges !

        if intensities is None:
            return points
        else:
            return (points, numpy.concatenate(resultsi))
예제 #2
0
def joinPoints(results, subStacks = None, shiftPoints = True, **args):
    """Joins a list of points obtained from processing a stack in chunks
    
    Arguments:
        results (list): list of point results from the individual sub-processes
        subStacks (list or None): list of all sub-stack information, see :ref:`SubStack`
        shiftPoints (bool): if True shift points to refer to origin of the image stack considered
                            when range specification is given. If False, absolute 
                            position in entire image stack.
    
    Returns:
       tuple: joined points, joined intensities
    """
    
    nchunks = len(results);
    pointlist = [results[i][0] for i in range(nchunks)];
    intensities = [results[i][1] for i in range(nchunks)]; 
    
    results = [];
    resultsi = [];
    for i in range(nchunks):
        cts = pointlist[i];
        cti = intensities[i];

        if cts.size > 0:
            cts[:,2] += subStacks[i]["z"][0];
            iid = numpy.logical_and(subStacks[i]["zCenters"][0] <= cts[:,2] , cts[:,2] < subStacks[i]["zCenters"][1]);
            cts = cts[iid,:];
            results.append(cts);
            if not cti is None:
                cti = cti[iid];
                resultsi.append(cti);
            
    if results == []:
        if not intensities is None:
            return (numpy.zeros((0,3)), numpy.zeros((0)));
        else:
            return numpy.zeros((0,3))
    else:
        points = numpy.concatenate(results);
        
        if shiftPoints:
            points = points + io.pointShiftFromRange(io.dataSize(subStacks[0]["source"]), x = subStacks[0]["x"], y = subStacks[0]["y"], z = 0);
        else:
            points = points - io.pointShiftFromRange(io.dataSize(subStacks[0]["source"]), x = 0, y = 0, z = subStacks[0]["z"]); #absolute offset is added initially via zranges !
            
        if intensities is None:
            return points;
        else:
            return (points, numpy.concatenate(resultsi));
예제 #3
0
def voxelizePixel(points,  dataSize = None, weights = None):
    """Mark pixels/voxels of each point in an image array
    
    Arguments:
        points (array): point data array
        dataSize (tuple or None): size of the final output data, if None size is determined by maximal point coordinates
        weights (array or None): weights for each points, if None weights are all 1s.
    
    Returns:
        (array): volumetric data with with points marked in voxels
    """
    
    if dataSize is None:
        dataSize = tuple(int(math.ceil(points[:,i].max())) for i in range(points.shape[1]));
    elif isinstance(dataSize, basestring):
        dataSize = io.dataSize(dataSize);
    
    if weights is None:
        vox = numpy.zeros(dataSize, dtype=numpy.int16);
        for i in range(points.shape[0]):
            if points[i,0] > 0 and points[i,0] < dataSize[0] and points[i,1] > 0 and points[i,1] < dataSize[1] and points[i,2] > 0 and points[i,2] < dataSize[2]:
                vox[points[i,0], points[i,1], points[i,2]] += 1;
    else:
        vox = numpy.zeros(dataSize, dtype=weights.dtype);
        for i in range(points.shape[0]):
            if points[i,0] > 0 and points[i,0] < dataSize[0] and points[i,1] > 0 and points[i,1] < dataSize[1] and points[i,2] > 0 and points[i,2] < dataSize[2]:
                vox[points[i,0], points[i,1], points[i,2]] += weights[i];
    
    return  vox;
예제 #4
0
def voxelizePixel(points, dataSize=None, weights=None):
    """Mark pixels/voxels of each point in an image array
    
    Arguments:
        points (array): point data array
        dataSize (tuple or None): size of the final output data, if None size is determined by maximal point coordinates
        weights (array or None): weights for each points, if None weights are all 1s.
    
    Returns:
        (array): volumetric data with with points marked in voxels
    """

    if dataSize is None:
        dataSize = tuple(
            int(math.ceil(points[:, i].max())) for i in range(points.shape[1]))
    elif isinstance(dataSize, basestring):
        dataSize = io.dataSize(dataSize)

    if weights is None:
        vox = numpy.zeros(dataSize, dtype=numpy.int16)
        for i in range(points.shape[0]):
            if points[i, 0] > 0 and points[i, 0] < dataSize[0] and points[
                    i, 1] > 0 and points[i, 1] < dataSize[1] and points[
                        i, 2] > 0 and points[i, 2] < dataSize[2]:
                vox[points[i, 0], points[i, 1], points[i, 2]] += 1
    else:
        vox = numpy.zeros(dataSize, dtype=weights.dtype)
        for i in range(points.shape[0]):
            if points[i, 0] > 0 and points[i, 0] < dataSize[0] and points[
                    i, 1] > 0 and points[i, 1] < dataSize[1] and points[
                        i, 2] > 0 and points[i, 2] < dataSize[2]:
                vox[points[i, 0], points[i, 1], points[i, 2]] += weights[i]

    return vox
예제 #5
0
def test():
  import os;
  import ClearMap.IO as io
  import ClearMap.Settings as settings
  import ClearMap.ImageProcessing.Ilastik as il;
  reload(il);
  
  ilp = os.path.join(settings.ClearMapPath, 'Test/Ilastik/Test.ilp')
  src = os.path.join(settings.ClearMapPath, 'Test/Data/ImageAnalysis/cfos-substack.tif');
  #out = os.path.join(settings.ClearMapPath, 'Test/Data/Ilastik/image.npy');
  out = None;
  #out = os.path.join(settings.ClearMapPath, 'Test/Data/Ilastik/result\d*.tif');
  
  cls = il.classifyPixel(ilp, src, out);
  print io.dataSize(src)
  print cls.shape
  io.writeData('/home/ckirst/result.raw', cls);
예제 #6
0
def test():
    import os
    import ClearMap.IO as io
    import ClearMap.Settings as settings
    import ClearMap.ImageProcessing.Ilastik as il
    reload(il)

    ilp = os.path.join(settings.ClearMapPath, 'Test/Ilastik/Test.ilp')
    src = os.path.join(settings.ClearMapPath,
                       'Test/Data/ImageAnalysis/cfos-substack.tif')
    #out = os.path.join(settings.ClearMapPath, 'Test/Data/Ilastik/image.npy');
    out = None
    #out = os.path.join(settings.ClearMapPath, 'Test/Data/Ilastik/result\d*.tif');

    cls = il.classifyPixel(ilp, src, out)
    print io.dataSize(src)
    print cls.shape
    io.writeData('/home/ckirst/result.raw', cls)
예제 #7
0
def calculateSubStacks(source, z = all, x = all, y = all, **args):
    """Calculates the chunksize and other info for parallel processing and returns a list of sub-stack objects
    
    The sub-stack information is described in :ref:`SubStack`  
    
    Arguments:
        source (str): image source
        x,y,z (tuple or all): range specifications
        processes (int): number of parallel processes
        chunkSizeMax (int): maximal size of a sub-stack
        chunkSizeMin (int): minial size of a sub-stack
        chunkOverlap (int): minimal sub-stack overlap
        chunkOptimization (bool): optimize chunck sizes to best fit number of processes
        chunkOptimizationSize (bool or all): if True only decrease the chunk size when optimizing
        verbose (bool): print information on sub-stack generation
        
    Returns:
        list: list of sub-stack objects
    """    
    
    #determine z ranges
    fs = io.dataSize(source);
    zs = fs[2];
    zr = io.toDataRange(zs, r = z);
    nz = zr[1] - zr[0];
    
    #calculate optimal chunk sizes
    nchunks, zranges, zcenters = calculateChunkSize(nz, **args);
    
    #adjust for the zrange
    zcenters = [c + zr[0] for c in zcenters];
    zranges = [(zc[0] + zr[0], zc[1] + zr[0]) for zc in zranges];
    
    #create substacks
    subStacks = [];
    indexlo = zr[0];
    
    for i in range(nchunks):
        
        indexhi = int(round(zcenters[i+1]));
        if indexhi > zr[1] or i == nchunks - 1:
            indexhi = zr[1];
        
        zs = zranges[i][1] - zranges[i][0];
        
        subStacks.append({"stackId" : i, "nStacks" : nchunks, 
                          "source" : source, "x" : x, "y" : y, "z" : zranges[i], 
                          "zCenters" : (zcenters[i], zcenters[i+1]),
                          "zCenterIndices" : (indexlo, indexhi),
                          "zSubStackCenterIndices" : (indexlo - zranges[i][0], zs - (zranges[i][1] - indexhi))});
        
        indexlo = indexhi; # + 1;
    
    return subStacks;
def calculateSubStacks(source, z = all, x = all, y = all, **args):
    """Calculates the chunksize and other info for parallel processing and returns a list of sub-stack objects
    
    The sub-stack information is described in :ref:`SubStack`  
    
    Arguments:
        source (str): image source
        x,y,z (tuple or all): range specifications
        processes (int): number of parallel processes
        chunkSizeMax (int): maximal size of a sub-stack
        chunkSizeMin (int): minial size of a sub-stack
        chunkOverlap (int): minimal sub-stack overlap
        chunkOptimization (bool): optimize chunck sizes to best fit number of processes
        chunkOptimizationSize (bool or all): if True only decrease the chunk size when optimizing
        verbose (bool): print information on sub-stack generation
        
    Returns:
        list: list of sub-stack objects
    """    
    
    #determine z ranges
    fs = io.dataSize(source);
    zs = fs[2];
    zr = io.toDataRange(zs, r = z);
    nz = zr[1] - zr[0];
    
    #calculate optimal chunk sizes
    nchunks, zranges, zcenters = calculateChunkSize(nz, **args);
    
    #adjust for the zrange
    zcenters = [c + zr[0] for c in zcenters];
    zranges = [(zc[0] + zr[0], zc[1] + zr[0]) for zc in zranges];
    
    #create substacks
    subStacks = [];
    indexlo = zr[0];
    
    for i in range(nchunks):
        
        indexhi = int(round(zcenters[i+1]));
        if indexhi > zr[1] or i == nchunks - 1:
            indexhi = zr[1];
        
        zs = zranges[i][1] - zranges[i][0];
        
        subStacks.append({"stackId" : i, "nStacks" : nchunks, 
                          "source" : source, "x" : x, "y" : y, "z" : zranges[i], 
                          "zCenters" : (zcenters[i], zcenters[i+1]),
                          "zCenterIndices" : (indexlo, indexhi),
                          "zSubStackCenterIndices" : (indexlo - zranges[i][0], zs - (zranges[i][1] - indexhi))});
        
        indexlo = indexhi; # + 1;
    
    return subStacks;
예제 #9
0
def openData(dataSource, x = all, y = all, z = all, inverse = False, cleanUp = True): 
    """Open image in ImageJ 
    
    Arguments:
        dataSouce (str or array): volumetric image data
        x, y, z (all or tuple): sub-range specification
        inverse (bool):invert image
    
    Returns:
        (object): figure handle
    """

    checkImageJInitialized();
    
    if isinstance(dataSource, numpy.ndarray):
      filename = tempfile.mktemp(suffix = '.mhd', prefix = 'CM_ImageJ');
      io.writeData(filename, dataSource, x = x, y = y, z = z);
      temp= True
      dSize = dataSource.shape;
    else:
      filename = dataSource;
      temp = False;
      dSize = io.dataSize(dataSource);
    
    colorImage = len(dSize) == 4;
  
    if colorImage:
      macro = ('open("%s"); ' % filename) + \
               'run("Stack to Hyperstack...", "order=xyzct channels=%d slices=%d frames=1 display=Color"); ' % (dSize[3], dSize[2]) + \
               'Stack.setDisplayMode("composite");';
    else:
      macro = ('open("%s");' % filename);
    
    cmd = ImageJBinary + " -eval '%s'" % macro;
    
    print 'running: %s' % cmd
    res = os.system(cmd);
  
    if res != 0:
      raise RuntimeError('openData: failed executing: ' + cmd);
    
    
    if cleanUp and temp:
      os.remove(filename);
      filepath, imagename = os.path.split(filename);
      imagename = imagename[:-4] + '.raw';
      os.remove(os.path.join(filepath, imagename));
    
    return macro;
예제 #10
0
def testCompletedCumulativesInSpheres(points1, intensities1, points2, intensities2, dataSize = lbl.DefaultLabeledImageFile, radius = 100, method = 'AndresonDarling'):
    """Performs completed cumulative distribution tests for each pixel using points in a ball centered at that cooridnates, returns 4 arrays p value, statistic value, number in each group"""
    
    #TODO: sinple implementation -> slow -> speed up
    dataSize = io.dataSize(dataSize);
    if len(dataSize) != 3:
        raise RuntimeError('dataSize expected to be 3d');
    
    # distances^2 to origin
    x1= points1[:,0]; y1 = points1[:,1]; z1 = points1[:,2]; i1 = intensities1;
    d1 = x1 * x1 + y1 * y1 + z1 * z1;
    
    x2 = points2[:,0]; y2 = points2[:,1]; z2 = points2[:,2]; i2 = intensities2;
    d2 = x2 * x2 + y2 * y2 + z2 * z2;
        
    r2 = radius * radius; # TODO: inhomogenous in 3d !
    
    p = numpy.zeros(dataSize);
    s = numpy.zeros(dataSize);
    n1 = numpy.zeros(dataSize, dtype = 'int');
    n2 = numpy.zeros(dataSize, dtype = 'int');
    
    for x in range(dataSize[0]):
    #print x
        for y in range(dataSize[1]):
            #print y
            for z in range(dataSize[2]):
                #print z
                d11 = d1 - 2 * (x * x1 + y * y1 + z * z1) + (x*x + y*y + z*z);
                d22 = d2 - 2 * (x * x2 + y * y2 + z * z2) + (x*x + y*y + z*z);
                
                ii1 = d11 < r2;
                ii2 = d22 < r2;

                n1[x,y,z] = ii1.sum();
                n2[x,y,z] = ii2.sum();
                
                if n1[x,y,z] > 0 and n2[x,y,z] > 0:
                    (pp, ss) = self.testCompletedCumulatives((i1[ii1], i2[ii2]), method = method);
                else:
                    pp = 0; ss = 0;
                
                p[x,y,z] = pp; 
                s[x,y,z] = ss;
                
    
    return (p,s,n1,n2);
예제 #11
0
def voxelize(points, dataSize = None, sink = None, voxelizeParameter = None,  method = 'Spherical', size = (5,5,5), weights = None):
    """Converts a list of points into an volumetric image array
    
    Arguments:
        points (array): point data array
        dataSize (tuple): size of final image
        sink (str, array or None): the location to write or return the resulting voxelization image, if None return array
        voxelizeParameter (dict):
            ========== ==================== ===========================================================
            Name       Type                 Descritption
            ========== ==================== ===========================================================
            *method*   (str or None)        method for voxelization: 'Spherical', 'Rectangular' or 'Pixel'
            *size*     (tuple)              size parameter for the voxelization
            *weights*  (array or None)      weights for each point, None is uniform weights                          
            ========== ==================== ===========================================================      
    Returns:
        (array): volumetric data of smeared out points
    """
    
    if dataSize is None:
        dataSize = tuple(int(math.ceil(points[:,i].max())) for i in range(points.shape[1]));
    elif isinstance(dataSize, basestring):
        dataSize = io.dataSize(dataSize);
    
    points = io.readPoints(points);
        
    if method.lower() == 'spherical':
        if weights is None:
            data = vox.voxelizeSphere(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2]);
        else:
            data = vox.voxelizeSphereWithWeights(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2], weights);
           
    elif method.lower() == 'rectangular':
        if weights is None:
            data = vox.voxelizeRectangle(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2]);
        else:
            data = vox.voxelizeRectangleWithWeights(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2], weights);
    
    elif method.lower() == 'pixel':
        data = voxelizePixel(points, dataSize, weights);
        
    else:
        raise RuntimeError('voxelize: mode: %s not supported!' % method);
    
    return io.writeData(sink, data);
예제 #12
0
def voxelize(points, dataSize = None, sink = None, voxelizeParameter = None,  method = 'Spherical', size = (5,5,5), weights = None):
    """Converts a list of points into an volumetric image array

    Arguments:
        points (array): point data array
        dataSize (tuple): size of final image
        sink (str, array or None): the location to write or return the resulting voxelization image, if None return array
        voxelizeParameter (dict):
            ========== ==================== ===========================================================
            Name       Type                 Descritption
            ========== ==================== ===========================================================
            *method*   (str or None)        method for voxelization: 'Spherical', 'Rectangular' or 'Pixel'
            *size*     (tuple)              size parameter for the voxelization
            *weights*  (array or None)      weights for each point, None is uniform weights
            ========== ==================== ===========================================================
    Returns:
        (array): volumetric data of smeared out points
    """

    if dataSize is None:
        dataSize = tuple(int(math.ceil(points[:,i].max())) for i in range(points.shape[1]));
    elif isinstance(dataSize, basestring):
        dataSize = io.dataSize(dataSize);

    points = io.readPoints(points);

    if method.lower() == 'spherical':
        if weights is None:
            data = vox.voxelizeSphere(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2]);
        else:
            data = vox.voxelizeSphereWithWeights(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2], weights);

    elif method.lower() == 'rectangular':
        if weights is None:
            data = vox.voxelizeRectangle(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2]);
        else:
            data = vox.voxelizeRectangleWithWeights(points.astype('float'), dataSize[0], dataSize[1], dataSize[2], size[0], size[1], size[2], weights);

    elif method.lower() == 'pixel':
        data = voxelizePixel(points, dataSize, weights);

    else:
        raise RuntimeError('voxelize: mode: %s not supported!' % method);

    return io.writeData(sink, data);
예제 #13
0
def dataSize(filename, **args):
    """Returns size of data stored as a file list
    
    Arguments:
        filename (str): file name as regular expression
        x,y,z (tuple): data range specifications
    
    Returns:
        tuple: data size
    """

    fp, fl = readFileList(filename)
    nz = len(fl)

    d2 = io.dataSize(os.path.join(fp, fl[0]))
    if not len(d2) == 2:
        raise RuntimeError("FileList: importing multiple files of dim %d not supported!" % len(d2))

    dims = d2 + (nz,)
    return io.dataSizeFromDataRange(dims, **args)
예제 #14
0
def dataSize(filename, **args):
    """Returns size of data stored as a file list
    
    Arguments:
        filename (str): file name as regular expression
        x,y,z (tuple): data range specifications
    
    Returns:
        tuple: data size
    """

    fp, fl = readFileList(filename)
    nz = len(fl)

    d2 = io.dataSize(os.path.join(fp, fl[0]))
    if not len(d2) == 2:
        raise RuntimeError(
            "FileList: importing multiple files of dim %d not supported!" %
            len(d2))

    dims = d2 + (nz, )
    return io.dataSizeFromDataRange(dims, **args)
datadir ='/home/mtllab/Documents/th/';

fn = os.path.join(datadir, r'160412_mosaic_15-20-19/15-20-19_mosaic_UltraII\[(?P<row>\d{2}) x (?P<col>\d{2})\]_C00_xyz-Table Z(?P<z>\d{4}).ome.tif')

_, gr = st.findFileList(fn , sort = True, groups = ['row','col'], absolute = True)
groups = [];
for i in range(gr.shape[1]):
    groups.append(np.unique(gr[:,i]));

print groups

for i in groups[0]:
    for j in groups[1]:
        fileExpression = os.path.join(datadir, r'160412_mosaic_15-20-19/15-20-19_mosaic_UltraII\[%s x %s]_C00_xyz-Table Z\d{4}.ome.tif' % (i,j))

        io.dataSize(fileExpression)

        io.readMetaData(fileExpression, info = ['size', 'overlap', 'resolution'])


        import ClearMap.IO.FileList as fl;
        reload(fl)

        fncrop = os.path.join(datadir, r'cropped/15-20-19_mosaic_UltraII_%s_x_%s_C00_xyz-Table Z\d{4}.ome.tif' % (i,j))


        fc = fl.cropData(fileExpression, fncrop, x = (400, -400), y = (550, -550),  adjustOverlap = True, processes = all)
        #fc1 = fl.firstFile(fc)
        #io.readMetaData(fc1, info = ['overlap', 'resolution', 'size']);

예제 #16
0
def findFileInfo(filename):
    """Tries to infer relevant information from filename for tiling / stitching
  
  Arguments:
    filename (str): filename to infer information from
    
  Returns:
    dict: dictionary with relavant information: resolution (microns per pixel), overlap (microns), size (pixel)
    
  Note:
    resolution is in microns per pixel, overlap is in microns and size is in pixel
  """
    # TODO: move this to the individual file readers

    # this is for ome tif images
    from PIL import Image
    from PIL.ExifTags import TAGS

    def ome_info(fn):
        ret = {}
        i = Image.open(fn)
        info = i.tag.as_dict()
        for tag, value in info.iteritems():
            decoded = TAGS.get(tag)
            ret[decoded] = value
        return ret

    imginfo = ome_info(filename)
    keys = imginfo.keys()

    finfo = {"resolution": None, "overlap": None, "size": None}

    # get image sizes
    if ("ImageHeight" in keys) and ("ImageWidth" in keys):
        finfo["size"] = (imginfo["ImageWidth"], imginfo["ImageHeight"])
    else:
        finfo["size"] = io.dataSize(filename)

    if "ImageDescription" in keys:
        imgxml = imginfo["ImageDescription"]
        if isinstance(imgxml, tuple):
            imgxml = imgxml[0]
        imgxml = etree.fromstring(str(imgxml))

        # get resolution
        pix = [x for x in imgxml.iter("{*}Pixels")]
        if len(pix) > 0:
            pix = pix[0].attrib
            keys = pix.keys()
            if "PhysicalSizeX" in keys and "PhysicalSizeY" in keys and "PhysicalSizeZ" in keys:
                finfo["resolution"] = (
                    float(pix["PhysicalSizeX"]),
                    float(pix["PhysicalSizeY"]),
                    float(pix["PhysicalSizeZ"]),
                )

        # get overlap
        e1 = [x for x in imgxml.iter("{*}xyz-Table_X_Overlap")]
        e2 = [x for x in imgxml.iter("{*}xyz-Table_Y_Overlap")]
        if len(e1) > 0 and len(e2) > 0:
            finfo["overlap"] = (float(e1[0].attrib["Value"]), float(e2[0].attrib["Value"]))

    return finfo
def correctIllumination(img, correctIlluminationParameter = None, flatfield = None, background = None, scaling = None, save = None, verbose = False, 
                        subStack = None, out = sys.stdout, **parameter):
    """Correct illumination variations
    
     The intensity image :math:`I(x)` given a flat field :math:`F(x)` and 
     a background :math:`B(x)` the image is corrected to :math:`C(x)` as:
     
     .. math:
         C(x) = \\frac{I(x) - B(x)}{F(x) - B(x)}
         
     If the background is not given :math:`B(x) = 0`. 
     
     The correction is done slice by slice assuming the data was collected with 
     a light sheet microscope.
     
     The image is finally optionally scaled.
  
    Arguments:
        img (array): image data
        findCenterOfMaximaParameter (dict):
            ============ ==================== ===========================================================
            Name         Type                 Descritption
            ============ ==================== ===========================================================
            *flatfield*  (str, None or array) flat field intensities, if None d onot correct image for
                                              illumination, if True the 
            *background* (str, None or array) background image as file name or array
                                              if None background is assumed to be zero
            *scaling*    (str or None)        scale the corrected result by this factor
                                              if 'max'/'mean' scale to keep max/mean invariant
            *save*       (str or None)        save the corrected image to file
            *verbose*    (bool or int)        print / plot information about this step 
            ============ ==================== ===========================================================
        subStack (dict or None): sub-stack information 
        verbose (bool): print progress info 
        out (object): object to write progress info to
    
    Returns:
        array: illumination corrected image
        
        
    References: 
        Fundamentals of Light Microscopy and Electronic Imaging, p 421        
        
    See Also:
        :const:`DefaultFlatFieldLineFile`
    """  
    
    flatfield  = getParameter(correctIlluminationParameter, "flatfield",  flatfield);
    background = getParameter(correctIlluminationParameter, "background", background);
    scaling    = getParameter(correctIlluminationParameter, "scaling",    scaling);
    save       = getParameter(correctIlluminationParameter, "save",       save);
    verbose    = getParameter(correctIlluminationParameter, "verbose",    verbose);

    if verbose:    
        if flatfield is None or isinstance(flatfield, str) or flatfield is True:
            fld = flatfield;
        else:
            fld = "image of size %s" % str(flatfield.shape);
    
        if background is None or isinstance(background, str):
            bkg = background;
        else:
            bkg = "image of size %s" % str(background.shape);
        
        writeParameter(out = out, head = 'Illumination correction:', flatfield = fld, background = bkg, scaling = scaling, save = save);  
    
    
    print subStack;
 
    if not subStack is None:
        x = subStack["x"];
        y = subStack["y"];
    else:
        x = all;
        y = all;
    
    #print "sizes", x, y, img.shape
 
    #read data  
 
    timer = Timer(); 
 
    if flatfield is None:
        return img;
        
    elif flatfield is True:
        # default flatfield correction
    
        if subStack is None:    
            flatfield = flatfieldFromLine(DefaultFlatFieldLineFile, img.shape[0]);
        else:
            dataSize = io.dataSize(subStack["source"]);
            flatfield = flatfieldFromLine(DefaultFlatFieldLineFile, dataSize[0]);
            
    elif isinstance(flatfield, str):
        # point or image file
        if io.isPointFile(flatfield):
            if subStack is None:    
                flatfield = flatfieldFromLine(flatfield, img.shape[0]);
            else:
               dataSize = io.dataSize(subStack["source"]);
               flatfield = flatfieldFromLine(flatfield, dataSize[0]);
        else:
            flatfield = io.readData(flatfield);
    
    ffmean = flatfield.mean();    
    ffmax = flatfield.max();

    #correct for subset
    flatfield = io.readData(flatfield, x = x, y = y);   
    
    background = io.readData(background, x = x, y = y);
    
    if flatfield.shape != img[:,:,0].shape:
        raise RuntimeError("correctIllumination: flatfield does not match image size: %s vs %s" % (flatfield.shape,  img[:,:,0].shape));
    
    #convert to float for scaling
    dtype = img.dtype;
    img = img.astype('float32');
    flatfield = flatfield.astype('float32');
    
    # illumination correction in each slice
    if background is None:
        for z in range(img.shape[2]):
            img[:,:,z] = img[:,:,z] / flatfield;
    else:
        if background.shape != flatfield.shape:
            raise RuntimeError("correctIllumination: background does not match image size: %s vs %s" % (background.shape,  img[:,:,0].shape));        
        background = background.astype('float32');

        flatfield = (flatfield - background);
        for z in range(img.shape[2]):
            img[:,:,z] = (img[:,:,z] - background) / flatfield;
    
        
    # rescale
    if scaling is True:
        scaling = "mean";
    
    if isinstance(scaling, str):
        if scaling.lower() == "mean":
            # scale back by average flat field correction:
            sf = ffmean;
        elif scaling.lower() == "max":
            sf = ffmax;
        else:
            raise RuntimeError('Scaling not "Max" or "Mean" but %s' % scaling);
    else:
        sf = scaling;
      
    if verbose:
         writeParameter(out = out, head = 'Illumination correction:',  scaling = sf);
    
        
    
    if not sf is None:
        img = img * sf;
        img = img.astype(dtype);
    
    
    #write result for inspection
    if not save is None:
        writeSubStack(save, img, subStack = subStack);    
    
    #plot result for inspection
    if verbose > 1:
        plotTiling(img);
    
    if verbose:
        out.write(timer.elapsedTime(head = 'Illumination correction') + '\n');    
    
    return img 
예제 #18
0
def correctIllumination(img,
                        correctIlluminationParameter=None,
                        flatfield=None,
                        background=None,
                        scaling=None,
                        save=None,
                        verbose=False,
                        subStack=None,
                        out=sys.stdout,
                        **parameter):
    """Correct illumination variations
    
     The intensity image :math:`I(x)` given a flat field :math:`F(x)` and 
     a background :math:`B(x)` the image is corrected to :math:`C(x)` as:
     
     .. math:
         C(x) = \\frac{I(x) - B(x)}{F(x) - B(x)}
         
     If the background is not given :math:`B(x) = 0`. 
     
     The correction is done slice by slice assuming the data was collected with 
     a light sheet microscope.
     
     The image is finally optionally scaled.
  
    Arguments:
        img (array): image data
        findCenterOfMaximaParameter (dict):
            ============ ==================== ===========================================================
            Name         Type                 Descritption
            ============ ==================== ===========================================================
            *flatfield*  (str, None or array) flat field intensities, if None d onot correct image for
                                              illumination, if True the 
            *background* (str, None or array) background image as file name or array
                                              if None background is assumed to be zero
            *scaling*    (str or None)        scale the corrected result by this factor
                                              if 'max'/'mean' scale to keep max/mean invariant
            *save*       (str or None)        save the corrected image to file
            *verbose*    (bool or int)        print / plot information about this step 
            ============ ==================== ===========================================================
        subStack (dict or None): sub-stack information 
        verbose (bool): print progress info 
        out (object): object to write progress info to
    
    Returns:
        array: illumination corrected image
        
        
    References: 
        Fundamentals of Light Microscopy and Electronic Imaging, p 421        
        
    See Also:
        :const:`DefaultFlatFieldLineFile`
    """

    flatfield = getParameter(correctIlluminationParameter, "flatfield",
                             flatfield)
    background = getParameter(correctIlluminationParameter, "background",
                              background)
    scaling = getParameter(correctIlluminationParameter, "scaling", scaling)
    save = getParameter(correctIlluminationParameter, "save", save)
    verbose = getParameter(correctIlluminationParameter, "verbose", verbose)

    if verbose:
        if flatfield is None or isinstance(flatfield,
                                           str) or flatfield is True:
            fld = flatfield
        else:
            fld = "image of size %s" % str(flatfield.shape)

        if background is None or isinstance(background, str):
            bkg = background
        else:
            bkg = "image of size %s" % str(background.shape)

        writeParameter(out=out,
                       head='Illumination correction:',
                       flatfield=fld,
                       background=bkg,
                       scaling=scaling,
                       save=save)

    print subStack

    if not subStack is None:
        x = subStack["x"]
        y = subStack["y"]
    else:
        x = all
        y = all

    #print "sizes", x, y, img.shape

    #read data

    timer = Timer()

    if flatfield is None:
        return img

    elif flatfield is True:
        # default flatfield correction

        if subStack is None:
            flatfield = flatfieldFromLine(DefaultFlatFieldLineFile,
                                          img.shape[0])
        else:
            dataSize = io.dataSize(subStack["source"])
            flatfield = flatfieldFromLine(DefaultFlatFieldLineFile,
                                          dataSize[0])

    elif isinstance(flatfield, str):
        # point or image file
        if io.isPointFile(flatfield):
            if subStack is None:
                flatfield = flatfieldFromLine(flatfield, img.shape[0])
            else:
                dataSize = io.dataSize(subStack["source"])
                flatfield = flatfieldFromLine(flatfield, dataSize[0])
        else:
            flatfield = io.readData(flatfield)

    ffmean = flatfield.mean()
    ffmax = flatfield.max()

    #correct for subset
    flatfield = io.readData(flatfield, x=x, y=y)

    background = io.readData(background, x=x, y=y)

    if flatfield.shape != img[:, :, 0].shape:
        raise RuntimeError(
            "correctIllumination: flatfield does not match image size: %s vs %s"
            % (flatfield.shape, img[:, :, 0].shape))

    #convert to float for scaling
    dtype = img.dtype
    img = img.astype('float32')
    flatfield = flatfield.astype('float32')

    # illumination correction in each slice
    if background is None:
        for z in range(img.shape[2]):
            img[:, :, z] = img[:, :, z] / flatfield
    else:
        if background.shape != flatfield.shape:
            raise RuntimeError(
                "correctIllumination: background does not match image size: %s vs %s"
                % (background.shape, img[:, :, 0].shape))
        background = background.astype('float32')

        flatfield = (flatfield - background)
        for z in range(img.shape[2]):
            img[:, :, z] = (img[:, :, z] - background) / flatfield

    # rescale
    if scaling is True:
        scaling = "mean"

    if isinstance(scaling, str):
        if scaling.lower() == "mean":
            # scale back by average flat field correction:
            sf = ffmean
        elif scaling.lower() == "max":
            sf = ffmax
        else:
            raise RuntimeError('Scaling not "Max" or "Mean" but %s' % scaling)
    else:
        sf = scaling

    if verbose:
        writeParameter(out=out, head='Illumination correction:', scaling=sf)

    if not sf is None:
        img = img * sf
        img = img.astype(dtype)

    #write result for inspection
    if not save is None:
        writeSubStack(save, img, subStack=subStack)

    #plot result for inspection
    if verbose > 1:
        plotTiling(img)

    if verbose:
        out.write(timer.elapsedTime(head='Illumination correction') + '\n')

    return img
예제 #19
0
def cropData(source, sink=None, x=all, y=all, z=all, adjustOverlap=False, verbose=True, processes=all):
    """Crop source from start to stop point
  
  Arguments:
    source (str or array): filename or data array of source
    sink (str or None): filename or sink
    x,y,z (tuple or all): the range to crop the data to
    adjustOverlap (bool): correct overlap meta data if exists
  
  Return:
    str or array: array or filename with cropped data
  """

    if sink is None:
        return readDataFiles(source, x=x, y=y, z=z)
    else:  # sink assumed to be file expression

        if not io.isFileExpression(sink):
            raise RuntimeError("cropping data to different format not supported!")

        fileheader, fileext, digitfrmt = splitFileExpression(sink)

        # read first image to get data size and type
        fp, fl = readFileList(source)
        nz = len(fl)
        rz = io.toDataRange(nz, r=z)

        if adjustOverlap:  # change overlap in first file
            try:
                fn = os.path.join(fp, fl[0])
                info = io.readMetaData(fn, info=["description", "overlap", "resolution"])
                description = str(info["description"])
                overlap = numpy.array(info["overlap"], dtype=float)
                resolution = numpy.array(info["resolution"], dtype=float)

            except:
                raise RuntimeWarning("could not modify overlap!")

            fullsize = io.dataSize(fn)
            data = io.readData(fn, x=x, y=y)

            # overlap in pixels
            poverlap = overlap[:2] / resolution[:2]
            print poverlap

            # cropped pixel
            xr = io.toDataRange(fullsize[0], r=x)
            yr = io.toDataRange(fullsize[1], r=y)

            print xr
            print yr
            print fullsize

            poverlap[0] = poverlap[0] - xr[0] - (fullsize[0] - xr[1])
            poverlap[1] = poverlap[1] - yr[0] - (fullsize[1] - yr[1])
            print poverlap

            # new overlap in microns
            overlap = poverlap * resolution[:2]

            # check for consistency
            if numpy.abs(fullsize[0] - xr[1] - xr[0]) > 1 or numpy.abs(fullsize[1] - yr[1] - yr[0]) > 1:
                raise RuntimeWarning("cropping is inconsistent with overlap )modification!")

            # change image description
            import ClearMap.IO.TIF as CMTIF

            description = CMTIF.changeOMEMetaDataString(description, {"overlap": overlap})
            print len(description)

            # write first file
            fnout = fileheader + (digitfrmt % 0) + fileext
            io.writeData(fnout, data, info=description)

            zr = range(rz[0] + 1, rz[1])
        else:
            zr = range(rz[0], rz[1])

        print zr
        nZ = len(zr)

        if processes is None:
            processes = 1
        if processes is all:
            processes = multiprocessing.cpu_count()

        if processes > 1:  # parallel processing
            pool = multiprocessing.Pool(processes=processes)
            argdata = []

            for i, z in enumerate(zr):
                if verbose:
                    argdata.append(
                        (os.path.join(fp, fl[z]), fileheader + (digitfrmt % (i + 1)) + fileext, x, y, (i + 1), (nZ + 1))
                    )
                else:
                    argdata.append(
                        (os.path.join(fp, fl[z]), fileheader + (digitfrmt % (i + 1)) + fileext, x, y, None, None)
                    )

            pool.map(_cropParallel, argdata)

        else:  # sequential processing
            for i, z in enumerate(zr):
                if verbose:
                    print "cropData: corpping image %d / %d" % (i + 1, nZ + 1)

                fileSource = os.path.join(fp, fl[z])
                data = io.readData(fileSource, x=x, y=y)

                fileSink = fileheader + (digitfrmt % (i + 1)) + fileext
                io.writeData(fileSink, data)

        return sink