Tifffile is a Python library for reading and writing TIFF files, particularly those used in microscopy and scientific imaging. It provides comprehensive support for various TIFF formats including BigTIFF, OME-TIFF, and multi-page TIFF stacks.
Why tifffile?
- Microscopy Standard: Full support for OME-TIFF format used by microscopes
- Performance: Fast reading and writing of large image stacks
- Metadata Handling: Extract and preserve imaging metadata
- Multi-dimensional: Handle time series, z-stacks, multi-channel images
- Memory Efficient: Memory-mapped reading for large files
Basic Usage
Reading TIFF Files
import tifffile
import numpy as np
# Read entire TIFF stack
image_stack = tifffile.imread('calcium_recording.tif')
print(f"Shape: {image_stack.shape}") # (frames, height, width)
# Memory-mapped reading (efficient for large files)
memmap = tifffile.memmap('large_recording.tif')
first_frame = memmap[0] # Access without loading entire file
Writing TIFF Files
# Save array as TIFF
tifffile.imwrite('output.tif', image_data)
# Save with metadata
tifffile.imwrite(
'output.tif',
image_data,
metadata={'axes': 'TYX', 'fps': 30}
)
# Save multi-page TIFF
tifffile.imwrite('stack.tif', image_stack, photometric='minisblack')
Working with OME-TIFF
Reading OME-TIFF Metadata
# Open OME-TIFF file
with tifffile.TiffFile('microscopy_image.ome.tif') as tif:
# Access OME metadata
ome_metadata = tif.ome_metadata
print(ome_metadata)
# Get image data
image = tif.asarray()
# Access page-level metadata
for page in tif.pages:
print(f"Shape: {page.shape}")
print(f"Dtype: {page.dtype}")
print(f"Tags: {page.tags}")
Parsing OME-XML
from xml.dom import minidom
with tifffile.TiffFile('recording.ome.tif') as tif:
ome_xml = tif.ome_metadata
# Parse XML
dom = minidom.parseString(ome_xml)
# Extract specific metadata
pixels = dom.getElementsByTagName('Pixels')[0]
size_t = int(pixels.getAttribute('SizeT'))
size_x = int(pixels.getAttribute('SizeX'))
size_y = int(pixels.getAttribute('SizeY'))
print(f"Dimensions: T={size_t}, X={size_x}, Y={size_y}")
Common Calcium Imaging Workflows
Loading Time Series
# Load calcium imaging recording
recording = tifffile.imread('calcium_traces.tif')
print(f"Recording shape: {recording.shape}") # (time, height, width)
# Extract specific time window
baseline = recording[0:100] # First 100 frames
# Process frame by frame
for frame_idx, frame in enumerate(recording):
# Apply processing
processed = filters.gaussian(frame, sigma=1)
Multi-Channel Images
# Read multi-channel TIFF
with tifffile.TiffFile('multi_channel.tif') as tif:
# Get all channels
images = tif.asarray()
# Separate channels (assuming channel dimension is first)
if images.ndim == 4: # (channel, time, height, width)
channel_1 = images[0]
channel_2 = images[1]
Saving Processed Results
# Save processed stack with metadata
metadata = {
'axes': 'TYX',
'fps': 30,
'processing': 'gaussian_filter_sigma_1.5'
}
tifffile.imwrite(
'processed_recording.tif',
processed_stack,
metadata=metadata,
compression='lzw' # Optional compression
)
Memory-Efficient Processing
Working with Large Files
# Memory-map large file (doesn't load into RAM)
data = tifffile.memmap('large_dataset.tif', mode='r')
# Process in chunks
chunk_size = 100
for i in range(0, len(data), chunk_size):
chunk = data[i:i+chunk_size]
# Process chunk
result = process_frames(chunk)
ImageJ Compatibility
Save for ImageJ
# Save in ImageJ-compatible format
tifffile.imwrite(
'for_imagej.tif',
image_stack,
imagej=True,
metadata={'axes': 'TYX', 'unit': 'um'}
)
Common Image Stack Formats
Time Series (TYX)
# Shape: (time, height, width)
time_series = tifffile.imread('recording.tif')
Z-Stack (ZYX)
# Shape: (z_planes, height, width)
z_stack = tifffile.imread('z_stack.tif')
Multi-Channel Time Series (TCYX)
# Shape: (time, channels, height, width)
multi_channel = tifffile.imread('multi_channel_recording.tif')
Installation
pixi add tifffile
# or
conda install -c conda-forge tifffile
# or
pip install tifffile
Best Practices
- Use memory-mapping (
memmap) for large files - Preserve OME-TIFF metadata when saving processed data
- Specify axes order in metadata for clarity
- Use compression (lzw, zlib) to save disk space
- Close TiffFile objects or use context managers
- Check image shape and dtype before processing
- Validate metadata extraction for your specific microscope format