Rewrite: IJTiffWriter is replaced by IJTiffFile which includes preliminary support for reading.

- Support colormaps per channels via the colors argument.
- No writer process anymore, the pool writes to the file by using a filehandle with a lock.
- Can save extra tiff tags in every frame and/or per frame individually.
- Header and IFD classes with support for reading files.
- Multiplexing is now done automatically when multiple IJTiffFiles are initialized: the process pool is shared by all IJTiffFiles.
This commit is contained in:
Wim Pomp
2022-05-03 16:10:13 +02:00
parent e7b999faa7
commit edc126d079
4 changed files with 688 additions and 469 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/build/
/dist/
*.egg_info
/.idea/

View File

@@ -1,14 +1,15 @@
# Tiffwrite # Tiffwrite
Exploiting [tifffile](https://pypi.org/project/tifffile/) in parallel to write ImageJ compatible tiffs with good Exploiting [tifffile](https://pypi.org/project/tifffile/) in parallel to write BioFormats/ImageJ compatible tiffs with
compression. good compression.
## Features ## Features
- Writes bigtiff file that opens in ImageJ as hyperstack with correct dimensions. - Writes bigtiff files that open in ImageJ as hyperstack with correct dimensions.
- Parallel compression. - Parallel compression.
- Write individual frames in random order. - Write individual frames in random order.
- Compresses even more by referencing tag or image data which otherwise would have been save several times. - Compresses even more by referencing tag or image data which otherwise would have been saved several times.
For example empty frames, or a long string tag on every frame. For example empty frames, or a long string tag on every frame.
- Enables memory efficient scripts by saving frames whenever they're ready to be saved, not waiting for the whole stack. - Enables memory efficient scripts by saving frames whenever they're ready to be saved, not waiting for the whole stack.
- Colormaps, extra tags globally or frame dependent.
## Installation ## Installation
pip install tiffwrite pip install tiffwrite
@@ -18,31 +19,37 @@ or
# Usage # Usage
## Write an image stack ## Write an image stack
tiffwrite(file, data, axes='TZCXY', bar=False, colormap=None, pxsize=None) tiffwrite(file, data, axes='TZCXY', dtype=None, bar=False, *args, **kwargs)
- file: string; filename of the new tiff file.
- data: 2 to 5D numpy array in one of these datatypes: (u)int8, (u)int16, float32.
- axes: string; order of dimensions in data, default: TZCXY for 5D, ZCXY for 4D, CXY for 3D, XY for 2D data.
- dtype: string; cast data to dtype before saving, only (u)int8, (u)int16 and float32 are supported.
- bar: bool; whether or not to show a progress bar.
- args, kwargs: arguments to be passed to IJTiffFile, see below.
- file: string; filename of the new tiff file.
- data: 2 to 5D numpy array in one of these datatypes: (u)int8, (u)int16, float32.
- axes: string; order of dimensions in data, default: TZCXY for 5D, ZCXY for 4D, CXY for 3D, XY for 2D data.
- bar: bool; whether or not to show a progress bar.
- colormap: string; choose any colormap from the colorcet module.
- pxsize: float; set tiff tag so ImageJ can read the pixel size (in um).
## Write one frame at a time ## Write one frame at a time
with IJTiffWriter(file, shape, dtype='uint16', colormap=None, nP=None, extratags=None, pxsize=None) as tif: with IJTiffFile(file, shape, dtype='uint16', colors=None, colormap=None, pxsize=None, deltaz=None,
timeinterval=None, **extratags) as tif:
some loop: some loop:
tif.save(frame, c, z, t) tif.save(frame, c, z, t)
- file: string; filename of the new tiff file, or list of filenames. - file: string; filename of the new tiff file.
- shape: iterable; shape (C, Z, T) of data to be written in file. - shape: iterable; shape (C, Z, T) of data to be written in file.
- dtype: string; cast data to dtype before saving, only (u)int8, (u)int16 and float32 are supported. - dtype: string; cast data to dtype before saving, only (u)int8, (u)int16 and float32 are supported.
- colormap: string; choose any colormap from the colorcet module. - colors: iterable of strings; one color per channel, valid colors (also html) are defined in matplotlib.colors.
- nP: int; number of compressor workers to use Without colormap BioFormats will set the colors in this order: rgbwcmy.
- extratags: dict {int tagnr: (int type, data)}, extra tags to save on every frame, will cause a crash if not used Note that the color green is dark, the usual green is named 'lime' here.
correctly! - colormap: string; choose any colormap from the colorcet module. Colors and colormap cannot be used simultaneously.
- pxsize: float; set tiff tag so ImageJ can read the pixel size (in um). - pxsize: float; pixel size im um.
- deltaz: float; z slice interval in um.
- timeinterval: float; time between frames in seconds.
- extratags: other tags to be saved, example: Artist='John Doe', Tag4567=[400, 500] or
Copyright=Tag('ascii', 'Made by me'). See tiff_tag_registry.items().
- frame: 2D numpy array with data - frame: 2D numpy array with data.
- c, z, t: int; channel, z, time coordinates of the frame - c, z, t: int; channel, z, time coordinates of the frame.
# Examples # Examples
@@ -55,11 +62,11 @@ correctly!
## Write one frame at a time ## Write one frame at a time
from itertools import product from itertools import product
from tiffwrite import IJTiffWriter from tiffwrite import IJTiffFile
import numpy as np import numpy as np
shape = (3, 5, 10) # channels, z, time shape = (3, 5, 10) # channels, z, time
with IJTiffWriter('file.tif', shape, pxsize=0.09707) as tif: with IJTiffFile('file.tif', shape, pxsize=0.09707) as tif:
for c in range(shape[0]): for c in range(shape[0]):
for z in range(shape[1]): for z in range(shape[1]):
for t in range(shape[2]): for t in range(shape[2]):
@@ -67,21 +74,22 @@ correctly!
## Saving multiple tiffs simultaneously ## Saving multiple tiffs simultaneously
from itertools import product from itertools import product
from tiffwrite import IJTiffWriter from tiffwrite import IJTiffFile
import numpy as np import numpy as np
shape = (3, 5, 10) # channels, z, time shape = (3, 5, 10) # channels, z, time
with IJTiffWriter(('fileA.tif', 'fileB.tif'), shape) as tif: with IJTiffFile('fileA.tif', shape) as tif_a, IJTiffFile('fileB.tif', shape) as tif_b:
for c in range(shape[0]): for c in range(shape[0]):
for z in range(shape[1]): for z in range(shape[1]):
for t in range(shape[2]): for t in range(shape[2]):
tif.save('fileA.tif', np.random.randint(0, 10, (32, 32)), c, z, t) tif_a.save(np.random.randint(0, 10, (32, 32)), c, z, t)
tif.save('fileB.tif', np.random.randint(0, 10, (32, 32)), c, z, t) tif_b.save(np.random.randint(0, 10, (32, 32)), c, z, t)
## Tricks & tips ## Tricks & tips
- ImageJ colors channels in the order rgbwcym, and IJTiffwriter automatically and efficiently writes 0's when a frame is - The order of feeding frames to IJTiffFile is unimportant, IJTiffFile will order de ifd's such that the file will
skipped. You can use this when specific colors are important, for example: you want to use only red and blue.
- The order of feeding frames to IJTiffWriter is unimportant, IJTiffWriter will order de ifd's such that the file will
be opened as a correctly ordered hyperstack. be opened as a correctly ordered hyperstack.
- Using the colormap parameter you can make ImageJ open the file and apply the colormap. colormap='glasbey' is very - Using the colormap parameter you can make ImageJ open the file and apply the colormap. colormap='glasbey' is very
useful. useful.
- IJTiffFile does not allow more than one pool of parallel processes to be open at a time. Therefore, when writing
multiple tiff's simultaneously you have to open all before you start saving any frame, in this way all files share the
same pool.

View File

@@ -5,7 +5,7 @@ with open('README.md', 'r') as fh:
setuptools.setup( setuptools.setup(
name='tiffwrite', name='tiffwrite',
version='2021.12.0', version='2022.5.0',
author='Wim Pomp @ Lenstra lab NKI', author='Wim Pomp @ Lenstra lab NKI',
author_email='w.pomp@nki.nl', author_email='w.pomp@nki.nl',
description='Parallel tiff writer compatible with ImageJ.', description='Parallel tiff writer compatible with ImageJ.',
@@ -18,6 +18,6 @@ setuptools.setup(
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
], ],
python_requires='>=3.5', python_requires='>=3.7',
install_requires=['tifffile', 'numpy', 'tqdm', 'colorcet', 'multipledispatch'], install_requires=['tifffile', 'numpy', 'tqdm', 'colorcet', 'matplotlib'],
) )

File diff suppressed because it is too large Load Diff