Read and browse nested images in Leica LIF, LOF, and XLEF files
Project description
ConvertLeica-Docker
ConvertLeica-Docker is a toolset and web interface for converting Leica LIF, LOF, and XLEF microscopy image files to OME-TIFF or OME-Zarr, with special handling for certain file types and image configurations. It is designed for command-line, web-based, and Qt desktop workflows, supporting batch conversion and interactive browsing/conversion of large microscopy datasets.
The reusable Leica file-browser modules are also distributed separately as
convertleica-file-browser. This lets Python applications consume the readers
without copying source files from this repository:
pip install convertleica-file-browser
from convertleica_file_browser.ci_leica_converters_helpers import read_leica_file
contents_json = read_leica_file("example.lif")
Preview generation additionally needs OpenCV and can be installed with
pip install "convertleica-file-browser[preview]".
Package versions are derived from this repository's Git tags. Publishing a GitHub Release builds and publishes the matching wheel and source distribution to PyPI, alongside the Docker image release workflow.
Before the first release, configure a PyPI Trusted Publisher with owner
NL-BioImaging, repository ConvertLeica-Docker, workflow
publish-to-pypi.yml, and GitHub environment pypi. Create the matching
GitHub environment and protect it with required reviewer approval. No PyPI API
token is needed.
Table of Contents
- ConvertLeica-Docker
Features
- Convert Leica LIF, LOF, and XLEF files to OME-TIFF or OME-Zarr (multi-channel, multi-Z, RGB, tilescans, etc.)
- Automatic handling of special cases: returns .LOF or single-image .LIF files when OME-TIFF is not appropriate
- Batch and single-image conversion
- Web interface and Qt desktop GUI for browsing, previewing, and converting files
- Progress reporting and metadata inspection
- Robust file saving: Uses a temp-first approach with automatic retry logic for reliable saving to network drives
- Dual progress bars: Separate progress indicators for data processing and file saving phases
Installation
Requirements
- Python 3.13
- pip
- (Optional) Docker for containerized usage
Python packages
Different requirements files are provided for different scenarios:
requirements-docker.txt— Core dependencies for Docker container (numpy, tifffile, imagecodecs, opencv-python)requirements-server.txt— For running the web server (same core deps; server uses stdlib only)requirements-qt6ui.txt— For running Qt6 desktop GUIs (core deps + PyQt6)
Core packages (all scenarios):
- numpy>=2.0.0
- tifffile>=2024.1.30
- imagecodecs>=2024.1.1
- opencv-python==4.13.0.90
- numcodecs>=0.12
- zarr>=3.0.0
Qt Desktop GUI
The desktop application can be launched directly:
python ConvertLeicaQT.py
python ConvertLeicaQT.py --debug
- The GUI always converts the selected image; there is no LOF/XLEF size-threshold toggle in the desktop app.
- Use the
Convert to:row to chooseOME-TIFForOME-Zarr. --debugshows theFolder JSONandImage JSONbuttons for raw metadata inspection.
Install with:
# For Docker/CLI usage:
pip install -r requirements-docker.txt
# For web server:
pip install -r requirements-server.txt
# For Qt6 GUI applications:
pip install -r requirements-qt6ui.txt
(Optional) Build and run with Docker
# Build the Docker image
# (from the root of this repository)
docker build -t convertleica-docker .
# Run the container, mounting your data directory
# (replace L:/data with your data path)
docker run --rm -v "L:/data:/data" convertleica-docker --inputfile /data/myfile.lif --outputfolder /data/.processed
# With custom temp folder (useful when output is on a slow network mount)
docker run --rm \
-v "L:/data:/data" \
-v "/tmp/leica:/temp" \
convertleica-docker \
--inputfile /data/myfile.lif \
--outputfolder /data/.processed \
--tempfolder /temp \
--show_progress
Usage (Command Line)
Basic Command
python main.py --inputfile <path-to-LIF/LOF/XLEF> --outputfolder <output-folder> [--image_uuid <uuid>] [--show_progress] [--altoutputfolder <alt-folder>] [--xy_check_value <int>]
Arguments
--inputfile(required): Path to the input Leica file (.lif, .lof, .xlef)--outputfolder(required): Output directory for converted files--image_uuid: UUID of the image to extract (for multi-image files)--show_progress: Show progress bar during conversion--altoutputfolder: Optional second output directory--tempfolder: Custom temp folder for intermediate files (useful for Docker or network scenarios). If not set, uses system temp directory.--xy_check_value: XY size threshold for special handling (default: 3192)--get_image_metadata: Also include full image metadata JSON in the result underkeyvalues.image_metadata_json--get_image_xml: Also include the raw image XML (when available) underkeyvalues.image_xml
Inputs
- LIF: Leica Image File (may contain multiple images, folders, tilescans, etc.)
- LOF: Leica Object File (single image, often exported from LIF)
- XLEF: Leica Experiment File (may reference multiple images, often RGB)
List nested image IDs
Use extract_nested_leica_items to enumerate every image before submitting
individual conversion jobs. It expands nested LIF and XLEF folders lazily and
also supports single-image LOF files and legacy SP5 MemoryBlockID values.
from ci_leica_converters_helpers import extract_nested_leica_items
images = extract_nested_leica_items("/data/experiment.lif")
for image in images:
print(image["uuid"], image["name"])
Each result has the import-compatible shape introduced by OMERO.biomero:
{
"localPath": "/data/experiment.lif",
"uuid": "image-or-memory-block-id",
"name": "Image name"
}
Outputs
- OME-TIFF: Standard output for most images (multi-channel, multi-Z, tiled, etc.)
- .LOF: Returned for certain LOF files or when conversion to OME-TIFF is not needed
- Single-image .LIF: Returned for special cases (e.g., negative overlap tilescans)
Function Output Format
The function returns a JSON array string describing the conversion result(s). Each element has:
name: base name of the created or relevant file (without extension)full_path: absolute path to the output file (OME-TIFF, .LOF, or .LIF)alt_path: absolute path to the file inaltoutputfolder(if used and file exists), elsenullkeyvalues: a single-item list with a dictionary containing per-channel intensity stats and optional metadata
Per-channel intensity stats (always present when readable):
channel_mins: list[int] per channel, minimum pixel value observed (container units)channel_maxs: list[int] per channel, maximum pixel value observed (container units)channel_display_black_values: list[int] per channel, display black levels scaled to the container rangechannel_display_white_values: list[int] per channel, display white levels scaled to the container range
Optional metadata fields (included only when flags are used):
image_metadata_json: full parsed image metadata JSON (when--get_image_metadata)image_xml: raw image XML string if available, else empty string (when--get_image_xml)
If no conversion is applicable or an error occurs, an empty JSON array string ([]) is returned.
Example result:
[
{
"name": "Swiss Rolls GM1748 LEX277AD",
"full_path": "L:/Archief/active/cellular_imaging/OMERO_test/Leica-LIF/.processed/Swiss Rolls GM1748 LEX277AD.ome.tiff",
"alt_path": "U:/cc/Swiss Rolls GM1748 LEX277AD.ome.tiff",
"keyvalues": [
{
"channel_mins": [1097, 2257, 335, 175],
"channel_maxs": [7423, 5907, 10261, 3716],
"channel_display_black_values": [1179, 2357, 372, 202],
"channel_display_white_values": [6798, 5641, 7002, 2969]
},
"experiment_name": "Cells in mouse brain",
"experiment_date": "2025-05-01"
]
}
]
You can parse this output in Python using json.loads() to access the result programmatically.
Conversion Scenarios
- LIF file: RGB and multi-channel images are converted to OME-TIFF. If the image is a tilescan with negative overlap, a single-image .LIF is returned instead.
- LOF file: RGB and multi-channel images are converted to OME-TIFF. If not needed, the original .LOF is returned.
- XLEF file: RGB and multi-channel images are converted to OME-TIFF. Special cases (e.g., negative overlap or unsupported structure) may return the original LOF file.
WSL/Windows Example Usage
See Tests/test_convertleica.py and Tests/test_ometiff_RGB.py for real-world examples:
lif_file_path = 'L:/Archief/active/cellular_imaging/OMERO_test/Leica-LIF/Swiss Rolls GM1748 LEX277AD.lif'
image_uuid = "ad7b9384-0466-11e9-8a36-8cec4b8a9866"
outputfolder = 'L:/Archief/active/cellular_imaging/OMERO_test/Leica-LIF/.processed'
altoutputfolder = 'U:/cc'
status = convert_leica(
inputfile=lif_file_path,
image_uuid=image_uuid,
show_progress=True,
outputfolder=outputfolder,
altoutputfolder=altoutputfolder
)
print(status)
Special Cases
- Tilescan with Negative Overlap (LIF): Instead of OME-TIFF, a single-image .LIF is returned
- LOF/XLEF: If conversion is not needed, the original LOF file is returned
Robust File Saving
The converter uses a temp-first approach for reliable saving to network-mounted drives:
- Save to temp: The TIFF is first written to a local temp folder (system temp or custom
--tempfolder) - Copy with verification: The file is copied to the destination with size verification
- Automatic retry: On failure, retries up to 10 times with progressive backoff (1 min, 2 min, ... 10 min)
- Alt folder support: If
--altoutputfolderis specified, the file is also copied there from temp - Cleanup: The temp file is removed only after all copies succeed
This prevents corrupted or partial files on unreliable network connections.
Progress Indicators
When --show_progress is enabled, two distinct progress bars are shown:
Converting to OME-TIFF: |██████████████████████████████████████████████████| 100.0% Processing complete
Saving: <▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓> 100.0% - Copying to output
- Processing bar (
|███|): Data reading, stitching, and tiled-pyramid creation (0-100%) - Saving bar (
<▓▓▓>): Verified copying to the requested output locations (0-100%)
Troubleshooting
- Ensure all dependencies are installed (
pip install -r requirements-docker.txtfor CLI/Docker) - For Docker, ensure your data directory is mounted correctly
- For large files, ensure sufficient disk space and memory
- If you encounter errors, check the console output for details
License
Apache License 2.0 — see LICENSE.
References
More documentation
- Server.md — Web server and website documentation, including progressive preview and disk cache behavior, endpoints, and client flow.
- ConvertLeicaQT.md — Desktop Qt GUI documentation with browsing, progressive previews (cache parity with server), and conversion workflow.
- LeicaViewerQT.md — A lightweight Qt desktop image viewer focused on Leica LIF/LOF/XLEF browsing and quick previewing.
- tools/omero_import_metadata_probe/README.md — Generate tiled/pyramidal TIFF and Zarr fixtures and verify their OMERO/BIOMERO imports.
Note: Requires the same Python dependencies as the converter (see requirements).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file convertleica_file_browser-1.7.3.tar.gz.
File metadata
- Download URL: convertleica_file_browser-1.7.3.tar.gz
- Upload date:
- Size: 56.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c011b7ad8507d96784344d8875595e417e1af039ddd6a43cab84b61665aa7b1
|
|
| MD5 |
73aa6e30151000858ea0c3eadd8e68b6
|
|
| BLAKE2b-256 |
16f339ef77c9c6da2748b8ea16276031ec7c81d8dba7f330d4844c918f952412
|
Provenance
The following attestation bundles were made for convertleica_file_browser-1.7.3.tar.gz:
Publisher:
publish-to-pypi.yml on NL-BioImaging/ConvertLeica-Docker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
convertleica_file_browser-1.7.3.tar.gz -
Subject digest:
5c011b7ad8507d96784344d8875595e417e1af039ddd6a43cab84b61665aa7b1 - Sigstore transparency entry: 2205691231
- Sigstore integration time:
-
Permalink:
NL-BioImaging/ConvertLeica-Docker@c438953fd00e118a2012294db55efd895f10259c -
Branch / Tag:
refs/tags/v1.7.3 - Owner: https://github.com/NL-BioImaging
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@c438953fd00e118a2012294db55efd895f10259c -
Trigger Event:
release
-
Statement type:
File details
Details for the file convertleica_file_browser-1.7.3-py3-none-any.whl.
File metadata
- Download URL: convertleica_file_browser-1.7.3-py3-none-any.whl
- Upload date:
- Size: 58.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f346deea2622a66fdf64524c69200342315a0e449a8b9999dc29189ad133c024
|
|
| MD5 |
d48bf05156fa215bd8060f115c48ce76
|
|
| BLAKE2b-256 |
aff7a46995863e99de0debaad0ab92542bb56e695226e6a50781efbee73e3a8f
|
Provenance
The following attestation bundles were made for convertleica_file_browser-1.7.3-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on NL-BioImaging/ConvertLeica-Docker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
convertleica_file_browser-1.7.3-py3-none-any.whl -
Subject digest:
f346deea2622a66fdf64524c69200342315a0e449a8b9999dc29189ad133c024 - Sigstore transparency entry: 2205691609
- Sigstore integration time:
-
Permalink:
NL-BioImaging/ConvertLeica-Docker@c438953fd00e118a2012294db55efd895f10259c -
Branch / Tag:
refs/tags/v1.7.3 - Owner: https://github.com/NL-BioImaging
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@c438953fd00e118a2012294db55efd895f10259c -
Trigger Event:
release
-
Statement type: