A tiny Python library for writing multi-channel TIFF stacks.

Overview

xtiff

PyPI PyPI - Python Version PyPI - License Codecov GitHub Workflow Status (branch) GitHub issues GitHub pull requests

A tiny Python library for writing multi-channel TIFF stacks.

The aim of this library is to provide an easy way to write multi-channel image stacks for external visualization and analysis. It acts as an interface to the popular tifffile package and supports xarray DataArrays as well as numpy-compatible data structures.

To maximize compatibility with third-party software, the images are written in standard-compliant fashion, with minimal metadata and in TZCYX channel order. In particular, a minimal (but customizable) subset of the OME-TIFF standard is supported, enabling the naming of channels.

Requirements

This package requires Python 3.7 or later.

Python package dependencies are listed in requirements.txt.

Using virtual environments is strongly recommended.

Installation

Install xtiff and its dependencies with:

pip install xtiff

Usage

The package provides the following main function for writing TIFF files:

to_tiff(img, file, image_name=None, image_date=None, channel_names=None, description=None, 
        profile=TiffProfile.OME_TIFF, big_endian=None, big_tiff=None, big_tiff_threshold=4261412864, 
        compression_type=None, compression_level=0, pixel_size=None, pixel_depth=None, 
        interleaved=True, software='xtiff', ome_xml_fun=get_ome_xml, **ome_xml_kwargs)


img: The image to write, as xarray DataArray or numpy-compatible data structure.
    Supported shapes:
    - (y, x),
    - (c, y, x)
    - (z, c, y, x)
    - (t, z, c, y, x)
    - (t, z, c, y, x, s)
    Supported data types:
    - any numpy data type when using TiffProfile.TIFF
    - uint8, uint16, float32 when using TiffProfile.IMAGEJ (uint8 for RGB images)
    - bool, int8, int16, int32, uint8, uint16, uint32, float32, float64 when using TiffProfile.OME_TIFF

file: File target supported by tifffile TiffWriter, e.g. path to file (str, pathlib.Path) or binary stream.

image_name: Image name for OME-TIFF images. If True, the image name is determined using the DataArray name or
    the file name (in that order); if False, the image name is not set. If None, defaults to the behavior for True
    for named DataArrays and when the file path is provided, and to the behavior of False otherwise. Only relevant
    when writing OME-TIFF files, any value other than None or False will raise a warning for other TIFF profiles.

image_date: Date and time of image creation in '%Y:%m:%d %H:%M:%S' format or as datetime object. Defaults to
    the current date and time if None. Note: this does not determine the OME-XML AcquisitionDate element value.

channel_names: A list of channel names. If True, channel names are determined using the DataArray channel
    coordinate; if False, channel names are not set. If None, defaults to the behavior for True for DataArrays when
    writing multi-channel OME-TIFFs, and to the behavior for False otherwise. Only relevant when writing
    multi-channel OME-TIFF files, any value other than None or False will raise a warning for other TIFF profiles.

description: TIFF description tag. Will default to the OME-XML header when writing OME-TIFF files. Any value
    other than None will raise a warning in this case.

profile: TIFF specification of the written file.
    Supported TIFF profiles:
    - TIFF (no restrictions apply)
    - ImageJ (undocumented file format that is supported by the ImageJ software)
    - OME-TIFF (Open Microscopy Environment TIFF standard-compliant file format with minimal OME-XML header)

big_endian: If true, stores data in big endian format, otherwise uses little endian byte order. If None, the
    byte order is set to True for the ImageJ TIFF profile and defaults to the system default otherwise.

big_tiff: If True, enables support for writing files larger than 4GB. Not supported for TiffProfile.IMAGEJ.

big_tiff_threshold: Threshold for enabling BigTIFF support when big_tiff is set to None, in bytes. Defaults
    to 4GB, minus 32MB for metadata.

compression_type: Compression algorithm, see tifffile.TIFF.COMPRESSION() for available values. Compression is
    not supported for TiffProfile.IMAGEJ. Note: Compression prevents from memory-mapping images and should therefore
    be avoided when images are compressed externally, e.g. when they are stored in compressed archives.

compression_level: Compression level, between 0 and 9. Compression is not supported for TiffProfile.IMAGEJ.
    Note: Compression prevents from memory-mapping images and should therefore be avoided when images are compressed
    externally, e.g. when they are stored in compressed archives.

pixel_size: Planar (x/y) size of one pixel, in micrometer.

pixel_depth: Depth (z size) of one pixel, in micrometer. Only relevant when writing OME-TIFF files, any value
    other than None will raise a warning for other TIFF profiles.

interleaved: If True, OME-TIFF images are saved as interleaved (this only affects OME-XML metadata). Always
    True for RGB(A) images (i.e., S=3 or 4) - a warning will be raised if explicitly set to False for RGB(A) images.

software: Name of the software used to create the file. Must be 7-bit ASCII. Saved with the first page only.

ome_xml_fun: Function that will be used for generating the OME-XML header. See the default implementation for
    reference of the required signature. Only relevant when writing OME-TIFF files, ignored otherwise.

ome_xml_kwargs: Optional arguments that are passed to the ome_xml_fun function. Only relevant when writing
    OME-TIFF files, will raise a warning if provided for other TIFF profiles.

In addition, get_ome_xml() is provided as the default OME-XML-generating function.

FAQ

What metadata is included in the written images?

In general, written metadata is kept at a minimum and only information that can be inferred from the raw image data is included (image dimensions, data type, number of channels, channel names for xarrays). Additional metadata natively supported by the tifffile package can be specified using function parameters. For OME-TIFF files, the OME-XML "Description" tag contents can be further refined by specifying custom OME-XML-generating functions.

Why should I care about TIFF? I use Zarr/NetCDF/whatever.

That's good! TIFF is an old and complex file format, has many disadvantages and is impractical for storing large images. However, it also remains one of the most widely used scientific image formats and is (at least partially) supported by many popular tools, such as ImageJ. With xtiff, you can continue to store your images in your favorite file format, while having the opportunity to easily convert them to a format that can be read by (almost) any tool.

Why can't I use the tifffile package directly?

Of course you can! Christoph Gohlke's tifffile package provides a very powerful and feature-complete interface for writing TIFF files and is the backend for xtiff. Essentially, the xtiff package is just a wrapper for tifffile. While you can in principle write any image directly with tifffile, in many cases, the flexibility of the TIFF format can be daunting. The xtiff package reduces the configuration burden and metadata to an essential minimum.

Authors

Created and maintained by Jonas Windhager [email protected]

Contributing

Contributing

Changelog

Changelog

License

MIT

Comments
  • Non-Latin symbols in channel names

    Non-Latin symbols in channel names

    I don't know if it is an issue with tifffile or xtiff library, but when channel names contain non-Latin symbols then to_tiff method crashes: https://github.com/BodenmillerGroup/xtiff/blob/d0a7b5cf2626aaa8cdb3a1f6403d8edd9353c782/xtiff.py#L311

    Traceback (most recent call last):
      File "/home/anton/bblab/imctools/imctools/converters/mcdfolder2imcfolder.py", line 59, in mcdfolder_to_imcfolder
        imc_writer.write_imc_folder(create_zip=create_zip)
      File "/home/anton/bblab/imctools/imctools/io/imc/imcwriter.py", line 77, in write_imc_folder
        acquisition_data.save_ome_tiff(
      File "/home/anton/bblab/imctools/imctools/data/acquisitiondata.py", line 136, in save_ome_tiff
        to_tiff(
      File "/home/anton/bblab/imctools/venv/lib/python3.8/site-packages/xtiff.py", line 311, in to_tiff
        writer.save(data=img, photometric='MINISBLACK', compress=compression, description=description,
      File "/home/anton/bblab/imctools/venv/lib/python3.8/site-packages/tifffile/tifffile.py", line 1836, in write
        addtag(270, 's', 0, description, writeonce=True)
      File "/home/anton/bblab/imctools/venv/lib/python3.8/site-packages/tifffile/tifffile.py", line 1772, in addtag
        value = bytestr(value, 'ascii') + b'\0'
      File "/home/anton/bblab/imctools/venv/lib/python3.8/site-packages/tifffile/tifffile.py", line 15622, in bytestr
        return s.encode(encoding) if isinstance(s, str) else s
    UnicodeEncodeError: 'ascii' codec can't encode character '\u03b5' in position 1241: ordinal not in range(128)
    
    
    bug 
    opened by plankter 6
  • Fix for deprecated TiffWriter.save method.

    Fix for deprecated TiffWriter.save method.

    TiffWriter.save is deprecated - we should replace replace with TiffWriter.write. Issue: https://github.com/BodenmillerGroup/xtiff/issues/11

    I also added a separate test.yml workflow to make development easier when not intending to deploy.

    Changelog from tifffile

    2022.2.2 Fix TypeError when second ImageDescription tag contains non-ASCII (#112). Fix parsing IJMetadata with many IJMetadataByteCounts (#111). Detect MicroManager NDTiffv2 header (not tested). Remove cache from ZarrFileSequenceStore (use zarr.LRUStoreCache). Raise limit on maximum number of pages. Use J2K format when encoding JPEG2000 segments. Formally deprecate imsave and TiffWriter.save. Drop support for Python 3.7 and numpy < 1.19 (NEP29).

    opened by agvaughan 4
  • Fix Mu Character.

    Fix Mu Character.

    The mu character appeared to somewhat non-functioning previously. I'm not 100% sure what is going on here but the character now prints as μ instead of µ which seems more correct. @LauraKuett could you test this out to confirm?

    opened by ilan-gold 4
  • Memory efficient writing to TIFF and pyramidal tiffs

    Memory efficient writing to TIFF and pyramidal tiffs

    Hi!

    I wanted to discuss two (somewhat related) issues. At the moment we need to load the whole array into memory in order to save it to TIFF. I would like to have an option to write by chunks, this would be memory efficient, but slower since we cannot write in parallel to TIFF.

    Related to this, I would also like to have support for writing pyramidal tiffs, so I can use applications that support them (e.g. QuPath) to visualise really large datasets. Writing the pyramidal structure would again be memory efficient at expense of speed.

    I have code that does this, but I wonder (and hence this issue) if that is something that you want added to xtiff.

    Cheers

    enhancement 
    opened by eddienko 2
  • TiffWriter.save is deprecated - replace with tiffwriter.write

    TiffWriter.save is deprecated - replace with tiffwriter.write

    TiffWriter.save is deprecated - we should replace replace with TiffWriter.write

    Changelog from tifffile

    2022.2.2
        Fix TypeError when second ImageDescription tag contains non-ASCII (#112). Fix parsing IJMetadata with many IJMetadataByteCounts (#111). Detect MicroManager NDTiffv2 header (not tested). Remove cache from ZarrFileSequenceStore (use zarr.LRUStoreCache). Raise limit on maximum number of pages. Use J2K format when encoding JPEG2000 segments. Formally deprecate imsave and TiffWriter.save. Drop support for Python 3.7 and numpy < 1.19 (NEP29).
    

    I wrote and tested a fix in the fork here - will add a PR If that works for you!

    bug 
    opened by agvaughan 1
  • Save OME-TIFF images as interleaved=false for grayscale images

    Save OME-TIFF images as interleaved=false for grayscale images

    As reported by @LauraKuett, when saving (grayscale) TZCYX image stacks (i.e., TZCYXS with S=1, as opposed to S=3 or 4 for RGB(A) images), images can be interpreted as non-interleaved and should therefore be saved as interleaved=false in the OME-XML metadata to improve compatibility with third-party software.

    enhancement 
    opened by jwindhager 0
  • Tifffile updates

    Tifffile updates

    Restores compatibility with recent tifffile updates and adds support for tifffile's software parameter.

    Also see cgohlke/tifffile#21 - many thanks to @cgohlke for the prompt support.

    @plankter please review and approve if it works

    bug 
    opened by jwindhager 0
Releases(v0.7.0)
CleverCSV is a Python package for handling messy CSV files.

CleverCSV is a Python package for handling messy CSV files. It provides a drop-in replacement for the builtin CSV module with improved dialect detection, and comes with a handy command line applicati

The Alan Turing Institute 1k Dec 19, 2022
A tool for batch processing large fasta files and accompanying metadata table to upload to repositories via API

Fasta Uploader A tool for batch processing large fasta files and accompanying metadata table to repositories via API The python fasta_uploader.py scri

Centre for Infectious Disease and One Health 1 Dec 09, 2021
MetaMove is written in Python3 and aims at easing batch renaming operations based on file meta data.

MetaMove MetaMove is written in Python3 and aims at easing batch renaming operations based on file meta data. MetaMove abuses eval combined with f-str

Jan Philippi 2 Dec 28, 2021
Maltego transforms to pivot between PE files based on their VirusTotal codeblocks

VirusTotal Codeblocks Maltego Transforms Introduction These Maltego transforms allow you to pivot between different PE files based on codeblocks they

Ariel Jungheit 18 Feb 03, 2022
MHS2 Save file editing tools. Transfers save files between players, switch and pc version, encrypts and decrypts.

SaveTools MHS2 Save file editing tools. Transfers save files between players, switch and pc version, encrypts and decrypts. Credits Written by Asteris

31 Nov 17, 2022
Two scripts help you to convert csv file to md file by template

Two scripts help you to convert csv file to md file by template. One help you generate multiple md files with different filenames from the first colume of csv file. Another can generate one md file w

2 Oct 15, 2022
ValveVMF - A python library to parse Valve's VMF files

ValveVMF ValveVMF is a Python library for parsing .vmf files for the Source Engi

pySourceSDK 2 Jan 02, 2022
OneDriveExplorer - A command line and GUI based application for reconstructing the folder strucure of OneDrive from the UserCid.dat file

OneDriveExplorer - A command line and GUI based application for reconstructing the folder strucure of OneDrive from the UserCid.dat file

Brian Maloney 100 Dec 13, 2022
Organize the files into the relevant sub-folders

This program can be used to organize files in a directory by their file extension. And move duplicate files to a duplicates folder.

Thushara Thiwanka 2 Dec 15, 2021
Find potentially sensitive files

find_files Find potentially sensitive files This script searchs for potentially sensitive files based off of file name or string contained in the file

4 Aug 20, 2022
Python file organizer application

Python file organizer application

Pak Maneth 1 Jun 21, 2022
Object-oriented file system path manipulation

path (aka path pie, formerly path.py) implements path objects as first-class entities, allowing common operations on files to be invoked on those path

Jason R. Coombs 1k Dec 28, 2022
fast change directory with python and ruby

fcdir fast change directory with python and ruby run run python script , chose drirectoy and change your directory need you need python and ruby deskt

XCO 2 Jun 20, 2022
A python script to convert an ucompressed Gnucash XML file to a text file for Ledger and hledger.

README 1 gnucash2ledger gnucash2ledger is a Python script based on the Github Gist by nonducor (nonducor/gcash2ledger.py). This Python script will tak

Thomas Freeman 0 Jan 28, 2022
A simple tool to find and replace all the matches of a regular expression in file(s).

FindREp A simple tool to find and replace all the matches of a regular expression in file(s). You can either select the file(s) directly or select a f

Biraj 5 Oct 18, 2022
Listreqs is a simple requirements.txt generator. It's an alternative to pipreqs

⚡ Listreqs Listreqs is a simple requirements.txt generator. It's an alternative to pipreqs. Where in Pipreqs, it helps you to Generate requirements.tx

Soumyadip Sarkar 4 Oct 15, 2021
Python interface for reading and appending tar files

Python interface for reading and appending tar files, while keeping a fast index for finding and reading files in the archive. This interface has been

Lawrence Livermore National Laboratory 1 Nov 12, 2021
pydicom - Read, modify and write DICOM files with python code

pydicom is a pure Python package for working with DICOM files. It lets you read, modify and write DICOM data in an easy "pythonic" way.

DICOM in Python 1.5k Jan 04, 2023
Instant Fuzzy File Search for Alfred

List all the files inside a folder using fd, and instantly fuzzy-search through all of them using fzf, all from inside Alfred with a single keyword: fzf.

Mr. Pennyworth 37 Nov 30, 2022
Singer is an open source standard for moving data between databases, web APIs, files, queues, and just about anything else you can think of.

Singer is an open source standard for moving data between databases, web APIs, files, queues, and just about anything else you can think of. Th

Singer 1.1k Jan 05, 2023