示例#1
0
 def save(self, tile_indices, output_dir, tile):
     # Overwrite the original preprocessed tile with corrected version
     path = cytokit_io.get_processor_img_path(tile_indices.region_index,
                                              tile_indices.tile_x,
                                              tile_indices.tile_y)
     cytokit_io.save_tile(osp.join(output_dir, path),
                          tile,
                          config=self.config)
     return path
示例#2
0
def postprocess_tile(tile, tile_indices, ops, log_fn, task_config):
    output_dir = task_config.output_dir

    # Illumination Correction
    if ops.illumination_op:
        # Prepare and save illumination images, if not already done
        ops.illumination_op.prepare_region_data(output_dir)
        path = ops.illumination_op.save_region_data(output_dir)
        if path is not None:
            log_fn('Illumination data saved to "{}"'.format(path))

        # Run correction for tile
        tile = ops.illumination_op.run(tile, tile_indices)
        log_fn('Illumination correction complete', tile)
    else:
        log_fn('Skipping illumination correction', debug=True)

    # Spectral Unmixing
    if ops.unmixing_op:
        # Prepare unmixing models for each region
        ops.unmixing_op.prepare_region_data(output_dir)

        # Run correction for tile
        tile = ops.unmixing_op.run(tile, tile_indices)
        log_fn('Spectral unmixing complete', tile)
    else:
        log_fn('Skipping spectral unmixing', debug=True)

    # Get best focus data
    # TODO Prevent needing to re-read the processor data file each time
    best_focus_data = function_data.get_best_focus_coord_map(output_dir)
    best_focus_z_plane = best_focus_data[(tile_indices.region_index,
                                          tile_indices.tile_x,
                                          tile_indices.tile_y)]

    # Rerun cytometry based on corrected tile
    tile, cyto_data = ops.cytometry_op.run(
        tile, best_focus_z_plane=best_focus_z_plane)
    paths = ops.cytometry_op.save(tile_indices, output_dir, cyto_data)
    log_fn(
        'Postprocessing cytometry complete; Statistics saved to "{}"'.format(
            paths[-1]), cyto_data[0])

    # Save resulting tile
    path = cytokit_io.get_processor_img_path(tile_indices.region_index,
                                             tile_indices.tile_x,
                                             tile_indices.tile_y)
    cytokit_io.save_tile(osp.join(output_dir, path),
                         tile,
                         config=task_config.exp_config)
    log_fn('Saved postprocessed tile to "{}"'.format(path), tile)
示例#3
0
def preprocess_tile(tile, tile_indices, ops, log_fn, task_config):
    output_dir = task_config.output_dir

    # Drift Compensation
    if ops.align_op:
        tile = ops.align_op.run(tile)
        log_fn('Drift compensation complete', tile)
    else:
        log_fn('Skipping drift compensation', debug=True)

    # Crop off overlap in imaging process
    if ops.crop_op:
        tile = ops.crop_op.run(tile)
        log_fn('Tile overlap crop complete', tile)
    else:
        log_fn('Skipping tile crop', debug=True)

    # Resample images for improved downstream speed
    if ops.resize_op:
        tile = ops.resize_op.run(tile)
        log_fn('Tile resize complete', tile)
    else:
        log_fn('Skipping tile resize', debug=True)

    # Best Focal Plane Selection
    best_focus_data = None
    if ops.focus_op:
        # Used the cropped, but un-deconvolved tile for focal plane selection
        best_focus_data = ops.focus_op.run(tile)
        ops.focus_op.save(tile_indices, output_dir, best_focus_data)
        log_fn('Focal plane selection complete', best_focus_data[0])
    else:
        log_fn('Skipping focal plane selection', debug=True)

    # Deconvolution
    if ops.decon_op:
        tile = ops.decon_op.run(tile)
        log_fn('Deconvolution complete', tile)
    else:
        log_fn('Skipping deconvolution', debug=True)

    # Cytometry (segmentation + quantification)
    if ops.cytometry_op:
        best_focus_z_plane = best_focus_data[1] if best_focus_data else None
        tile, cyto_data = ops.cytometry_op.run(
            tile,
            best_focus_z_plane=best_focus_z_plane,
            tile_indices=tile_indices)
        paths = ops.cytometry_op.save(tile_indices, output_dir, cyto_data)
        log_fn(
            'Tile cytometry complete; Statistics saved to "{}"'.format(
                paths[-1]), cyto_data[0])
    else:
        log_fn('Skipping tile cytometry', debug=True)

    # Tile summary statistic operations
    if ops.summary_op:
        ops.summary_op.run(tile)
        log_fn('Tile statistic summary complete')
    else:
        log_fn('Skipping tile statistic summary', debug=True)

    # Save the output tile if tile generation/assembly was enabled
    if task_config.op_flags.run_tile_generator:
        path = cytokit_io.get_processor_img_path(tile_indices.region_index,
                                                 tile_indices.tile_x,
                                                 tile_indices.tile_y)
        cytokit_io.save_tile(osp.join(output_dir, path),
                             tile,
                             config=task_config.exp_config)
        log_fn('Saved preprocessed tile to path "{}"'.format(path), tile)
示例#4
0
def get_tile_montage(config, image_dir, hyperstack, icyc=0, iz=0, ich=0, ireg=0, bw=0, bv_fn=None, allow_missing=False,
                     imread_fn=None):
    """Generate a montage image for a specific cycle, z-plane, channel, and region

    This function supports both raw, flattened 2D images as well as consolidated, 5D
    hyperstacks (as determined by `hyperstack` argument)
    Args:
        config: Experiment configuration
        image_dir: Location of tiled images; These should include all z-planes, cycles, and channels in
            individual tif files (e.g. the output of the pre-processing or segmentation pipelines)
        hyperstack: Flag indicating whether or not images are 5D hyperstacks or flattened 2D images:
            - Hyperstacks are typically results from any sort of processing or segmentation step
            - Flattened 2D images are typically raw files generated directly from a microscope
        icyc: 0-based cycle index
        iz: 0-based z-plane index
        ich: 0-based channel index
        ireg: 0-based region index
        bw: Border width (in pixels) to add to each tile in the montage image, which useful for determining
            tile location within the montage; If <= 0, this parameter will do nothing
        bv_fn: Border value function with signature `fn(tile_x, tile_y) --> float`; if not given all
            border values are assigned a value of 0
        allow_missing: Flag indicating whether or not to allow missing tiles into the montage; defaults
            to false and is generally only useful when debugging missing data
        imread_fn: When not using 5D hyperstacks (i.e. reading raw image files) this can be useful for cases when,
            for example, raw, single-channel files are actually 3 channel files with the first two channels blank
            (this happens w/ Keyence somehow).  This function will take an image path and must return a single 2D
            image with shape (rows, cols)
    Returns:
        A (usually very large) 2D array containing all tiles stitched together
    """
    tile_indexes = list(range(config.n_tiles_per_region))
    tw, th = config.tile_width, config.tile_height
    tiles = []
    for itile in tile_indexes:
        tx, ty = config.get_tile_coordinates(itile)

        # If operating on a hyperstack, extract the appropriate slice to add to the montage
        if hyperstack:
            path = cytokit_io.get_processor_img_path(ireg, tx, ty)
            path = osp.join(image_dir, path)
            if not osp.exists(path) and allow_missing:
                tile = np.zeros((th, tw))
            else:
                tile = cytokit_io.read_tile(path)
            tile = tile[icyc, iz, ich, :, :]
        # Otherwise, assume raw acquisition files are to be loaded and then cropped before being added
        else:
            path = cytokit_io.get_raw_img_path(ireg, itile, icyc, ich, iz)
            path = osp.join(image_dir, path)
            if not osp.exists(path) and allow_missing:
                tile = np.zeros((th, tw))
            else:
                tile = cytokit_io.read_image(path) if imread_fn is None else imread_fn(path)
                if tile.ndim != 2:
                    raise ValueError(
                        'Expecting 2D image at path "{}" but shape found is {}.  Consider using the '
                        '`imread_fn` argument to specify a custom function to open files or if already using it, '
                        'make sure that results are 2D'
                        .format(path, tile.shape)
                    )
                tile = tile_crop.apply_slice(tile, tile_crop.get_slice(config))
        
        # Highlight borders, if configured to do so
        if bw > 0:
            bv = 0 if bv_fn is None else bv_fn(tx, ty)
            tile[0:bw, :] = bv
            tile[-bw:, :] = bv
            tile[:, 0:bw] = bv
            tile[:, -bw:] = bv
        
        # Add to montage
        tiles.append(tile)

    return core.montage(tiles, config)