Skip to content

Commit

Permalink
Release v2024.5.10
Browse files Browse the repository at this point in the history
  • Loading branch information
cgohlke committed May 10, 2024
1 parent b9baea0 commit 9000e74
Showing 1 changed file with 35 additions and 24 deletions.
59 changes: 35 additions & 24 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ many proprietary metadata formats.

:Author: `Christoph Gohlke <https://www.cgohlke.com>`_
:License: BSD 3-Clause
:Version: 2024.5.3
:Version: 2024.5.10
:DOI: `10.5281/zenodo.6795860 <https://doi.org/10.5281/zenodo.6795860>`_

Quickstart
Expand Down Expand Up @@ -74,17 +74,22 @@ This revision was tested with the following requirements and dependencies
(required for plotting)
- `Lxml <https://pypi.org/project/lxml/>`_ 5.2.1
(required only for validating and printing XML)
- `Zarr <https://pypi.org/project/zarr/>`_ 2.17.2
- `Zarr <https://pypi.org/project/zarr/>`_ 2.18.0
(required only for opening Zarr stores)
- `Fsspec <https://pypi.org/project/fsspec/>`_ 2024.3.1
(required only for opening ReferenceFileSystem files)

Revisions
---------

2024.5.10

- Pass 5082 tests.
- Support reading JPEGXL compression in DNG 1.7.
- Read invalid TIFF created by IDEAS software.

2024.5.3

- Pass 5080 tests.
- Fix reading incompletely written LSM.
- Fix reading Philips DP with extra rows of tiles (#253, breaking).

Expand Down Expand Up @@ -384,8 +389,8 @@ References
http://www.cipa.jp/std/documents/e/DC-008-Translation-2016-E.pdf
- The EER (Electron Event Representation) file format.
https://github.com/fei-company/EerReaderLib
- Digital Negative (DNG) Specification. Version 1.5.0.0, June 2012.
https://www.adobe.com/content/dam/acom/en/products/photoshop/pdfs/dng_spec_1.5.0.0.pdf
- Digital Negative (DNG) Specification. Version 1.7.1.0, September 2023.
https://helpx.adobe.com/content/dam/help/en/photoshop/pdf/DNG_Spec_1_7_1_0.pdf
- Roche Digital Pathology. BIF image file format for digital pathology.
https://diagnostics.roche.com/content/dam/diagnostics/Blueprint/en/pdf/rmd/Roche-Digital-Pathology-BIF-Whitepaper.pdf
- Astro-TIFF specification. https://astro-tiff.sourceforge.io/
Expand Down Expand Up @@ -453,6 +458,7 @@ Iterate over all pages in the TIFF file and successively read images:
>>> with TiffFile('temp.tif') as tif:
... for page in tif.pages:
... image = page.asarray()
...

Get information about the image stack in the TIFF file without reading
any image data:
Expand Down Expand Up @@ -480,6 +486,7 @@ Inspect the "XResolution" tag from the first page in the TIFF file:

>>> with TiffFile('temp.tif') as tif:
... tag = tif.pages[0].tags['XResolution']
...
>>> tag.value
(1, 1)
>>> tag.name
Expand All @@ -497,11 +504,13 @@ Iterate over all tags in the TIFF file:
... for page in tif.pages:
... for tag in page.tags:
... tag_name, tag_value = tag.name, tag.value
...

Overwrite the value of an existing tag, for example, XResolution:

>>> with TiffFile('temp.tif', mode='r+') as tif:
... _ = tif.pages[0].tags['XResolution'].overwrite((96000, 1000))
...

Write a 5-dimensional floating-point array using BigTIFF format, separate
color components, tiling, Zlib compression level 8, horizontal differencing
Expand All @@ -518,7 +527,7 @@ predictor, and additional metadata:
... compression='zlib',
... compressionargs={'level': 8},
... predictor=True,
... metadata={'axes': 'TZCYX'}
... metadata={'axes': 'TZCYX'},
... )

Write a 10 fps time series of volumes with xyz voxel size 2.6755x2.6755x3.9474
Expand All @@ -530,15 +539,15 @@ micron^3 to an ImageJ hyperstack formatted TIFF file:
... 'temp.tif',
... volume,
... imagej=True,
... resolution=(1./2.6755, 1./2.6755),
... resolution=(1.0 / 2.6755, 1.0 / 2.6755),
... metadata={
... 'spacing': 3.947368,
... 'unit': 'um',
... 'finterval': 1/10,
... 'finterval': 1 / 10,
... 'fps': 10.0,
... 'axes': 'TZYX',
... 'Labels': image_labels,
... }
... },
... )

Read the volume and metadata from the ImageJ hyperstack file:
Expand All @@ -547,6 +556,7 @@ Read the volume and metadata from the ImageJ hyperstack file:
... volume = tif.asarray()
... axes = tif.series[0].axes
... imagej_metadata = tif.imagej_metadata
...
>>> volume.shape
(6, 57, 256, 256)
>>> axes
Expand All @@ -567,10 +577,7 @@ Create a TIFF file containing an empty image and write to the memory-mapped
NumPy array (note: this does not work with compression or tiling):

>>> memmap_image = memmap(
... 'temp.tif',
... shape=(256, 256, 3),
... dtype='float32',
... photometric='rgb'
... 'temp.tif', shape=(256, 256, 3), dtype='float32', photometric='rgb'
... )
>>> type(memmap_image)
<class 'numpy.memmap'>
Expand All @@ -587,6 +594,7 @@ interoperability):
>>> with TiffWriter('temp.tif') as tif:
... tif.write(series0, photometric='rgb')
... tif.write(series1, photometric='minisblack')
...

Read the second image series from the TIFF file:

Expand All @@ -600,6 +608,7 @@ Successively write the frames of one contiguous series to a TIFF file:
>>> with TiffWriter('temp.tif') as tif:
... for frame in data:
... tif.write(frame, contiguous=True)
...

Append an image series to the existing TIFF file (note: this does not work
with ImageJ hyperstack or OME-TIFF files):
Expand All @@ -614,13 +623,14 @@ Create a TIFF file from a generator of tiles:
... for y in range(0, data.shape[0], tileshape[0]):
... for x in range(0, data.shape[1], tileshape[1]):
... yield data[y : y + tileshape[0], x : x + tileshape[1]]
...
>>> imwrite(
... 'temp.tif',
... tiles(data, (16, 16)),
... tile=(16, 16),
... shape=data.shape,
... dtype=data.dtype,
... photometric='rgb'
... photometric='rgb',
... )

Write a multi-dimensional, multi-resolution (pyramidal), multi-series OME-TIFF
Expand All @@ -632,7 +642,7 @@ series:
>>> subresolutions = 2
>>> pixelsize = 0.29 # micrometer
>>> with TiffWriter('temp.ome.tif', bigtiff=True) as tif:
... metadata={
... metadata = {
... 'axes': 'TCYXS',
... 'SignificantBits': 8,
... 'TimeIncrement': 0.1,
Expand All @@ -642,36 +652,37 @@ series:
... 'PhysicalSizeY': pixelsize,
... 'PhysicalSizeYUnit': 'µm',
... 'Channel': {'Name': ['Channel 1', 'Channel 2']},
... 'Plane': {'PositionX': [0.0] * 16, 'PositionXUnit': ['µm'] * 16}
... 'Plane': {'PositionX': [0.0] * 16, 'PositionXUnit': ['µm'] * 16},
... }
... options = dict(
... photometric='rgb',
... tile=(128, 128),
... compression='jpeg',
... resolutionunit='CENTIMETER',
... maxworkers=2
... maxworkers=2,
... )
... tif.write(
... data,
... subifds=subresolutions,
... resolution=(1e4 / pixelsize, 1e4 / pixelsize),
... metadata=metadata,
... **options
... **options,
... )
... # write pyramid levels to the two subifds
... # in production use resampling to generate sub-resolution images
... for level in range(subresolutions):
... mag = 2**(level + 1)
... mag = 2 ** (level + 1)
... tif.write(
... data[..., ::mag, ::mag, :],
... subfiletype=1,
... resolution=(1e4 / mag / pixelsize, 1e4 / mag / pixelsize),
... **options
... **options,
... )
... # add a thumbnail image as a separate series
... # it is recognized by QuPath as an associated image
... thumbnail = (data[0, 0, ::8, ::8] >> 2).astype('uint8')
... tif.write(thumbnail, metadata={'Name': 'thumbnail'})
...

Access the image levels in the pyramidal OME-TIFF file:

Expand All @@ -680,6 +691,7 @@ Access the image levels in the pyramidal OME-TIFF file:
>>> with TiffFile('temp.ome.tif') as tif:
... baseimage = tif.series[0].asarray()
... second_level = tif.series[0].levels[1].asarray()
...

Iterate over and decode single JPEG compressed tiles in the TIFF file:

Expand All @@ -694,6 +706,7 @@ Iterate over and decode single JPEG compressed tiles in the TIFF file:
... tile, indices, shape = page.decode(
... data, index, jpegtables=page.jpegtables
... )
...

Use Zarr to read parts of the tiled, pyramidal images in the TIFF file:

Expand Down Expand Up @@ -743,7 +756,7 @@ to it via the Zarr interface (note: this does not work with compression):
... dtype='uint16',
... photometric='minisblack',
... tile=(128, 128),
... metadata={'axes': 'CYX'}
... metadata={'axes': 'CYX'},
... )
>>> store = imread('temp.ome.tif', mode='r+', aszarr=True)
>>> z = zarr.open(store, mode='r+')
Expand All @@ -768,9 +781,7 @@ dtype('float64')
Read an image stack from a series of TIFF files with a file name pattern
as NumPy or Zarr arrays:

>>> image_sequence = TiffSequence(
... 'temp_C0*.tif', pattern=r'_(C)(\d+)(T)(\d+)'
... )
>>> image_sequence = TiffSequence('temp_C0*.tif', pattern=r'_(C)(\d+)(T)(\d+)')
>>> image_sequence.shape
(1, 2)
>>> image_sequence.axes
Expand Down

0 comments on commit 9000e74

Please sign in to comment.