예제 #1
0
    def get_omexml(self, pixel_array, channels, name, pixel_type):
        omexml = omexmlClass.OMEXML()
        image = omexml.image()
        image.Name = name
        image.AcquisitionDate = datetime.datetime.now().isoformat()

        pixels = image.Pixels
        pixels.SizeX = pixel_array.shape[4]
        pixels.SizeY = pixel_array.shape[3]
        pixels.SizeC = pixel_array.shape[2]
        pixels.SizeZ = pixel_array.shape[1]
        pixels.SizeT = pixel_array.shape[0]
        pixels.PixelType = pixel_type

        channel_count = len(channels)
        pixels.channel_count = channel_count
        for i in range(channel_count):
            pixels.Channel(i).ID = "Channel:0:{}".format(i)
            pixels.Channel(i).Name = channels[i]

        root = et.XML(str(omexml))
        ome = "{http://www.openmicroscopy.org/Schemas/OME/2016-06}"
        pixels_elem = root.find("{}Image/{}Pixels".format(ome, ome))

        # Repeat for-loop because XML parsing must have channel adjustments
        for i in range(channel_count):
            et.SubElement(pixels_elem,
                          '{}TiffData'.format(ome),
                          FirstC=str(i),
                          FirstT="0",
                          FirstZ="0",
                          IFD="0",
                          PlaneCount="1")

        return omexmlClass.OMEXML(et.tostring(root))
예제 #2
0
def readOmeTiff(input_path):
    with tifffile.TiffFile(input_path) as tif:
        array = tif.asarray()
        omexmlString = tif[0].image_description.decode("utf-8")

    # Turn Ome XML String to an Bioformats object for parsing
    metadata = omexmlClass.OMEXML(omexmlString)

    # Parse pixel sizes
    pixels = metadata.image(0).Pixels
    SizeC = pixels.SizeC
    SizeT = pixels.SizeT
    SizeZ = pixels.SizeZ
    SizeX = pixels.SizeX
    SizeY = pixels.SizeY
    pixels.DimensionOrder

    # Expand image array to 5D of order (T, Z, C, X, Y)
    if SizeC == 1:
        array = np.expand_dims(array, axis=-3)
    if SizeZ == 1:
        array = np.expand_dims(array, axis=-4)
    if SizeT == 1:
        array = np.expand_dims(array, axis=-5)

    return (array, omexmlString)
예제 #3
0
def read_ometiff(input_path):
    with tifffile.TiffFile(input_path) as tif:
        array = tif.asarray()
        omexml_string = tif[0].image_description.decode("utf-8")

    # Turn Ome XML String to an Bioformats object for parsing
    metadata = omexmlClass.OMEXML(omexml_string)

    # Parse pixel sizes
    pixels = metadata.image(0).Pixels
    size_c = pixels.SizeC
    size_t = pixels.SizeT
    size_z = pixels.SizeZ
    size_x = pixels.SizeX
    size_y = pixels.SizeY

    # Expand image array to 5D of order (T, Z, C, X, Y)
    if size_c == 1:
        array = np.expand_dims(array, axis=-3)
    if size_z == 1:
        array = np.expand_dims(array, axis=-4)
    if size_t == 1:
        array = np.expand_dims(array, axis=-5)

    return array, omexml_string
예제 #4
0
def execute(image_path):

    image_name = os.path.basename(image_path)
    print(image_name)

    with tifffile.TiffFile(image_path) as tif:

        array6D = []
        # Turn Ome XML String to a Bioformats object for parsing
        omexml = tif[0].image_description.decode("utf-8")
        metadata = omexmlClass.OMEXML(omexml)
        # Parse pixel sizes
        size_c = metadata.image(0).Pixels.SizeC
        size_z = metadata.image(0).Pixels.SizeZ
        size_t = metadata.image(0).Pixels.SizeT

        # Read each series, get the 5d array -> process it -> append to array6D
        for i in range(len(tif.series)):
            # Returned value is a 5D array of order (T, Z, C, X, Y)
            array5D = read_serie(tif.series[i], size_c, size_z, size_t)
            # Apply inversion operation
            result5d = apply_2d_transfo_to_serie(_invert, array5D, False)

            array6D.append(result5d)

    # Save the inverted image
    write_ometiff(image_name, array6D, omexml)

    print("INVERTION DONE")

    return {'output_image': image_name}
def update_ome_xml_for_fake_channels(ome_string):
    md = omexmlClass.OMEXML(ome_string)
    pixels = md.image().Pixels

    last_cycle_ind = None
    n_ch_added = 0
    origin_n_ch = pixels.get_channel_count()
    for i in range(origin_n_ch):
        # pixels.remove_channel(i)
        current_name = pixels.Channel(i).get_Name()
        current_cycle_ind = re.search("c0(\d).*", current_name).group(1)
        if not last_cycle_ind:
            last_cycle_ind = current_cycle_ind

        if last_cycle_ind != current_cycle_ind:
            pixels.append_channel(i + n_ch_added, "c0%s" % last_cycle_ind + " anchor")
            n_ch_added += 1

        pixels.Channel(i).set_ID("Channel:0:" + str(i + n_ch_added))

        # for k in pixels.Channel(i).node.attrib:
        # print(k, pixels.Channel(i).node.get(k))
        # print(i, pixels.Channel(i).node.attrib)
        last_cycle_ind = current_cycle_ind
    pixels.append_channel(origin_n_ch + n_ch_added, "c0%s" % last_cycle_ind + " anchor")
    pixels.populate_TiffData()
    return md
def main(args):
    ignore_dapi = True
    with tf.TiffFile(args.ome_tif, "r", is_ome=True) as fh:
        print(fh)
        ome_string = fh.ome_metadata
        shape = fh.pages[0].shape

    updated_md = update_ome_xml_for_fake_channels(ome_string)

    clean_xml = xml_cleanup(updated_md.to_xml())
    meta = ET.tostring(clean_xml, encoding="ascii")
    ch_map = map_old_new_chs(ome_string, omexmlClass.OMEXML(meta))
    # print(ch_map)

    tmp_anchor = np.zeros(shape, dtype=np.uint16)
    new_name = Path(args.ome_tif).stem + "_with_anchors.ome.tif"

    if args.known_anchor:
        known_anchor_cyc = args.known_anchor.split(" ")[0]

    writer = tf.TiffWriter(new_name, bigtiff=True)
    with tf.TiffFile(args.ome_tif, "r", is_ome=True) as fh:
        for i in sorted(ch_map.keys()):
            print(i, ch_map[i])
            old_ind = ch_map[i][1]
            cur_ch_name = ch_map[i][0]
            if old_ind is not None:
                tmp_array = normalize(fh.pages[old_ind].asarray().squeeze(), 98)
                writer.save(tmp_array, photometric="minisblack", description=meta)

                if (
                    cur_ch_name.startswith(known_anchor_cyc)
                    and cur_ch_name != args.known_anchor
                ):
                    continue

                # print(fh.pages[old_ind])
                if ignore_dapi and "DAPI" in cur_ch_name:
                    continue
                print(cur_ch_name + " max projected")
                tmp_anchor = np.max(np.array([tmp_array, tmp_anchor]), axis=0)
                # print(tmp_anchor.shape)
            else:
                print("save anchor, and re-intialize anchor image")
                # print(tmp_anchor.shape)
                writer.save(tmp_anchor, photometric="minisblack", description=meta)

                tmp_anchor = np.zeros(shape, dtype=np.uint16)

    writer.close()
예제 #7
0
def update_xml(omexml,
               Image_ID=None,
               Image_Name=None,
               Image_AcquisitionDate=None,
               DimensionOrder=None,
               dType=None,
               SizeT=None,
               SizeZ=None,
               SizeC=None,
               SizeX=None,
               SizeY=None,
               Channel_ID=None,
               Channel_Name=None,
               Channel_SamplesPerPixel=None):

    metadata = omexmlClass.OMEXML(omexml)

    if Image_ID:
        metadata.image().set_ID(Image_ID)
    if Image_Name:
        metadata.image().set_Name(Image_Name)
    if Image_AcquisitionDate:
        metadata.image().Image.AcquisitionDate = Image_AcquisitionDate

    if DimensionOrder:
        metadata.image().Pixels.DimensionOrder = DimensionOrder
    if dType:
        metadata.image().Pixels.PixelType = dType
    if SizeT:
        metadata.image().Pixels.set_SizeT(SizeT)
    if SizeZ:
        metadata.image().Pixels.set_SizeZ(SizeZ)
    if SizeC:
        metadata.image().Pixels.set_SizeC(SizeC)
    if SizeX:
        metadata.image().Pixels.set_SizeX(SizeX)
    if SizeY:
        metadata.image().Pixels.set_SizeY(SizeY)

    if Channel_ID:
        metadata.image().Channel.ID = Channel_ID
    if Channel_Name:
        metadata.image().Channel.Name = Channel_Name
    if Channel_SamplesPerPixel:
        metadata.image().Channel.SamplesPerPixel = Channel_SamplesPerPixel

    metadata = metadata.to_xml().encode()

    return metadata
예제 #8
0
def update_xml(omexml,
               Image_ID=None,
               Image_Name=None,
               Image_AcquisitionDate=None,
               DimensionOrder=None,
               dType=None,
               SizeT=None,
               SizeZ=None,
               SizeC=None,
               SizeX=None,
               SizeY=None,
               Channel_ID=None,
               Channel_Name=None,
               Channel_SamplesPerPixel=None):

    metadata = omexmlClass.OMEXML(omexml)

    if not Image_ID == None:
        metadata.image(0).Image.ID = Image_ID
    if not Image_Name == None:
        metadata.image(0).Name = Image_Name
    if not Image_AcquisitionDate == None:
        metadata.image(0).Image.AcquisitionDate = Image_AcquisitionDate

    if not DimensionOrder == None:
        metadata.image(0).Pixels.DimensionOrder = DimensionOrder
    if not dType == None:
        metadata.image(0).Pixels.PixelType = dType
    if not SizeT == None:
        metadata.image(0).Pixels.SizeT = SizeT
    if not SizeZ == None:
        metadata.image(0).Pixels.SizeZ = SizeZ
    if not SizeC == None:
        metadata.image(0).Pixels.SizeC = SizeC
    if not SizeX == None:
        metadata.image(0).Pixels.SizeX = SizeX
    if not SizeY == None:
        metadata.image(0).Pixels.SizeY = SizeY

    if not Channel_ID == None:
        metadata.image(0).Channel.ID = Channel_ID
    if not Channel_Name == None:
        metadata.image(0).Channel.Name = Channel_Name
    if not Channel_SamplesPerPixel == None:
        metadata.image(0).Channel.SamplesPerPixel = Channel_SamplesPerPixel

    metadata = metadata.to_xml(encoding='utf-8')
    return metadata.replace("<ome:", "<").replace("</ome:", "</")
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}'
예제 #10
0
def read_ometiff(input_path):
    with tifffile.TiffFile(input_path) as tif:
        array = tif.asarray()
        omexml_string = tif.ome_metadata

    # Turn Ome XML String to an Bioformats object for parsing
    metadata = omexmlClass.OMEXML(omexml_string)

    # Parse pixel sizes
    pixels = metadata.image(0).Pixels
    size_c = pixels.SizeC
    size_t = pixels.SizeT
    size_z = pixels.SizeZ
    size_x = pixels.SizeX
    size_y = pixels.SizeY

    # Expand image array to 5D of order (T, Z, C, X, Y)
    if size_c == 1:
        array = np.expand_dims(array, axis=-3)
    if size_z == 1:
        array = np.expand_dims(array, axis=-4)
    if size_t == 1:
        array = np.expand_dims(array, axis=-5)

    # Makes sure to return the array in (T, Z, C, X, Y) order

    dim_format = pixels.DimensionOrder

    if dim_format == "XYCZT":
        pass
    elif dim_format == "XYZCT":
        array = np.moveaxis(array, 1, 2)
    elif dim_format == "XYCTZ":
        array = np.moveaxis(array, 0, 1)
    elif dim_format == "XYZTC":
        array = np.moveaxis(array, 0, 2)
    elif dim_format == "XYTZC":
        array = np.moveaxis(array, 0, 2)
        array = np.moveaxis(array, 0, 1)
    elif dim_format == "XYTCZ":
        array = np.moveaxis(array, 1, 2)
        array = np.moveaxis(array, 0, 1)
    else:
        print(array.shape)
        raise Exception("Unknow dimension format")

    return array, omexml_string
def map_old_new_chs(ome_string, new_md):
    ori_ch_names = omexmlClass.OMEXML(ome_string).image().Pixels.get_channel_names()
    ori_ch_names_i = {ch: i for i, ch in enumerate(ori_ch_names)}

    pixels = new_md.image().Pixels
    new_i_ch_name = {
        int(pixels.Channel(i).node.get("ID").split(":")[-1]): pixels.Channel(i).Name
        for i in range(pixels.get_channel_count())
    }

    maps = {}
    for i in sorted(new_i_ch_name.keys()):
        ch_name = new_i_ch_name[i]
        if "anchor" not in ch_name:
            maps[i] = (ch_name, ori_ch_names_i[new_i_ch_name[i]])
        else:
            maps[i] = (ch_name, None)
    return maps
예제 #12
0
def gen_xml(array):

    #Dimension order is assumed to be TZCYX
    dim_order = "TZCYX"

    metadata = omexmlClass.OMEXML()
    shape = array.shape
    assert (len(shape) == 5), "Expected array of 5 dimensions"

    metadata.image().set_Name("IMAGE")
    metadata.image().set_ID("0")

    pixels = metadata.image().Pixels
    pixels.ome_uuid = metadata.uuidStr
    pixels.set_ID("0")

    pixels.channel_count = shape[2]

    pixels.set_SizeT(shape[0])
    pixels.set_SizeZ(shape[1])
    pixels.set_SizeC(shape[2])
    pixels.set_SizeY(shape[3])
    pixels.set_SizeX(shape[4])

    pixels.set_DimensionOrder(dim_order[::-1])

    pixels.set_PixelType(omexmlClass.get_pixel_type(array.dtype))

    for i in range(pixels.SizeC):
        pixels.Channel(i).set_ID("Channel:0:" + str(i))
        pixels.Channel(i).set_Name("C:" + str(i))

    for i in range(pixels.SizeC):
        pixels.Channel(i).set_SamplesPerPixel(1)

    pixels.populate_TiffData()

    return metadata.to_xml().encode()
예제 #13
0
    def __getitem__(self, idx):

        img_path = self.img_paths_list[idx]
        image = skimage.io.imread(img_path)

        if self.metadata_path is not None:
            tree = ET.parse(self.metadata_path)
            root = tree.getroot()
            omexml = ET.tostring(root, encoding=None, method="xml")
            omemd = omexmlClass.OMEXML(omexml)

            md = get_metadata_ometiff(img_path, omemd)

        elif self.metadata_path is None:
            # get metadata from image if no metadata file found
            md, additional_mdczi = get_metadata(img_path)

            # FUTURE IMPLEMENTATION if not .ome.tiff or .czi, check if metadata file in folder
            # if md == None:
            #
            #     parent_folder = os.path.dirname(img_path)
            #     for fname in os.listdir(parent_folder):
            #         if fname.endswith('.xml'):
            #             xml_path = os.path.join(parent_folder,fname)
            #             tree = ET.parse(xml_path)
            #             root = tree.getroot()
            #             omexml = ET.tostring(root, encoding=None, method='xml')
            #             omemd = omexmlClass.OMEXML(omexml)
            #             md = get_metadata_ometiff(img_path, omemd)
            #             break

        if md is not None:
            return img_path, image, md

        elif md is None:
            raise ValueError("No metadata found.")
예제 #14
0
def get_metadata_ometiff(filename, series=0):
    """Returns a dictionary with OME-TIFF metadata.

    :param filename: filename of the OME-TIFF image
    :type filename: str
    :param series: Image Series, defaults to 0
    :type series: int, optional
    :return: dictionary with the relevant OME-TIFF metainformation
    :rtype: dict
    """

    with tifffile.TiffFile(filename) as tif:
        try:
            # get OME-XML metadata as string the old way
            omexml_string = tif[0].image_description.decode('utf-8')
        except TypeError as e:
            print(e)
            omexml_string = tif.ome_metadata

    # get the OME-XML using the apeer-ometiff-library
    omemd = omexmlClass.OMEXML(omexml_string)

    # create dictionary for metadata and get OME-XML data
    metadata = create_metadata_dict()

    # get directory and filename etc.
    metadata['Directory'] = os.path.dirname(filename)
    metadata['Filename'] = os.path.basename(filename)
    metadata['Extension'] = 'ome.tiff'
    metadata['ImageType'] = 'ometiff'
    metadata['AcqDate'] = omemd.image(series).AcquisitionDate
    metadata['Name'] = omemd.image(series).Name

    # get image dimensions TZCXY
    metadata['SizeT'] = omemd.image(series).Pixels.SizeT
    metadata['SizeZ'] = omemd.image(series).Pixels.SizeZ
    metadata['SizeC'] = omemd.image(series).Pixels.SizeC
    metadata['SizeX'] = omemd.image(series).Pixels.SizeX
    metadata['SizeY'] = omemd.image(series).Pixels.SizeY

    # get number of image series
    metadata['TotalSeries'] = omemd.get_image_count()
    metadata['Sizes BF'] = [metadata['TotalSeries'],
                            metadata['SizeT'],
                            metadata['SizeZ'],
                            metadata['SizeC'],
                            metadata['SizeY'],
                            metadata['SizeX']]

    # get dimension order
    metadata['DimOrder BF'] = omemd.image(series).Pixels.DimensionOrder

    # reverse the order to reflect later the array shape
    metadata['DimOrder BF Array'] = metadata['DimOrder BF'][::-1]

    # get the scaling
    metadata['XScale'] = omemd.image(series).Pixels.PhysicalSizeX
    metadata['XScale'] = np.round(metadata['XScale'], 3)
    # metadata['XScaleUnit'] = omemd.image(series).Pixels.PhysicalSizeXUnit
    metadata['YScale'] = omemd.image(series).Pixels.PhysicalSizeY
    metadata['YScale'] = np.round(metadata['YScale'], 3)
    # metadata['YScaleUnit'] = omemd.image(series).Pixels.PhysicalSizeYUnit
    metadata['ZScale'] = omemd.image(series).Pixels.PhysicalSizeZ
    metadata['ZScale'] = np.round(metadata['ZScale'], 3)
    # metadata['ZScaleUnit'] = omemd.image(series).Pixels.PhysicalSizeZUnit

    # additional check for faulty z-scaling
    if metadata['ZScale'] == 0.0:
        metadata['ZScale'] = 1.0

    # get all image IDs
    for i in range(omemd.get_image_count()):
        metadata['ImageIDs'].append(i)

    # get information about the instrument and objective
    try:
        metadata['InstrumentID'] = omemd.instrument(series).get_ID()
    except (KeyError, AttributeError) as e:
        print('Key not found:', e)
        metadata['InstrumentID'] = None

    try:
        metadata['DetectorModel'] = omemd.instrument(series).Detector.get_Model()
        metadata['DetectorID'] = omemd.instrument(series).Detector.get_ID()
        metadata['DetectorModel'] = omemd.instrument(series).Detector.get_Type()
    except (KeyError, AttributeError) as e:
        print('Key not found:', e)
        metadata['DetectorModel'] = None
        metadata['DetectorID'] = None
        metadata['DetectorModel'] = None

    try:
        metadata['ObjNA'] = omemd.instrument(series).Objective.get_LensNA()
        metadata['ObjID'] = omemd.instrument(series).Objective.get_ID()
        metadata['ObjMag'] = omemd.instrument(series).Objective.get_NominalMagnification()
    except (KeyError, AttributeError) as e:
        print('Key not found:', e)
        metadata['ObjNA'] = None
        metadata['ObjID'] = None
        metadata['ObjMag'] = None

    # get channel names
    for c in range(metadata['SizeC']):
        metadata['Channels'].append(omemd.image(series).Pixels.Channel(c).Name)

    # add axes and shape information using aicsimageio package
    ometiff_aics = AICSImage(filename)
    metadata['Axes_aics'] = ometiff_aics.dims
    metadata['Shape_aics'] = ometiff_aics.shape
    metadata['SizeX_aics'] = ometiff_aics.size_x
    metadata['SizeY_aics'] = ometiff_aics.size_y
    metadata['SizeC_aics'] = ometiff_aics.size_c
    metadata['SizeZ_aics'] = ometiff_aics.size_t
    metadata['SizeT_aics'] = ometiff_aics.size_t
    metadata['SizeS_aics'] = ometiff_aics.size_s

    # close AICSImage object
    ometiff_aics.close()

    # check for None inside Scaling to avoid issues later one ...
    metadata = checkmdscale_none(metadata,
                                 tocheck=['XScale', 'YScale', 'ZScale'],
                                 replace=[1.0, 1.0, 1.0])

    return metadata