From c9e437f8748c720a0126d44e299360d2975a3f96 Mon Sep 17 00:00:00 2001 From: Joost de Folter Date: Thu, 5 Sep 2024 17:35:48 +0200 Subject: [PATCH] Fixes to Tiff tag metadata, handle multi tiff files --- OmeSliCC/OmeSource.py | 5 ++-- OmeSliCC/TiffSource.py | 66 +++++++++++++++++++++++++----------------- OmeSliCC/conversion.py | 7 +++-- OmeSliCC/image_util.py | 2 +- OmeSliCC/util.py | 3 +- 5 files changed, 51 insertions(+), 32 deletions(-) diff --git a/OmeSliCC/OmeSource.py b/OmeSliCC/OmeSource.py index a273e7b..2fa43cf 100644 --- a/OmeSliCC/OmeSource.py +++ b/OmeSliCC/OmeSource.py @@ -243,10 +243,11 @@ def get_channel_window(self, channeli): dtype = self.get_pixel_type() if dtype.kind == 'f': - info = np.finfo(dtype) + # info = np.finfo(dtype) + start, end = 0, 1 else: info = np.iinfo(dtype) - start, end = info.min, info.max + start, end = info.min, info.max nsizes = len(self.sizes) if nsizes > 1: diff --git a/OmeSliCC/TiffSource.py b/OmeSliCC/TiffSource.py index 4c0a857..5d88abc 100644 --- a/OmeSliCC/TiffSource.py +++ b/OmeSliCC/TiffSource.py @@ -51,10 +51,32 @@ def __init__(self, self.first_page = tiff.pages.first if tiff.is_ome and tiff.ome_metadata is not None: xml_metadata = tiff.ome_metadata - self.metadata = XmlDict.xml2dict(xml_metadata) + self.metadata = tifffile.xml2dict(xml_metadata) if 'OME' in self.metadata: self.metadata = self.metadata['OME'] self.has_ome_metadata = True + if 'BinaryOnly' in self.metadata: + # binary image only; get metadata from metadata file instead + self.has_ome_metadata = False + metdata_filename = os.path.join(os.path.dirname(filename), + self.metadata['BinaryOnly'].get('MetadataFile')) + if os.path.isfile(metdata_filename): + metdata_tiff = TiffFile(metdata_filename) + if metdata_tiff.is_ome and metdata_tiff.ome_metadata is not None: + xml_metadata = metdata_tiff.ome_metadata + self.metadata = tifffile.xml2dict(xml_metadata) + if 'OME' in self.metadata: + self.metadata = self.metadata['OME'] + images = self.metadata.get('Image') + if isinstance(images, list): + for image in images: + if image.get('Name', '').lower() == get_filetitle(filename).lower(): + self.metadata['Image'] = image + break + self.has_ome_metadata = True + + if self.has_ome_metadata: + pass elif tiff.is_imagej: self.metadata = tiff.imagej_metadata elif self.first_page.description: @@ -72,12 +94,13 @@ def __init__(self, photometric = series0.keyframe.photometric self.pages = get_tiff_pages(tiff) for page0 in self.pages: - npages = len(page0) - self.npages = npages if isinstance(page0, list): page = page0[0] + npages = len(page0) else: page = page0 + npages = 1 + self.npages = npages if not self.dimension_order: self.dimension_order = page.axes photometric = page.photometric @@ -98,16 +121,8 @@ def __init__(self, self.depth = shape[2] depth *= self.depth bitspersample = page.dtype.itemsize * 8 - if tiff.is_ome: - images = self.metadata.get('Image', {}) - image = images - if isinstance(images, list): - for image in images: - name = image.get('Name', '') - if name in filename: - break - - pixels = image.get('Pixels', {}) + if self.has_ome_metadata: + pixels = ensure_list(self.metadata.get('Image', {}))[0].get('Pixels', {}) depth = int(pixels.get('SizeZ', depth)) nchannels = int(pixels.get('SizeC', nchannels)) nt = int(pixels.get('SizeT', nt)) @@ -128,9 +143,8 @@ def __init__(self, def _find_metadata(self): pixel_size = [] - page = self.first_page # from OME metadata - if page.is_ome: + if self.has_ome_metadata: self._get_ome_metadata() return @@ -139,10 +153,11 @@ def _find_metadata(self): pixel_size_unit = self.metadata.get('unit', '').encode().decode('unicode_escape') if pixel_size_unit == 'micron': pixel_size_unit = self.default_physical_unit - for scale in self.metadata.get('scales', '').split(','): - scale = scale.strip() - if scale != '': - pixel_size.append((float(scale), pixel_size_unit)) + if 'scales' in self.metadata: + for scale in self.metadata['scales'].split(','): + scale = scale.strip() + if scale != '': + pixel_size.append((float(scale), pixel_size_unit)) if len(pixel_size) == 0 and self.metadata is not None and 'spacing' in self.metadata: pixel_size_z = (self.metadata['spacing'], pixel_size_unit) # from description @@ -156,13 +171,12 @@ def _find_metadata(self): pixel_size.append((self.metadata['MPP'], self.default_physical_unit)) # from page TAGS if len(pixel_size) < 2: - if pixel_size_unit == '': - pixel_size_unit = self.tags.get('ResolutionUnit', '') - if isinstance(pixel_size_unit, Enum): - pixel_size_unit = pixel_size_unit.name - pixel_size_unit = pixel_size_unit.lower() - if pixel_size_unit == 'none': - pixel_size_unit = '' + pixel_size_unit = self.tags.get('ResolutionUnit', '') + if isinstance(pixel_size_unit, Enum): + pixel_size_unit = pixel_size_unit.name + pixel_size_unit = pixel_size_unit.lower() + if pixel_size_unit == 'none': + pixel_size_unit = '' res0 = convert_rational_value(self.tags.get('XResolution')) if res0 is not None and res0 != 0: pixel_size.append((1 / res0, pixel_size_unit)) diff --git a/OmeSliCC/conversion.py b/OmeSliCC/conversion.py index 3a0b331..c5bbb3b 100644 --- a/OmeSliCC/conversion.py +++ b/OmeSliCC/conversion.py @@ -33,8 +33,11 @@ def create_source(source_ref: str, params: dict, omero=None) -> OmeSource: elif ext in Image.registered_extensions().keys(): source = PlainImageSource(source_ref, source_pixel_size=source_pixel_size, target_pixel_size=target_pixel_size) else: - from OmeSliCC.BioSource import BioSource - source = BioSource(source_ref, source_pixel_size=source_pixel_size, target_pixel_size=target_pixel_size) + try: + from OmeSliCC.BioSource import BioSource + source = BioSource(source_ref, source_pixel_size=source_pixel_size, target_pixel_size=target_pixel_size) + except ImportError: + raise NotImplementedError('Unsupported: Bioformats not installed') return source diff --git a/OmeSliCC/image_util.py b/OmeSliCC/image_util.py index 1a2daf8..a396cf4 100644 --- a/OmeSliCC/image_util.py +++ b/OmeSliCC/image_util.py @@ -322,7 +322,7 @@ def create_compression_codecs(compression: list) -> list: def get_tiff_pages(tiff: TiffFile) -> list: pages = [] found = False - if tiff.series: + if tiff.series and not tiff.is_mmstack: # has series baseline = tiff.series[0] for level in baseline.levels: diff --git a/OmeSliCC/util.py b/OmeSliCC/util.py index 6dc4f28..fb21582 100644 --- a/OmeSliCC/util.py +++ b/OmeSliCC/util.py @@ -134,7 +134,8 @@ def round_significants(a: float, significant_digits: int) -> float: def get_filetitle(filename: str) -> str: filebase = os.path.basename(filename) - return os.path.splitext(filebase)[0] + title = os.path.splitext(filebase)[0].rstrip('.ome') + return title def split_num_text(text: str) -> list: