Exemple #1
0
def mean_projection(br, bw, x_range, y_range, **kwargs):
    """ Calculate the mean intensity projection

    Args:
        br (BioReader object): input file object
        bw (BioWriter object): output file object
        x_range (tuple): x-range of the img to be processed
        y_range (tuple): y-range of the img to be processed

    Returns:
        image array : Mean IP of the input volume
    """
    with ProcessManager.thread():
        br.max_workers = ProcessManager._active_threads
        bw.max_workers = ProcessManager._active_threads

        # x,y range of the volume
        x, x_max = x_range
        y, y_max = y_range

        # iterate over depth
        out_image = np.zeros((y_max - y, x_max - x), dtype=np.float64)
        for ind, z in enumerate(range(0, br.Z, tile_size_z)):
            z_max = min([br.Z, z + tile_size_z])

            out_image += np.sum(br[y:y_max, x:x_max, z:z_max,
                                   ...].astype(np.float64),
                                axis=2).squeeze()

        # output image
        out_image /= br.Z
        bw[y:y_max, x:x_max, 0:1, 0, 0] = out_image.astype(br.dtype)
Exemple #2
0
def unshade_image(img,
                  out_dir,
                  brightfield,
                  darkfield,
                  photobleach=None,
                  offset=None):

    with ProcessManager.thread() as active_threads:

        with BioReader(img, max_workers=active_threads.count) as br:

            with BioWriter(out_dir.joinpath(img.name),
                           metadata=br.metadata,
                           max_workers=active_threads.count) as bw:

                new_img = br[:, :, :1, 0, 0].squeeze().astype(np.float32)

                new_img = new_img - darkfield
                new_img = np.divide(new_img, brightfield)

                if photobleach != None:
                    new_img = new_img - np.float32(photobleach)
                if offset != None:
                    new_img = new_img + np.float32(offset)

                new_img[new_img < 0] = 0

                new_img = new_img.astype(br.dtype)

                bw[:] = new_img
Exemple #3
0
        def load_and_scale(*args,**kwargs):
            sub_image = _get_higher_res(**kwargs)

            with ProcessManager.thread():
                image = args[0]
                x_ind = args[1]
                y_ind = args[2]
                image[y_ind[0]:y_ind[1],x_ind[0]:x_ind[1]] = kwargs['slide_writer'].scale(sub_image)
Exemple #4
0
 def load_and_store(fname, ind):
     with ProcessManager.thread() as active_threads:
         with BioReader(fname['file'],
                        max_workers=active_threads.count) as br:
             I = np.squeeze(br[:, :, :1, 0, 0])
         img_stack[:, :, ind] = cv2.resize(
             I, (OPTIONS['size'], OPTIONS['size']),
             interpolation=cv2.INTER_LINEAR).astype(np.float64)
Exemple #5
0
def label_cython(input_path: Path, output_path: Path, connectivity: int):
    """ Label the input image and writes labels back out.

    Args:
        input_path: Path to input image.
        output_path: Path for output image.
        connectivity: Connectivity kind.
    """
    with ProcessManager.thread() as active_threads:
        with BioReader(
                input_path,
                max_workers=active_threads.count,
        ) as reader:

            with BioWriter(
                    output_path,
                    max_workers=active_threads.count,
                    metadata=reader.metadata,
            ) as writer:
                # Load an image and convert to binary
                image = numpy.squeeze(reader[..., 0, 0])

                if not numpy.any(image):
                    writer.dtype = numpy.uint8
                    writer[:] = numpy.zeros_like(image, dtype=numpy.uint8)
                    return

                image = (image > 0)
                if connectivity > image.ndim:
                    ProcessManager.log(
                        f'{input_path.name}: Connectivity is not less than or equal to the number of image dimensions, '
                        f'skipping this image. connectivity={connectivity}, ndim={image.ndim}'
                    )
                    return

                # Run the labeling algorithm
                labels = ftl.label_nd(image, connectivity)

                # Save the image
                writer.dtype = labels.dtype
                writer[:] = labels
    return True
Exemple #6
0
def max_min_projection(br, bw, x_range, y_range, **kwargs):
    """ Calculate the max or min intensity
    projection of a section of the input image.

    Args:
        br (BioReader object): input file object
        bw (BioWriter object): output file object
        x_range (tuple): x-range of the img to be processed
        y_range (tuple): y-range of the img to be processed

    Returns:
        image array : Max IP of the input volume
    """
    with ProcessManager.thread():
        br.max_workers = ProcessManager._active_threads
        bw.max_workers = ProcessManager._active_threads

        # set projection method
        if not 'method' in kwargs:
            method = np.max
        else:
            method = kwargs['method']

        # x,y range of the volume
        x, x_max = x_range
        y, y_max = y_range

        # iterate over depth
        for ind, z in enumerate(range(0, br.Z, tile_size_z)):
            z_max = min([br.Z, z + tile_size_z])
            if ind == 0:
                out_image = method(br[y:y_max, x:x_max, z:z_max, 0, 0], axis=2)
            else:
                out_image = np.dstack((out_image,
                                       method(br[y:y_max, x:x_max, z:z_max, 0,
                                                 0],
                                              axis=2)))

        # output image
        bw[y:y_max, x:x_max, 0:1, 0, 0] = method(out_image, axis=2)
Exemple #7
0
def label_thread(input_path, output_path, connectivity):

    with ProcessManager.thread() as active_threads:
        with bfio.BioReader(input_path,
                            max_workers=active_threads.count) as br:
            with bfio.BioWriter(output_path,
                                max_workers=active_threads.count,
                                metadata=br.metadata) as bw:

                # Load an image and convert to binary
                image = (br[..., 0, 0] > 0).squeeze()

                if connectivity > image.ndim:
                    ProcessManager.log(
                        "{}: Connectivity is not less than or equal to the number of image dimensions, skipping this image. connectivity={}, ndim={}"
                        .format(input_path.name, connectivity, image.ndim))
                    return

                # Run the labeling algorithm
                labels = ftl.label_nd(image.squeeze(), connectivity)

                # Save the image
                bw.dtype = labels.dtype
                bw[:] = labels
Exemple #8
0
def make_tile(x_min: int,
              x_max: int,
              y_min: int,
              y_max: int,
              z: int,
              parsed_vector: dict,
              bw: BioWriter) -> None:
    """Create a supertile from images and save to file

    This method builds a supertile, which is a section of the image defined by
    the global variable ``chunk_size`` and is composed of multiple smaller tiles
    defined by the ``BioReader._TILE_SIZE``. Images are stored on disk as
    compressed chunks that are ``_TILE_SIZE`` length and width, and the upper
    left pixel of a tile is always a multiple of ``_TILE_SIZE``. To prevent
    excessive file loading and to ensure files are properly placed, supertiles
    are created from smaller images and saved all at once.

    Args:
        x_min: Minimum x bound of the tile
        x_max: Maximum x bound of the tile
        y_min: Minimum y bound of the tile
        y_max: Maximum y bound of the tile
        z: Current z position to assemble
        parsed_vector: The result of _parse_vector
        local_threads: Used to determine the number of concurrent threads to run
        bw: The output file object

    """

    with ProcessManager.thread() as active_threads:

        # Get the data type
        with BioReader(parsed_vector['filePos'][0]['file']) as br:
            dtype = br.dtype

        # initialize the supertile
        template = numpy.zeros((y_max-y_min,x_max-x_min,1,1,1),dtype=dtype)

        # get images in bounds of current super tile
        for f in parsed_vector['filePos']:

            # check that image is within the x-tile bounds
            if (f['posX'] >= x_min and f['posX'] <= x_max) \
                or (f['posX']+f['width'] >= x_min and f['posX']+f['width'] <= x_max) \
                or (f['posX'] <= x_min and f['posX']+f['width'] >= x_max):

                # check that image is within the y-tile bounds
                if (f['posY'] >= y_min and f['posY'] <= y_max) \
                    or (f['posY']+f['height'] >= y_min and f['posY']+f['height'] <= y_max) \
                    or (f['posY'] <= y_min and f['posY']+f['height'] >= y_max):

                    # get bounds of image within the tile
                    Xt = [max(0,f['posX']-x_min)]
                    Xt.append(min(x_max-x_min,f['posX']+f['width']-x_min))
                    Yt = [max(0,f['posY']-y_min)]
                    Yt.append(min(y_max-y_min,f['posY']+f['height']-y_min))

                    # get bounds of image within the image
                    Xi = [max(0,x_min - f['posX'])]
                    Xi.append(min(f['width'],x_max - f['posX']))
                    Yi = [max(0,y_min - f['posY'])]
                    Yi.append(min(f['height'],y_max - f['posY']))

                    # Load the image
                    with BioReader(f['file'],max_workers=active_threads.count) as br:
                        image = br[Yi[0]:Yi[1],Xi[0]:Xi[1],z:z+1,0,0] # only get the first c,t layer

                    # Put the image in the buffer
                    template[Yt[0]:Yt[1],Xt[0]:Xt[1],...] = image

        # Save the image
        bw.max_workers = ProcessManager._active_threads
        bw[y_min:y_max,x_min:x_max,z:z+1,0,0] = template
Exemple #9
0
def _get_higher_res(S: int,
                    slide_writer: PyramidWriter,
                    X: typing.Tuple[int,int] = None,
                    Y: typing.Tuple[int,int] = None,
                    Z: typing.Tuple[int,int] = (0,1)):
    """ Recursive function for pyramid building
    
    This is a recursive function that builds an image pyramid by indicating
    an original region of an image at a given scale. This function then
    builds a pyramid up from the highest resolution components of the pyramid
    (the original images) to the given position resolution.
    
    As an example, imagine the following possible pyramid:
    
    Scale S=0                     1234
                                 /    \
    Scale S=1                  12      34
                              /  \    /  \
    Scale S=2                1    2  3    4
    
    At scale 2 (the highest resolution) there are 4 original images. At scale 1,
    images are averaged and concatenated into one image (i.e. image 12). Calling
    this function using S=0 will attempt to generate 1234 by calling this
    function again to get image 12, which will then call this function again to
    get image 1 and then image 2. Note that this function actually builds images
    in quadrants (top left and right, bottom left and right) rather than two
    sections as displayed above.
    
    Due to the nature of how this function works, it is possible to build a
    pyramid in parallel, since building the subpyramid under image 12 can be run
    independently of the building of subpyramid under 34.
    
    Args:
        S: Top level scale from which the pyramid will be built
        file_path: Path to image
        slide_writer: object used to encode and write pyramid tiles
        X: Range of X values [min,max] to get at the indicated scale
        Y: Range of Y values [min,max] to get at the indicated scale
    Returns:
        image: The image corresponding to the X,Y values at scale S
    """
    
    # Get the scale info
    scale_info = slide_writer.scale_info(S)
    
    if X == None:
        X = [0,scale_info['size'][0]]
    if Y == None:
        Y = [0,scale_info['size'][1]]
    
    # Modify upper bound to stay within resolution dimensions
    if X[1] > scale_info['size'][0]:
        X[1] = scale_info['size'][0]
    if Y[1] > scale_info['size'][1]:
        Y[1] = scale_info['size'][1]
    
    if str(S)==slide_writer.scale_info(-1)['key']:
        with ProcessManager.thread():
        
            with bfio.BioReader(slide_writer.image_path,max_workers=1) as br:
            
                image = br[Y[0]:Y[1],X[0]:X[1],Z[0]:Z[1],...].squeeze()

            # Write the chunk
            slide_writer.store_chunk(image,str(S),(X[0],X[1],Y[0],Y[1]))
        
        return image

    else:
        # Initialize the output
        image = np.zeros((Y[1]-Y[0],X[1]-X[0]),dtype=slide_writer.dtype)
        
        # Set the subgrid dimensions
        subgrid_dims = [[2*X[0],2*X[1]],[2*Y[0],2*Y[1]]]
        for dim in subgrid_dims:
            while dim[1]-dim[0] > CHUNK_SIZE:
                dim.insert(1,dim[0] + ((dim[1] - dim[0]-1)//CHUNK_SIZE) * CHUNK_SIZE)

        def load_and_scale(*args,**kwargs):
            sub_image = _get_higher_res(**kwargs)

            with ProcessManager.thread():
                image = args[0]
                x_ind = args[1]
                y_ind = args[2]
                image[y_ind[0]:y_ind[1],x_ind[0]:x_ind[1]] = kwargs['slide_writer'].scale(sub_image)
        
        with ThreadPoolExecutor(1) as executor:
            for y in range(0,len(subgrid_dims[1])-1):
                y_ind = [subgrid_dims[1][y] - subgrid_dims[1][0],subgrid_dims[1][y+1] - subgrid_dims[1][0]]
                y_ind = [np.ceil(yi/2).astype('int') for yi in y_ind]
                for x in range(0,len(subgrid_dims[0])-1):
                    x_ind = [subgrid_dims[0][x] - subgrid_dims[0][0],subgrid_dims[0][x+1] - subgrid_dims[0][0]]
                    x_ind = [np.ceil(xi/2).astype('int') for xi in x_ind]
                    executor.submit(load_and_scale,
                                    image,x_ind,y_ind,           # args
                                    X=subgrid_dims[0][x:x+2],    # kwargs
                                    Y=subgrid_dims[1][y:y+2],
                                    Z=Z,
                                    S=S+1,
                                    slide_writer=slide_writer)
    
    # Write the chunk
    slide_writer.store_chunk(image,str(S),(X[0],X[1],Y[0],Y[1]))
    return image