def to_ometiff(self, channel_clips, sample, json_file):
        channel_data = {}
        channels = []
        images = []
        ometif_path = '{}.ome.tif'.format(json_file.name.replace('.json', ''))
        s3_target = open('s3_target.txt').read().strip()
        for (channel, clip) in channel_clips:
            channel_data[channel] = {
                'sample':
                sample,
                'tileSource':
                'https://s3.amazonaws.com/{}/linnarsson/'.format(s3_target) +
                'linnarsson.tiles/linnarsson.images.{}/'.format(channel) +
                '{}.dzi'.format(channel)
            }

            channels.append(channel)
            array = self.scale_sample(channel=channel,
                                      sample=sample,
                                      max_allowed=256,
                                      clip=float(clip)).astype(np.uint8)

            images.append(array)

        json.dump(channel_data, json_file, indent=2)

        image = np.transpose(np.dstack(tuple(images)))
        image = np.expand_dims(image, axis=0)
        image = np.expand_dims(image, axis=0)

        channels = [tup[0] for tup in channel_clips]
        omexml = self.get_omexml(pixel_array=image,
                                 channels=channels,
                                 name='linnarsson',
                                 pixel_type='uint8')

        io.write_ometiff(ometif_path, image, str(omexml))
import numpy as np

from pathlib import Path
import datetime


def create_omexml(image_array, channel_names):
    metadata = omexmlClass.OMEXML()
    image = metadata.image()
    image.AcquisitionDate = datetime.datetime.now().isoformat()

    pixels = image.Pixels
    pixels.SizeX = image_array.shape[2]
    pixels.SizeY = image_array.shape[1]
    pixels.SizeC = image_array.shape[0]
    pixels.PixelType = str(image_array.dtype)

    pixels.channel_count = len(channel_names)
    for i, name in enumerate(channel_names):
        pixels.Channel(i).Name = name

    return f'<?xml version="1.0" encoding="UTF-8"?>\n{metadata}'


if __name__ == "__main__":
    arr = np.arange(3 * 50 * 50).reshape((3, 50, 50))
    outfile = "dataset.ome.tif"
    channel_names = ["0", "1", "2"]
    omexml_string = create_omexml(arr, channel_names)
    io.write_ometiff(outfile, arr, omexml_string)
示例#3
0
def execute(filepath,
            separator=';',
            filter_method='none',
            filter_size=3,
            threshold_method='triangle',
            min_objectsize=1000,
            max_holesize=100,
            saveformat='ome.tiff'):
    """Main function that executed the workflow.

    :param filepath: file path of the CZI image
    :type filepath: tsr
    :param separator: sepeartor for the CSV table, defaults to ';'
    :type separator: str, optional
    :param filter_method: smoothing filer, defaults to 'none'
    :type filter_method: str, optional
    :param filter_size: kernel size or radius of filter element, defaults to 3
    :type filter_size: int, optional
    :param threshold_method: threshold method, defaults to 'triangle'
    :type threshold_method: str, optional
    :param min_objectsize: minimum object size, defaults to 1000
    :type min_objectsize: int, optional
    :param max_holesize: maximum object size, defaults to 100
    :type max_holesize: int, optional
    :param saveformat: format to save the segmented image, defaults to 'ome.tiff'
    :type saveformat: str, optional
    :return: outputs
    :rtype: dict
    """

    print('--------------------------------------------------')
    print('FilePath : ', filepath)
    print(os.getcwd())
    print('File exists : ', os.path.exists(filepath))
    print('--------------------------------------------------')

    # define name for figure to be saved
    filename = os.path.basename(filepath)

    # get the metadata from the czi file
    md, additional_mdczi = imf.get_metadata(filepath)

    # to make it more readable extravt values from metadata dictionary
    stageX = md['SceneStageCenterX']
    stageY = md['SceneStageCenterY']

    # define columns names for dataframe
    cols = ['S', 'T', 'Z', 'C', 'Number']
    objects = pd.DataFrame(columns=cols)

    # optional dipslay of "some" results - empty list = no display
    show_image = [0]

    # scalefactor to read CZI
    sf = 1.0

    # index for channel - currently only single channel images are supported !
    chindex = 0

    # define maximum object sizes
    max_objectsize = 1000000000

    # define save format for mask
    adapt_dtype_mask = True
    dtype_mask = np.int8

    # check if it makes sense
    if max_holesize > min_objectsize:
        min_objectsize = max_holesize

    # read the czi mosaic image
    czi = CziFile(filepath)

    # get the shape of the data using aicspylibczi
    print('Dimensions   : ', czi.dims)
    print('Size         : ', czi.size)
    print('Shape        : ', czi.dims_shape())
    print('IsMosaic     : ', czi.is_mosaic())

    # read the mosaic pixel data
    mosaic = czi.read_mosaic(C=0, scale_factor=sf)
    print('Mosaic Shape :', mosaic.shape)

    # get the mosaic as NumPy.Array - must fit im memory !!!
    image2d = np.squeeze(mosaic, axis=0)
    md['SizeX_readmosaic'] = image2d.shape[1]
    md['SizeY_readmosaic'] = image2d.shape[0]

    # create the savename for the OME-TIFF
    if saveformat == 'ome.tiff':
        savename_seg = filename.split('.')[0] + '.ome.tiff'
    if saveformat == 'tiff':
        savename_seg = filename.split('.')[0] + '.tiff'

    # initialize empty dataframe
    results = pd.DataFrame()

    # main loop over all T - Z - C slices
    for s in progressbar.progressbar(range(md['SizeS']), redirect_stdout=True):
        for t in range(md['SizeT']):
            for z in range(md['SizeZ']):

                values = {'S': s, 'T': t, 'Z': z, 'C': chindex, 'Number': 0}

        # preprocessing - filter the image
        if filter_method == 'none' or filter_method == 'None':
            image2d_filtered = image2d
        if filter_method == 'median':
            image2d_filtered = median(image2d, selem=disk(filter_size))
        if filter_method == 'gauss':
            image2d_filtered = gaussian(image2d,
                                        sigma=filter_size,
                                        mode='reflect')

        # threshold image
        binary = sgt.autoThresholding(image2d_filtered,
                                      method=threshold_method)

        # Remove contiguous holes smaller than the specified size
        mask = morphology.remove_small_holes(binary,
                                             area_threshold=max_holesize,
                                             connectivity=1,
                                             in_place=True)

        # remove small objects
        mask = morphology.remove_small_objects(mask,
                                               min_size=min_objectsize,
                                               in_place=True)

        # clear the border
        mask = segmentation.clear_border(mask, bgval=0, in_place=True)

        # label the objects
        mask = measure.label(binary)

        # adapt pixel type of mask
        if adapt_dtype_mask:
            mask = mask.astype(dtype_mask, copy=False)

        # measure region properties
        to_measure = ('label', 'area', 'centroid', 'bbox')

        # measure the specified parameters store in dataframe
        props = pd.DataFrame(
            measure.regionprops_table(
                mask, intensity_image=image2d,
                properties=to_measure)).set_index('label')

        # filter objects by size
        props = props[(props['area'] >= min_objectsize)
                      & (props['area'] <= max_objectsize)]

        # add well information for CZI metadata
        try:
            props['WellId'] = md['Well_ArrayNames'][s]
            props['Well_ColId'] = md['Well_ColId'][s]
            props['Well_RowId'] = md['Well_RowId'][s]
        except (IndexError, KeyError) as error:
            # Output expected ImportErrors.
            print('Key not found:', error)
            print('Well Information not found. Using S-Index.')
            props['WellId'] = s
            props['Well_ColId'] = s
            props['Well_RowId'] = s

        # add plane indices
        props['S'] = s
        props['T'] = t
        props['Z'] = z
        props['C'] = chindex

        # count the number of objects
        values['Number'] = props.shape[0]

        # update dataframe containing the number of objects
        objects = objects.append(pd.DataFrame(values, index=[0]),
                                 ignore_index=True)
        results = results.append(props, ignore_index=True)

    # make sure the array as 5D of order (T, Z, C, X, Y) to write an correct OME-TIFF
    mask = imf.expand_dims5d(mask, md)

    # write the OME-TIFF suing apeer-ometiff-library
    io.write_ometiff(savename_seg, mask, omexml_string=None)

    # rename columns in pandas datatable
    results.rename(columns={
        'bbox-0': 'ystart',
        'bbox-1': 'xstart',
        'bbox-2': 'yend',
        'bbox-3': 'xend'
    },
                   inplace=True)

    # calculate the bbox width in height in [pixel] and [micron]
    results['bbox_width'] = results['xend'] - results['xstart']
    results['bbox_height'] = results['yend'] - results['ystart']
    results['bbox_width_scaled'] = results['bbox_width'] * md['XScale']
    results['bbox_height_scaled'] = results['bbox_height'] * md['XScale']

    # calculate the bbox center StageXY
    results['bbox_center_stageX'], results[
        'bbox_center_stageY'] = bbox2stageXY(
            image_stageX=stageX,
            image_stageY=stageY,
            sizeX=md['SizeX'],
            sizeY=md['SizeY'],
            scale=md['XScale'],
            xstart=results['xstart'],
            ystart=results['ystart'],
            bbox_width=results['bbox_width'],
            bbox_height=results['bbox_height'])

    # show results
    print(results)
    print('Done.')

    # write the CSV data table
    print('Write to CSV File : ', filename)
    csvfile = os.path.splitext(filename)[0] + '_planetable.csv'
    results.to_csv(csvfile, sep=separator, index=False)

    # set the outputs
    outputs = {}
    outputs['segmented_image'] = savename_seg
    outputs['objects_table'] = csvfile

    return outputs
示例#4
0
                             ignore_index=True)
    results = results.append(props, ignore_index=True)

    image_counter += 1
    # optional display of results
    if image_counter - 1 in show_image:
        print('Well:', props['WellId'].iloc[0], 'Index S-C:', s, chindex,
              'Objects:', values['Number'])

        ax = vst.plot_segresults(image2d, mask, props, add_bbox=True)

# make sure the array as 5D of order (T, Z, C, X, Y) to write an correct OME-TIFF
mask = imf.expand_dims5d(mask, md)

# write the OME-TIFF suing apeer-ometiff-library
io.write_ometiff(savename, mask, omexml_string=None)

# rename columns in pandas datatable
results.rename(columns={
    'bbox-0': 'ystart',
    'bbox-1': 'xstart',
    'bbox-2': 'yend',
    'bbox-3': 'xend'
},
               inplace=True)

# calculate the bbox width in height in [pixel] and [micron]
results['bbox_width'] = results['xend'] - results['xstart']
results['bbox_height'] = results['yend'] - results['ystart']
results['bbox_width_scaled'] = results['bbox_width'] * md['XScale']
results['bbox_height_scaled'] = results['bbox_height'] * md['XScale']