Shallow Zarr storage
Shallow storage removes duplicate image or label arrays from returned OME-Zarr results and refers to verified canonical pixels already in managed storage. New or changed arrays remain in the result. The importer still registers the result in OMERO and attaches its provenance, even when all image pixels match the input. Canonical inputs are never pruned.
BIOMERO.shallower provides the shared shallowing implementation. The importer runs that library locally or validates results shallowed on Slurm. See the shallower guide for supported formats, filesystem requirements and standalone CLI use, and the architecture guide for transactions and recovery.
Enable shallow imports
Install biomero-importer[identity] and set BIOMERO_SHALLOW_ZARR=true in
the importer service and in processes that submit shallow orders. The
NL-BIOMERO importer container includes the identity dependencies. Restart the
service after changing its environment or package installation.
The feature is off when the flag is absent or false. Enabling it advertises
the biomero.shallow-zarr capability; it does not turn ordinary uploads
into shallow imports. An order must explicitly request the operation and
provide the trusted canonical-input manifest for its workflow.
Within an enabled operation, usable RO-Crate output declarations take
precedence, followed by the workflow's saved original_pixels_not_required
setting. Both routes reuse the known source without measuring original pixels
again. Otherwise the shared shallower compares decoded pixels at the coarsest
compatible pyramid level; labels retain full-resolution comparison. Full-image
shape, axes, dtype and coordinate guards still apply. Missing or stale comparison
metadata is refreshed from the same canonical backing store when needed; no
source export, copy or reimport is required. Fresh OMERO exports retain their
separate full-resolution correctness check.
Remote helpers without a current source comparison cache keep full results for
local evaluation against managed canonical storage. A mutable HPC input copy
cannot refresh that authoritative cache.
The calling process can check get_importer_capabilities() before submitting
an order. This describes that process's installed dependencies and environment;
it does not query a remote importer service. Keep their configuration aligned.
Choose where shallowing runs
| Route | Shallowing | Importer responsibility |
|---|---|---|
| Local | Importer runs the shared shallower library after preprocessing | Compare identities, shallow, resolve sources and register results |
| Remote | BIOMERO runs the shallower container on Slurm before result archiving and transfer | Validate receipts and retained data, resolve sources and register results |
Within enabled shallow workflows, remote shallowing is preferred. To use
the local path, set BIOMERO_REMOTE_SHALLOW_ZARR=false on both the workflow
worker and importer. This avoids the additional Slurm shallowing job but
transfers full results and performs shallowing on the importer host.
BIOMERO_SHALLOW_ZARR_WORKERS controls local identity parallelism; choose it
for the host's CPU and storage capacity.
For remote shallowing, enable BIOMERO_REMOTE_SHALLOW_ZARR and configure
BIOMERO_REMOTE_SHALLOWER_IMAGE and BIOMERO_REMOTE_SHALLOWER_VERSION
identically on the workflow worker and importer. Select the container from
the shallower releases
and use the Python package version reported by that container's
biomero-shallower --version. Docker tag spelling and Python version spelling
can differ for prereleases. Dependency compatibility is maintained in
pyproject.toml, not in this guide.
The importer does not submit or download the Slurm helper. Image acquisition, initialization and worker configuration are described in the NL-BIOMERO remote-shallower guide.
Submit a local shallow order
BIOMERO result scripts construct these orders automatically. Other integrations
can submit them through the importer API. They need an existing, trusted
CanonicalInputManifest: source identities, generations and managed-storage
references must describe the actual canonical inputs. Do not construct this
manifest from untrusted result metadata or use an empty manifest as a shortcut.
Given a normal upload-order dictionary order and that manifest:
from biomero_importer import get_importer_capabilities, submit_import_order
from biomero_schema.imports import ImportOptionsEnvelope, ShallowZarrImportOperation
capabilities = get_importer_capabilities()
if "biomero.shallow-zarr" not in capabilities["lifecycleOperations"]:
raise RuntimeError(capabilities["configurationErrors"] or "Shallow imports disabled")
order["ImportOptions"] = ImportOptionsEnvelope(
operations=(ShallowZarrImportOperation(canonicalInputs=canonical_manifest),)
).to_dict()
order_uuid = submit_import_order(order)
See import orders for required order fields and the schema documentation for the canonical-input and operation contracts. The operation runs after external preprocessing and before OMERO registration, so it can consume an existing Zarr or a Zarr produced by a converter. Orders with no operation retain their existing behavior.
Import remotely shallowed results
The workflow's import order additionally supplies remoteReceipts from its
completed shallower task. The importer validates the report checksum,
configured image and tool version, canonical snapshot, task and job IDs,
shallow manifest and retained structure. A matching receipt avoids repeating
pixel hashing and shallowing. Local source resolution and OMERO
registration still take place in the importer.
A remote result cannot be accepted merely because its archive contains a report. Missing trusted receipts, mismatched versions, tampering and unresolved canonical sources cause an error. A trusted kept-full receipt can also refresh canonical comparison metadata without repeating an unsuccessful comparison. Full results without such a receipt can use local shallowing. A corrupt or incomplete shallow result is not silently treated as a full Zarr.
Canonical storage must remain available through the configured shared mounts and storage mappings. Deleting or moving the canonical arrays breaks results that reference them. See storage and preprocessing.
Interrupted imports and recovery
Recovery is automatic within an explicitly requested shallow lifecycle operation
and needs no additional feature flag. BIOMERO_SHALLOW_ZARR=true is still
required; disabled shallow operations are rejected before locking or recovery.
Remote receipts also require BIOMERO_REMOTE_SHALLOW_ZARR to remain enabled.
Ordinary imports without a lifecycle operation are unaffected, even when shallow
storage is enabled. Before inspecting a shallow result,
the importer obtains the shared
shallower filesystem lock and recovers any interrupted prune journal. Recovery
restores uncommitted pixel moves and metadata before evaluating the store or
reusing its shallow manifest. The same path applies to v2 and v3. The lock remains
held through normalization and registration-plan preparation; it is released if
the process dies. Recovery storage must provide working shared filesystem locks
and the shallower's atomic move and synchronization requirements.
An explicit unsupported-lock error uses legacy preparation with a warning, provided no interrupted prune journal exists. This retains the existing normalization behavior without adding recovery or concurrency protection. Busy locks, permissions, storage errors and failures during recovery or normalization do not trigger this fallback. Interrupted transactions still require working locks before preparation can continue.
A busy store, conflicting journal or incomplete recovery fails preparation.
The importer does not register the incomplete store or reinterpret it as a full
result. Keep the result and its sibling .biomero-prune-* journal for diagnosis;
do not delete the journal to bypass recovery. Symlinked result roots are rejected.
Resolve an interrupted journal on storage supporting recovery before retrying.
There is no migration or scan of old OMERO images, Plates or Zarrs. The scripts' small recovery record belongs to a newly staged workflow-result import plan, not each image; historical data is considered only when explicitly retried.
Filesystem recovery is separate from OMERO registration. An order can fail after registering some of its objects, and startup marks interrupted orders failed. Review the order's log and registered objects before issuing a replacement. Import provenance is mandatory: a file is successful only after its registered objects have the import-order annotation. Sessions stay alive through registration and postprocessing. If annotation access fails, the importer makes up to three annotation-only attempts, reconnecting as the original user in the original group and reusing the exact registered IDs. A write whose response was lost is accepted only after all expected provenance fields are found on the linked annotation. Conflicting or incomplete provenance fails the import.
If these attempts fail, the order is marked failed and its description records the registered object type and IDs. Preserve that event and repair those objects; do not rerun registration to repair annotations. This bounded metadata recovery does not make arbitrary resubmission of a failed or interrupted order safe. These changes do not automatically requeue failed orders or guarantee exactly one registration for arbitrary external clients that submit duplicate orders. BIOMERO result scripts use a saved order plan to resume polling existing orders. Before creating a plan they test the new durable-write requirements using disposable metadata. Unsupported file synchronization, atomic replacement or POSIX directory synchronization selects legacy order submission before any import is queued. A saved plan cannot be bypassed through this fallback. The importer's existing normalization write requirements are unchanged.
Image and Plate registration
An eligible Image result registers its shallow collection root as the primary
OMERO Image. Its PixelBuffer uses the canonical source pixels and its shallow
reference exposes the result labels to label-aware viewers. When
importImageLabelViews is enabled, the importer also registers lightweight
label projections so TIFF-based workflows can select and export an individual
mask without copying its arrays.
The default Plate registration uses canonical source pixels while preserving
the result's Plate, Well and WellSample hierarchy. The optional
platePixelSource="label" and plateLabelName registration options create a
label-backed Plate view without copying arrays. The selected label must exist
on every image; incomplete selections fail instead of substituting a label.
Label image names and display
Imported label images include their source store and, for nested images, their
field or series path. For example, result.ome.zarr/labels/labels_cells becomes
result_labels_cells; plate.zarr/A/1/0/labels/cells becomes
plate_A_1_0_cells. This changes the OMERO name only.
The importer preserves valid omero.channels[].window settings on the label
group itself. Missing channel activation and colour settings default to active
and white. It does not copy contrast settings from the source intensity image.
When a label window is missing or invalid, the importer reads the
full-resolution label array one storage chunk at a time and saves a window
from zero to its maximum ID in OMERO. All-background masks use 0–1. Label IDs,
array types and Zarr metadata remain unchanged.
This fallback adds a full label-array read during import; its working memory depends on storage chunk size. Producers can avoid that scan by writing valid display windows on each label group, for example:
{
"omero": {
"channels": [{
"label": "Cells",
"active": true,
"color": "FFFFFF",
"window": {"min": 0, "max": 4294967295, "start": 0, "end": 407272}
}]
}
}
Use the actual maximum label ID, not the number of objects or a reduced
pyramid's maximum. For OME-Zarr 0.5 this metadata belongs under the group's
ome attribute; see the OME-Zarr specification.
Existing imported images keep their saved names and rendering settings.
Provenance
Input .biomero-input.json markers disambiguate renamed results with identical
pixels. They must match the operation's canonical manifest and are consumed
before registration. Local shallowing still verifies returned pixels.
The importer records the actual storage outcome in
.biomero-import-storage.json beside the result. Local shallowing records
the executing library version. Accepted remote receipts also record the helper
container, task/job IDs and report checksum. Full-Zarr fallbacks are recorded
as full storage. BIOMERO result scripts use this data for the compact OMERO
storage-provenance view without hashing pixels again. Historical shallow stores
without an outcome receipt do not acquire an inferred execution version.