Source code for sdt.io.tiff

# SPDX-FileCopyrightText: 2020 Lukas Schrangl <lukas.schrangl@tuwien.ac.at>
#
# SPDX-License-Identifier: BSD-3-Clause

"""High level TIFF I/O"""
import collections
import contextlib
import itertools
import logging
from pathlib import Path
from typing import Iterable, List, Mapping, Union

import numpy as np
import tifffile

with contextlib.suppress(ImportError):
    from . import yaml


_logger = logging.getLogger(__name__)


redundant_tiff_metadata: List = [
    "compression",
    "frame_no",
    "is_fluoview",
    "is_imagej",
    "is_micromanager",
    "is_mdgel",
    "is_mediacy",
    "is_nih",
    "is_ome",
    "is_reduced",
    "is_shaped",
    "is_stk",
    "is_tiled",
    "predictor",
    "resolution",
    "resolution_unit",
]
"""Metadata that should not be saved in the image description since it is
actually stored elsewhere.
"""


[docs] def save_as_tiff( filename: Union[str, Path], frames: Iterable[np.ndarray], metadata: Union[None, Iterable[Mapping], Mapping] = None, contiguous: bool = True, ): """Write a sequence of images to a TIFF stack If the items in `frames` contain a dict named `metadata`, an attempt to serialize it to YAML and save it as the TIFF file's ImageDescription tags. Parameters ---------- filename Name of the output file frames Frames to be written to TIFF file. metadata: Metadata to be written. If a single dict, save with the first frame. If an iterable, save each entry with the corresponding frame. contiguous Whether to write to the TIFF file contiguously or not. This has implications when reading the data. If using `PIMS`, set to `True`. Setting to `False` allows for per-image metadata. """ if metadata is None: metadata = [] elif isinstance(metadata, collections.abc.Mapping): metadata = [metadata] with tifffile.TiffWriter(filename) as tw: for f, md in zip(frames, itertools.chain(metadata, itertools.repeat({}))): desc = None dt = None if not md: # PIMS and old imageio added metadata to frames for k in "meta", "metadata": with contextlib.suppress( AttributeError, # no metadata TypeError, ValueError, # dict() fail ): md = dict(getattr(f, k)) break if md: for k in "datetime", "DateTime": with contextlib.suppress(KeyError): dt = md.pop(k) break # Remove redundant metadata for k in redundant_tiff_metadata: md.pop(k, None) if md: # Try serializing remaining metadata to YAML try: desc = yaml.safe_dump(md) except Exception: _logger.error(f"{filename}: Failed to serialize metadata to YAML") tw.write( f, software="sdt.io", description=desc, datetime=dt, contiguous=contiguous, )