Skip to main content

Read Carl Zeiss image files (CZI)

Project description

Czifile is a Python library for reading image data and metadata from Carl Zeiss Image (CZI) files, the native file format of ZEN by Carl Zeiss Microscopy GmbH.

Czifile is a pure-Python library under the BSD-3-Clause license. It provides single-call array access to scenes and spatial ROIs, xarray DataArray output with physical axis coordinates, multi-scene merging, per-dimension selection by integer, slice, or sequence, chunk-based iteration, and pyramid-level access. It handles Fast Airyscan upsampling and PALM downsampling with optional stored-resolution output, and assembles FCS and line-scan files from T-chunked subblocks. It also supports Zstd and JPEG XR compression, pixel type promotion across channels, and direct access to all ZISRAW segments and file-level attachments.

Author:

Christoph Gohlke

License:

BSD-3-Clause

Version:

2026.3.15

DOI:

10.5281/zenodo.14948581

Quickstart

Install the czifile package and all dependencies from the Python Package Index:

python -m pip install -U czifile[all]

See Examples for using the programming interface.

Source code, examples, and support are available on GitHub.

Requirements

This revision was tested with the following requirements and dependencies (other versions may work):

Revisions

2026.3.15

  • Replace CziImagePlanes with CziImageChunks (breaking).

  • Add CziImage.chunks method for flexible chunk-based iteration.

  • Add CziFile.metadata_segment property.

  • Add offset properties to CziAttachmentEntryA1 and subblock entry classes.

  • Add CziSegmentId.packed property returning the 16-byte on-disk field.

  • Manage update_pending flag in CziFile context manager for writable handles.

  • Improve documentation.

2026.3.14

  • Add option to return pixel data at stored resolution.

  • Allow sequence and slice of scene indices in imread and asarray/asxarray.

  • Interpret dimension slice selection as absolute coordinates.

  • Add command line options to select dimensions.

2026.3.12

  • Rewrite with many breaking changes.

  • Support Zstd compression schemes.

  • Support reading subblock masks.

  • Add CziFile.scenes interface.

  • Add pyramid level access via CziImage.levels.

  • Add option to read subset of image data.

  • Add option to iterate over image planes in any dimension order.

  • Add xarray-style attributes.

  • Add asxarray method to return image as xarray DataArray with metadata.

  • Add fillvalue and maxworkers parameters to asarray.

  • Add option to specify pixel type.

  • Promote pixel type when channels have mixed types.

  • Remove Mosaic dimension from CziDirectoryEntryDV.dims; use mosaic_index.

  • Reduce caching of CziDirectoryEntryDV properties.

  • Remove resize and order parameters from asarray (breaking).

  • Remove czi2tif function and command line script.

  • Prefix public class names with Czi.

  • Raise CziFileError for issues with CZI file structure.

  • Use logging instead of warnings.

  • Improve representation of instances.

  • Add pytest-based unit tests.

  • Add type hints.

  • Convert docstrings to Google style with Sphinx directives.

  • Remove imagecodecs-lite fallback; require imagecodecs.

  • Remove scipy/ndimage dependency.

  • Make tifffile an optional dependency.

  • Drop support for Python < 3.12 and numpy < 2 (SPEC 0).

2019.7.2.3

Refer to the CHANGES file for older revisions.

Notes

The API is not stable yet and might change between revisions.

Python 32-bit versions are deprecated. Python < 3.12 are no longer supported.

“ZEISS” and “Carl Zeiss” are registered trademarks of Carl Zeiss AG.

The ZISRAW file format design specification [1] is confidential and the license agreement does not permit to write data into CZI files.

Only a subset of the 2016 specification is implemented. Specifically, multi-file images and topography images are not supported. Some features are untested due to lack of sample files.

Tested on Windows with a few example files only.

Czifile relies on the imagecodecs package for decoding LZW, ZStandard, JPEG, and JPEG XR compressed images.

Other libraries for reading CZI files (all GPL or LGPL licensed): libczi, pylibCZIrw, bioio-czi, bio-formats, libCZI (deprecated), and pylibczi (deprecated).

References

Examples

Read image data of the first scene from a CZI file as numpy array:

>>> arr = imread('Example.czi')
>>> assert arr.shape == (2, 2, 3, 486, 1178)
>>> assert arr.dtype == 'uint16'

Access scenes, shape, and metadata:

>>> with CziFile('Example.czi') as czi:
...     assert len(czi.scenes) == 3
...     img = czi.scenes[0]  # 0 is the absolute coordinate of the first scene
...     assert img.shape == (2, 2, 3, 486, 1178)
...     assert img.dims == ('T', 'C', 'Z', 'Y', 'X')
...     assert img.dtype == 'uint16'
...     assert img.compression.name == 'ZSTDHDR'
...     assert list(img.channels) == ['DAPI', 'EGFP']
...     assert czi.metadata().startswith('<ImageDocument>')
...

Select dimensions and read as numpy array:

>>> with CziFile('Example.czi') as czi:
...     img = czi.scenes[0]
...     assert img.sizes == {'T': 2, 'C': 2, 'Z': 3, 'Y': 486, 'X': 1178}
...
...     # integer selection: fix T=0 and C=0; result has Z, but no T or C axis
...     volume = img(T=0, C=0).asarray()
...     assert volume.shape == (3, 486, 1178)
...
...     # None selection: keep all values but reorder dimensions
...     # dims order follows the kwargs order, then spatial dims
...     # T (unspecified) comes first, then C, Z (in kwargs order), then Y X
...     tczyx = img(C=None, Z=None).asarray()
...     assert tczyx.shape == (2, 2, 3, 486, 1178)
...
...     # read in C-outer, Z-inner, T-innermost order with parallelism
...     arr = img(C=None, Z=None, T=None).asarray(maxworkers=8)
...     assert arr.shape == (2, 3, 2, 486, 1178)  # 'C', 'Z', 'T', 'Y', 'X'
...
...     # img.bbox gives (x, y, width, height) in global CZI coordinates
...     x0, y0, *_ = img.bbox
...     plane_roi = img(T=0, C=0, roi=(x0, y0, 128, 128)).asarray()
...     assert plane_roi.shape == (3, 128, 128)  # 'Z', 'Y', 'X'
...
...     # fill pixels outside subblock coverage with a specific value
...     padded = img(C=0, roi=(0, 0, 2048, 2048)).asarray(fillvalue=0)
...     assert padded.shape == (2, 3, 2048, 2048)  # 'T', 'Z', 'Y', 'X'
...

Iterate image chunks:

>>> with CziFile('Example.czi') as czi:
...     img = czi.scenes[0]
...
...     # iterate individual Y/X planes as CziImage views
...     # by default, all non-spatial dims are iterated one-at-a-time
...     for chunk in img.chunks():
...         assert isinstance(chunk, CziImage)
...         assert chunk.asarray().shape == (486, 1178)
...
...     # keep C in each chunk: iterate T and Z only
...     for chunk in img.chunks(C=None):
...         assert chunk.asarray().shape == (2, 486, 1178)
...
...     # batch Z into groups of 3; last chunk may be smaller if Z indivisible
...     for chunk in img.chunks(Z=3):
...         assert chunk.sizes['Z'] <= 3
...
...     # spatial tiling: iterate T x C x Z x grid
...     for chunk in img.chunks(Y=256, X=256):
...         assert chunk.shape[-2] <= 256
...         assert chunk.shape[-1] <= 256
...
...     # keep C, tile spatially
...     for chunk in img.chunks(C=None, Y=256, X=256):
...         assert chunk.dims[0] == 'C'
...

Read image as xarray DataArray with physical coordinates and attributes:

>>> with CziFile('Example.czi') as czi:
...     xarr = czi.scenes[0].asxarray()
...     assert xarr.name == 'Scene 0'
...     assert xarr.sizes == {'T': 2, 'C': 2, 'Z': 3, 'Y': 486, 'X': 1178}
...     assert xarr.coords['X'].size == 1178  # physical axis coordinates
...

Access multiple scenes:

>>> with CziFile('Example.czi') as czi:
...     # iterate scenes individually and read as arrays
...     for img in czi.scenes.values():
...         arr = img.asarray()
...
...     # query which scenes (indices) are available
...     assert list(czi.scenes.keys()) == [0, 1, 2]
...
...     # select the second scene
...     assert czi.scenes[1].sizes == {
...         'T': 2,
...         'C': 2,
...         'Z': 3,
...         'Y': 256,
...         'X': 256,
...     }
...
...     # merge selected scenes into one
...     img = czi.scenes(scene=[0, 1])  # first 2 scenes
...     assert img.sizes == {'T': 2, 'C': 2, 'Z': 3, 'Y': 1109, 'X': 1760}
...
...     # merge all scenes into one
...     img = czi.scenes()
...     assert img.sizes == {'T': 2, 'C': 2, 'Z': 3, 'Y': 2055, 'X': 2581}
...

Access pyramid levels:

>>> with CziFile('Example.czi') as czi:
...     img = czi.scenes[0]
...     assert img.is_pyramid
...     assert len(img.levels) == 2  # full resolution + 1 downsampled level
...     assert img.levels[0] is img  # full resolution level is the same as img
...     overview = img.levels[1]  # lowest-res level
...     assert overview.sizes == {'T': 2, 'C': 2, 'Z': 3, 'Y': 243, 'X': 589}
...

Access attachments:

>>> with CziFile('Example.czi') as czi:
...     for attachment in czi.attachments():
...         name = attachment.attachment_entry.name
...         data = attachment.data()  # decoded (ndarray, tuple, bytes...)
...         raw = attachment.data(raw=True)  # bytes; may be written to file
...
...     # convenience shortcut for TimeStamps attachment data
...     assert czi.timestamps.shape == (2,)
...

Low-level access to CZI file segments:

>>> with CziFile('Example.czi') as czi:
...     # file header: version, GUIDs, and segment offsets
...     hdr = czi.header
...     assert hdr.version == (1, 0)
...     assert str(hdr.file_guid) == 'f8a61493-053e-c94e-bae0-bc7e96d18997'
...     assert not hdr.update_pending
...
...     # iterate all subblock segments sequentially via the directory
...     for segdata in czi.subblocks():
...         entry = segdata.directory_entry
...         assert entry.dims == ('H', 'T', 'C', 'Z', 'Y', 'X', 'S')
...         assert entry.start == (0, 0, 0, 0, 0, 582, 0)
...         assert entry.shape == (1, 1, 1, 1, 486, 1178, 1)
...         assert entry.stored_shape == (1, 1, 1, 1, 243, 589, 1)
...         assert entry.compression == CziCompressionType.ZSTDHDR
...         assert segdata.data_offset == 661865  # offset of image data
...         assert segdata.data_size == 183875  # size of compressed image data
...         tile = segdata.data()  # decompressed image data as numpy array
...         assert tile.shape == entry.stored_shape
...         assert tile.dtype == entry.pixel_type.dtype
...         assert isinstance(segdata.data(raw=True), bytes)  # compressed data
...         assert segdata.metadata().startswith('<METADATA>')
...         break  # just the first subblock segment for demonstration
...
...     # iterate only image tiles in a selected image view
...     img = czi.scenes[0](T=0, C=0, Z=0)
...     for entry in img.directory_entries:
...         segdata = entry.read_segment_data(czi)
...         assert isinstance(segdata, CziSubBlockSegmentData)
...         tile = segdata.data()
...         assert tile.shape == entry.stored_shape
...         break  # just the first filtered directory entry
...
...     # walk all file segments by type using their ZISRAW segment IDs
...     for segdata in czi.segments(CziSegmentId.ZISRAWSUBBLOCK):
...         assert isinstance(segdata, CziSubBlockSegmentData)
...
...     # direct low-level segment header at a known file offset
...     seg = CziSegment(czi, czi.header.directory_position)
...     assert seg.sid == CziSegmentId.ZISRAWDIRECTORY
...     assert seg.used_size == 68768
...     seg_data = seg.data()
...     assert isinstance(seg_data, CziSubBlockDirectorySegmentData)
...

View the images and metadata in a CZI file from the console:

$ python -m czifile Example.czi

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

czifile-2026.3.15.tar.gz (97.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

czifile-2026.3.15-py3-none-any.whl (59.9 kB view details)

Uploaded Python 3

File details

Details for the file czifile-2026.3.15.tar.gz.

File metadata

  • Download URL: czifile-2026.3.15.tar.gz
  • Upload date:
  • Size: 97.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for czifile-2026.3.15.tar.gz
Algorithm Hash digest
SHA256 4c94cdd2e1d98d3fa0d9c80075be2213384484f313fdc796cc341f26cfb34c2e
MD5 69cb407f92ac108a698f598b627d53fe
BLAKE2b-256 495a3b92ab8f3feccc33a837a6817716814cd8082d792a3596a31b9627b8b844

See more details on using hashes here.

File details

Details for the file czifile-2026.3.15-py3-none-any.whl.

File metadata

  • Download URL: czifile-2026.3.15-py3-none-any.whl
  • Upload date:
  • Size: 59.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for czifile-2026.3.15-py3-none-any.whl
Algorithm Hash digest
SHA256 a7e894cc7d5d60e70981162c8ffc46d7d95779f27b70814fc63b781369002d99
MD5 efa742e293c1114042f75f6636233653
BLAKE2b-256 a65da891edb52d471063cc860a54b43dd2adc2f9dfcec0d810bfef69a4087882

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page