Skip to main content

Eager, process-isolated reader for SlideBook .sld microscopy files via Bio-Formats, with metadata and optional napari support

Project description

sldread

Read SlideBook .sld microscopy containers in Python via Bio-Formats, with the vendor SlideBook reader jar added to the JVM classpath.

A .sld file is a proprietary container holding multiple images (captures / scenes). sldread reads a chosen scene eagerly into a NumPy array (C, Z, Y, X) together with basic metadata (scene/channel names, physical pixel sizes), and can hand a scene to napari.

Runtime dependencies are minimal: numpy + scyjava only. scyjava pulls in JPype, provisions a JVM (via cjdk) on first use, and fetches Bio-Formats from Maven. napari is an optional extra.

Why does this repo exist? (and when it should disappear)

This is not meant to be yet another microscopy reader. It exists only to work around a single, specific bug in the upstream SlideBook Bio-Formats reader:

  • The native reader (loci.formats.in.SlideBook6Reader) keeps a single, process-global file session. It is not re-entrant and not safe across the open/close/reopen and threading patterns that modern lazy I/O stacks rely on.
  • Because of this, bioio / bioio-bioformats cannot read SlideBook pixels reliably: their lazy/dask path opens short-lived helper readers and suspends/reopens the file, which trips the global session (AssertionError: File already open. / File not open.). It is fundamentally a threading / multiple-open problem, not something a wrapper can configure away.
  • The only reliable pattern is one uninterrupted setId() → openBytes() → close() session per process. sldread does exactly that, eagerly, in an isolated subprocess — nothing more.

So sldread is deliberately tiny and single-purpose. If the upstream issue is fixed — i.e. a future SlideBook reader build gives each reader an independent native session so that reopen-after-close and concurrent/threaded readers work — then this package becomes pointless and bioio should be used directly instead. At that point this repository will be archived and forgotten. Please prefer the upstream tools the moment they work. (The bug has been reported to the vendor, 3i.)

Read this first. SlideBook's native reader has a hard constraint that shapes the whole design — see Limitations. In short: a .sld file can only be read reliably in one uninterrupted reader session per process, so lazy/dask access does not work. sldread reads eagerly and isolates each read in its own subprocess.

Install

pip install sldread
# with napari support:
pip install "sldread[napari]"

Or with uv for development:

uv sync

Requires Python ≥ 3.10 (the floor set by scyjava).

The SlideBook reader jar (proprietary — not bundled)

The SlideBook6Reader.jar is proprietary and is NOT redistributed with this package. You must obtain it yourself, subject to the vendor's (3i / SlideBook) terms. sldread locates it, in order, from:

  1. the jar_path= argument (or --jar on the CLI),
  2. the SLIDEBOOK_READER_JAR environment variable,
  3. ./jars/SlideBook6Reader.jar (relative to the working directory).

A convenience downloader is provided (standard-library only, no extra deps), which fetches the pinned build from the SlideBook ImageJ update site:

sld-read download-jar            # -> ./jars/SlideBook6Reader.jar
sld-read download-jar /some/dir  # custom destination

Downloading the jar is your responsibility and governed by the vendor's licensing terms; this convenience command does not grant any rights to it.

The verified build is SlideBook6Reader.jar-20250730183505 from https://sites.imagej.net/SlideBook/jars/bio-formats/.

Usage

Library

from sldread import list_sld_scenes, read_sld_scene, sld_scene_to_napari

list_sld_scenes("file.sld")                  # -> ['undiff_WT_...', ...]

data, meta = read_sld_scene("file.sld", scene=0)
# data: numpy array, axis order (C, Z, Y, X)
# meta: scene_name, n_scenes, all_scene_names, channel_names,
#       physical_pixel_sizes {z, y, x in µm}, scale_zyx, shape, dtype,
#       dims_order, n_timepoints, timepoint

# napari (each channel becomes a layer, with physical scale on Z, Y, X):
import napari
img, kwargs, _ = sld_scene_to_napari("file.sld", scene=0)[0]
napari.view_image(img, **kwargs)

Public API:

read_sld_scene(path, scene=0, *, t=0, jar_path=None) -> (ndarray (C,Z,Y,X), dict)
list_sld_scenes(path, *, jar_path=None) -> list[str]
sld_scene_to_napari(path, scene=0, *, t=0, jar_path=None) -> napari LayerData list
napari_get_reader(path) -> reader callable or None

If sldread[napari] is installed, the .sld reader is also registered as a napari plugin (via a napari manifest), so files open through napari's File → Open.

A ready-to-run demo lives in examples/view_scene_napari.py:

uv run --extra napari python examples/view_scene_napari.py path/to/file.sld 5

Command line

sld-read list "file.sld"           # list scenes
sld-read read "file.sld" 0         # read scene 0, print a summary
sld-read read "file.sld" 0 --view  # open scene 0 in napari (needs the napari extra)
sld-read download-jar              # fetch the reader jar into ./jars

The jar is found via --jar, SLIDEBOOK_READER_JAR, or ./jars/.

Limitations (and what NOT to implement)

These come from the SlideBook native Bio-Formats reader (loci.formats.in.SlideBook6Reader), not from this code:

  • One open per process. The reader keeps a single, process-global native file session. Opening the same file a second time in one process is unreliable (intermittent AssertionError: File already open.), and closing one of two readers that have the file open deterministically breaks the other (AssertionError: File not open.). The only reliable pattern is a single, uninterrupted setId() -> openBytes()... -> close() session — which is why each read here runs in a fresh subprocess. (Reported upstream to the vendor, 3i.)
  • Eager only. Reads load a whole scene into memory (≈ C·Z·Y·X·bytes; e.g. ~99 MB for a 3×12×1200×1200 uint16 scene). Fine for typical scenes; not suitable for very large time-lapses in one shot.
  • Single timepoint by default. read_sld_scene reads t=0; pass t= for another timepoint. All Z and channels of that timepoint are read.
  • No RGB/interleaved planes. Expects one sample per plane (true for the SlideBook files seen here) and raises NotImplementedError otherwise, rather than returning wrong data.

Do not spend time on the following — they are blocked by the reader limitation above, not by missing effort:

  • Lazy / dask-backed loading of SlideBook pixels. Any access pattern that opens the file more than once per process, or keeps a reader open and reopens it later, fails non-deterministically.
  • A long-lived shared reader reused across many calls in one process.
  • Using bioio / bffile for pixel data. Their lazy pixel path opens/closes helper readers and hits the one-open-per-process limit.

If a future SlideBook build gives each reader an independent native session, these constraints can be revisited — until then, eager + process-isolated is the correct design.

Development

uv sync
uv run pytest                 # API tests run anywhere; the read test is gated
uv build                      # build sdist + wheel into dist/

The end-to-end read test is skipped unless both SLIDEBOOK_READER_JAR and SLDREAD_TEST_SLD (a sample .sld file) are set, so CI and other contributors can run the suite without proprietary data.

Publishing

uv build
uv publish                    # uploads dist/* to PyPI

uv publish accepts a token via --token / UV_PUBLISH_TOKEN, or use PyPI trusted publishing from CI (no long-lived token needed).

License

MIT (this package). The SlideBook reader jar is not covered by this license and is not distributed here.

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

sldread-0.1.0.tar.gz (12.1 kB view details)

Uploaded Source

Built Distribution

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

sldread-0.1.0-py3-none-any.whl (15.1 kB view details)

Uploaded Python 3

File details

Details for the file sldread-0.1.0.tar.gz.

File metadata

  • Download URL: sldread-0.1.0.tar.gz
  • Upload date:
  • Size: 12.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sldread-0.1.0.tar.gz
Algorithm Hash digest
SHA256 aa577e95aa6b0aa9759153c19cc2d25474a56d3efde265e0446036439697d6d3
MD5 55020d025b5aa3a4b5d64d811f995854
BLAKE2b-256 cd4cf59fc91f94623a1db9a5a928047371344dd7795d49f158d7415040f4000e

See more details on using hashes here.

Provenance

The following attestation bundles were made for sldread-0.1.0.tar.gz:

Publisher: release.yml on unige-biochem/sldread

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sldread-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sldread-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sldread-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a1c33ae1989f0953f86b9da3a7a5bb55816dfc3ba298628a8597d0e3278e8a6e
MD5 8039b1a657e5c44e71efdc25971b9a38
BLAKE2b-256 443abc9ac49a468eea1b9f88c26a03d6c31be7f711d2c24b5e11b1b31209ffa1

See more details on using hashes here.

Provenance

The following attestation bundles were made for sldread-0.1.0-py3-none-any.whl:

Publisher: release.yml on unige-biochem/sldread

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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