Skip to content

Fix CV7000 sparse acquisition series and metadata handling#4450

Open
Darlokt wants to merge 45 commits into
ome:developfrom
Darlokt:cv7000-reader-fix
Open

Fix CV7000 sparse acquisition series and metadata handling#4450
Darlokt wants to merge 45 commits into
ome:developfrom
Darlokt:cv7000-reader-fix

Conversation

@Darlokt

@Darlokt Darlokt commented Jul 2, 2026

Copy link
Copy Markdown

Hej everyone,

I was doing some conversions of some CV7000 data and found some weird behavior in the metadata construction etc. related to sparse acquisitions and timeline/action-specific channel metadata.

The reader previously assumed dense well/field layouts and often derived metadata from fixed plane positions, which broke when datasets had missing TIFFs, skipped fields, or timeline-specific channel instances.
The changes make series allocation, plane lookup, SPW metadata, channel metadata, physical pixel sizes, and missing-plane handling derive from actually acquired/readable planes where appropriate, while preserving parsed metadata-only plane records for fallbacks.

Problems Found

  • CV7000 sparse acquisitions were expanded as if every acquired well contained every field up to the global maximum field index. This created extra series for fields that were never acquired.
  • Missing TIFF planes could be treated as normal backing planes during metadata lookup. That caused WellSample positions and other per-plane metadata to be populated from planes without actual pixel data.
  • Channel metadata lookup assumed that the first logical plane for a channel existed. In sparse datasets, channel 0 or the expected first plane may be absent, so objective, exposure, color, light source, and physical pixel metadata could be skipped or attached incorrectly.
  • Timeline/action-specific channel instances were created before the global ChannelList metadata was parsed. Exact channel matching by raw channel plus timeline/action then found instances that existed but did not yet contain optical metadata.
  • Missing-plane duplication was enabled by default, which could silently duplicate neighboring planes instead of returning fill pixels for absent image data creating false data.
  • Duplicate logical plane slots could prefer metadata-only records over later TIFF-backed records.

Fixes

  • Series are now built only from acquired well/field pairs that have readable TIFF planes. This prevents creation of empty field series for sparse acquisitions.
  • SPW metadata now emits Image, WellSample, and PlateAcquisition references only for acquired fields, using compact per-well sample indexes.
  • PlateAcquisition MaximumFieldCount is now computed from the maximum number of acquired fields per well, not from the global maximum field index.
  • Missing-plane duplication is now opt-in by default. Missing planes return fill pixels unless cv7000.duplicate_missing_planes is explicitly enabled.
  • Plane lookup now prefers TIFF-backed planes where pixel data is required, such as WellSample position metadata and duplicate-plane reads.
  • Per-plane parsed metadata is still preserved for mapped MLF IMG records even when the referenced TIFF is missing, allowing logical missing planes to retain their own X/Y/Z metadata where useful.
  • Channel metadata is now populated from representative planes instead of assuming fixed plane indexes exist. TIFF-backed planes are preferred, with metadata-only planes used as fallback when needed.
  • Physical pixel sizes are set from the first channel in a series that has resolvable backed channel metadata, instead of requiring channel 0 to be present.
  • Channel lookup now matches exact raw channel plus timeline/action first, then falls back to raw-channel metadata when needed.
  • ChannelList settings are propagated to all timeline/action channel instances with the same raw channel index, restoring objective, exposure, color, fluorophore, excitation, and light source metadata across timeline-specific channels.
  • Light source references are added to all matching channel instances without duplicates, and duplicated channels now deep-copy light source reference lists to avoid accidental shared mutable state.

I had a bit of a problem with plane duplication being enabled by default. According to 5cd0ea5 this was added a a better visualization option, but left enabled by default. From where I stand, the default behavior should never create false data.
I did a small top level search throughout and also found similar behavior in the InCell reader. If you want I can also revert this behavior there to disabled by default.

After the fixes, on my test data, the conversion now creates the proper number of files associated with the actual number of planes captured as described by the Yokogawa metadata with correctly populated metadata.

All the best!
Kilian

Darlokt added 5 commits July 1, 2026 21:45
Build CV7000 series from acquired well/field pairs with readable TIFF
planes instead of expanding every acquired well to the global maximum field
index. Update SPW metadata to emit Image, WellSample, and PlateAcquisition
references only for acquired fields, using compact per-well sample indexes.

Set PlateAcquisition MaximumFieldCount from the maximum acquired field count
per well, and make missing-plane duplication opt-in so missing planes return
fill pixels by default.
Populate channel and objective metadata from representative real planes instead
of assuming the first plane index for each channel is present. Match channels
by raw channel plus timeline/action, falling back to raw channel only when
unambiguous.
Skip plane position metadata for missing planes so positions are only written
for real backed planes.
Populate WellSample positions only from TIFF-backed planes, avoiding metadata-only missing planes in sparse acquisitions. Set per-series physical pixel sizes from the first backed channel with resolvable channel metadata instead of requiring channel 0 to be present.
Preserve per-plane position metadata for mapped MLF IMG records even when the
referenced TIFF is missing, so dense logical planes with fill pixels keep their
own parsed X/Y/Z coordinates.
When resolving representative planes for channel metadata, prefer TIFF-backed
planes but fall back to metadata-only planes for the same channel if no backed
plane is available.
Recent sparse CV7000 fixes changed per-series metadata lookup to match
channels by raw channel plus timeline/action. That preserved channel
ordering for sparse acquisitions, but exposed a parser ordering issue:
timeline/action channel instances are created while parsing Timelapse,
before ChannelList is parsed. As a result, exact matches for later
timelines resolved to channel instances without objective, exposure,
color, or light source metadata.

Propagate ChannelList settings to every channel instance with the same
raw channel index, and add light source references to all matching
instances without duplicates. Keep exact timeline/action lookup first,
but let raw-channel fallback prefer a populated channel if exact lookup
is unavailable. Deep-copy light source references when duplicating
channels so later updates do not share mutable state accidentally.

This keeps the sparse acquired-field series allocation intact while
restoring optical metadata for all timeline/action channel occurrences.
@melissalinkert

Copy link
Copy Markdown
Member

Thanks, @Darlokt. Before we can consider including this, we do need:

See also https://ome-contributing.readthedocs.io/en/latest/code-contributions.html#procedure-for-accepting-code-contributions. Please let us know when both the CLA and test data have been submitted.

@Darlokt

Darlokt commented Jul 2, 2026

Copy link
Copy Markdown
Author

Thanks @melissalinkert, the CLA is signed!
I am unable to provide test data, as the data can not be shared and the microscope is not one of mine, so I can not create a new test dataset. If it is helpful, I can try to do a more detailed write up on the conflicts this resolves, as it mostly changes the interpretation of the existing metadata files/tightens the integration with the metadata files instead of inferring state?

@melissalinkert

Copy link
Copy Markdown
Member

I haven't been able to find a record of the CLA being submitted. Can you please double-check that it was submitted as instructed at https://ome-contributing.readthedocs.io/en/latest/cla.html?

We really do need a test case of some sort that both demonstrates why these changes are necessary and can be included in our test data repository in the future. Would you be able to replace the images in your test datasets with something artificial (see https://bio-formats.readthedocs.io/en/latest/developers/generating-test-images.html), and submit the modified dataset?

@Darlokt

Darlokt commented Jul 2, 2026

Copy link
Copy Markdown
Author

I double checked, it was send to the correct address, but I can send it again?

I can try to make a minimal synthetic test set, but I cant say its going to be correct, as I don't have the microscope to double check. It mostly boils down to .mrf vs .mlf mismatch and when compensating for that the downstream things that break. I can try to write a minimal test set based in this?

Darlokt added 4 commits July 2, 2026 19:44
Use Yokogawa MES bts:SliceLength as the physical Z spacing in micrometers, based on the CV7000 metadata and observed MLF Z positions. Parse the value from acquire actions and attach it to the mapped timeline/action channel metadata.
Set PixelsPhysicalSizeZ when all represented channels in a series agree on the same slice length. Leave it unset for missing or conflicting slice length metadata, and keep per-plane Z positions written in the existing reference-frame units.
Use Yokogawa MES light-source links as channel excitation metadata and treat Acquisition filter labels as detection filters. Populate emission wavelengths for band-pass filters, create OME Filter and LightPath emission filter references, and add support for BP, LP, and SP filter ranges.
Create Detector metadata from Yokogawa camera numbers and link per-channel DetectorSettings with binning. Preserve ambiguous gain, lamp, filter, and camera provenance as OriginalMetadata while leaving brightfield lamp channels unmapped to core OME light sources.
Split CV7000 initialization into explicit dataset path, sidecar parsing, series layout, plane lookup, and metadata population phases. Track series timing from measurement planes and populate per-image acquisition dates and plane delta times from Yokogawa timestamps.

Preserve Yokogawa sidecar provenance as OriginalMetadata, including MRF, MES, WPP, channel action settings, measurement summaries, and chunked raw XML with SHA-256 digests. Add structured objective, acquisition mode, contrast method, detector, binning, light path, and filter metadata population on top of the refactored reader layout.
Normalize Yokogawa decimal-comma numeric values before parsing CV7000 sidecar floats, including plane positions, pixel sizes, light source settings, exposure times, filter wavelengths, and Z spacing. Parse Andor gain parameters into DetectorSettings.Gain while retaining the original Andor parameter fields as provenance.
@Darlokt
Darlokt force-pushed the cv7000-reader-fix branch from e1e4d5d to a22966b Compare July 2, 2026 22:01
Darlokt added 4 commits July 3, 2026 00:18
After checking DataTools.parseDouble does everything needed, the wrapper was unnecessary and redundant.
Preserve `PostProcess.ppf` as raw CV7000 sidecar XML and parse lightweight PostProcess summary/action metadata while leaving verbose logs unexpanded. Keep OME `PhysicalSizeZ` limited to shared positive channel Z spacing, with per-channel Z offsets represented through per-plane `PositionZ` to account for per channel differing z spacing.
Restrict CV7000 dataset sidecar discovery to the declared acquisition files plus known Yokogawa sidecars, including PostProcess.ppf, OTF_crosstalk_parameter.xml, and OTF_geometry_parameter.xml.
Avoid adding unrelated XML files such as generated OME-XML metadata while preserving raw metadata for recognized sidecars and treating both .tif and .tiff as pixel files.
Parse OTF_crosstalk_parameter.xml from the .wpi directory to populate exact emission filter ranges, transmittance, and single-dichroic light path references for matching CV7000 channels. Preserve crosstalk filter, dichroic, fluorophore, and intensity values as Yokogawa original metadata while distinguishing filters by camera number.

Classify CV7000 companion files by dataset role so no-pixels file lists exclude TIFF planes consistently and known Yokogawa sidecars are matched by resolved dataset paths instead of recursive basename discovery.

Preserve raw XML only for explicit sidecar roles, leaving MeasurementData.mlf and parsed PostProcess.ppf out of the raw XML dump while retaining their structured original metadata.
@melissalinkert

Copy link
Copy Markdown
Member

Thanks @Darlokt, I confirm we have received your CLA (it just took a while to appear). Yes, please do write relevant tests that cover all of the changes in this pull request. This is a large set of changes to an established reader, so we need concrete tests to understand what wasn't working previously.

If looks like you're still actively working on this, so I would ask that you please convert this pull request to a Draft until you are done pushing commits (and then click Ready to review when you're done).

@Darlokt
Darlokt marked this pull request as draft July 3, 2026 14:49
Darlokt added 10 commits July 3, 2026 19:45
Set CV7000 plate well origins to zero and store MLF field X/Y values as micrometer well-sample offsets instead of reference-frame coordinates. Treat those positions as well-center-relative field offsets because the sidecar ranges fit inside the WPP well geometry only when interpreted as micrometers.

Stop writing per-plane X/Y positions from the same field offsets, leaving them on WellSample where they describe the acquisition field. Store MLF Z positions as micrometer AF-relative stack coordinates rather than generic reference-frame positions.
Store CV7000 MLF Z values as per-plane reference-frame coordinates instead of micrometer stage positions. Keep calibrated Z spacing on Pixels.PhysicalSizeZ when available, since MLF Z is AF-relative and not proven absolute stage Z.
Set OME plate row and column naming conventions for CV7000 datasets, record well-sample timepoints alongside image acquisition dates, and replace generic channel names with display labels derived from brightfield mode, target, and acquisition metadata. Preserve the original action/channel/camera identifiers as channel provenance metadata so the raw CV7000 source mapping remains available
Replace chunked global raw-XML metadata with structured CV7000 MapAnnotations plus raw sidecar FileAnnotations. Summarize sidecars with role, byte length, and SHA-256, link scoped annotations to plate, instrument, image, and channel objects, and keep large XML payloads attached as binary annotations instead of split base64 metadata.
Split CV7000Reader’s transient parsing, layout, and original-metadata bookkeeping into dedicated reader-local model/helper classes. Centralize dataset paths, raw sidecar state, acquired-well/field indexes, representative-plane lookup, and shared Yokogawa parsing utilities so metadata population can reuse indexed state instead of rescanning planes or duplicating string-parsing logic.
Record non-laser CV7000 illumination in OME metadata instead of only emitting laser-backed channel settings. Map brightfield channels to lamp light sources, write lamp entries as halogen filaments, and keep laser excitation wavelengths limited to true laser sources.

Also improve related instrument metadata by normalizing Andor camera handling and preserving Yokogawa filter-wheel labels on generated filters.
Map CV7000 white-light sources to OME FilamentType=Other instead of Halogen. The manual describes a halogen lamp, but MES sidecars expose only generic Type="Lamp" and installed hardware may differ, so the reader should avoid asserting a more specific filament type than the source metadata supports.
Add a cv7000.preserve_raw_sidecars metadata option and keep raw CV7000 sidecars attached as file annotations unless callers explicitly disable it. Also clean up parser helper usage, guard sidecar handling against null entries to avoid a possible null pointer, and remove the unused well-acquisition helper while keeping the default metadata output unchanged.
Parse the CV7000 OTF geometry sidecar and use it to populate objective records, including inferred nominal magnification, lens NA, and immersion when channel metadata alone is incomplete.
Also enrich promoted optics metadata with laser model/type, lamp power, channel illumination/acquisition/contrast fields based on information form there and the CV7000 user manual, and preserve matched OTF geometry affine rows in original metadata for auditability.
Darlokt added 12 commits July 4, 2026 11:05
Map MRF target system values onto the OME microscope model with Yokogawa as the manufacturer. Preserve the cleaned operator name as an Experimenter and link it from each image, while continuing to warn on non-CV7000 target systems.
Track duplicate-plane selection while building CV7000 plane lookups and publish per-image provenance summaries in Yokogawa original metadata. Annotate TIFF-backed, metadata-only, duplicated, filled, and missing-MLF planes so sparse acquisitions and ignored duplicate candidates remain auditable from the reader output.
Parse observed CV7000 objective names into magnification, immersion, phase, and long-working-distance tokens, then map known combinations to nominal magnification and lens NA when populating OME metadata. Refactor sidecar parsing into typed result objects, tighten helper visibility, and stream sidecar SHA-256/length summaries instead of buffering full files.
Reorganize `CV7000Reader` into clearer functional modules, extract shared channel-mapping and SAX parsing helpers, and centralize attribute cleanup through `YokogawaParsing`. Reset all parsed reader state when reopening datasets on a reused reader so CV7000 sidecar, channel, and OTF metadata do not leak across opens.
Add a `cv7000.infer_objective_lens_na` metadata option and default it to off. Only write `Objective.LensNA` and the `MappedLensNA` Yokogawa metadata when that option is explicitly enabled, since the CV7000 objective mapping is inferred rather than directly recorded in the acquisition metadata.
Replace CV7000’s custom plane index math with `FormatTools.getIndex` and `getZCTCoords` using an explicit `XYZCT` dimension order. This aligns reverse plane lookup, duplicate-plane fallback, and per-plane metadata with the reader’s logical Z/C/T layout, follows OME-Zarr’s preferred axis order, and fails fast if a Yokogawa channel cannot be mapped into the compact reader channel set.
Use action-aware channel indexing only when every acquired plane has a complete MES-derived action/channel match. Fall back to raw MLF channel indexes when channel sidecar metadata is missing, lacks action assignments, or does not map all acquired planes, and record the fallback mode and reason in Yokogawa provenance metadata.
Treat CV7000 `bts:Power` values as light-source attenuation rather than physical laser or lamp power. Store valid values on `Channel.LightSourceSettings.Attenuation`, preserve them in original metadata, and stop populating OME Laser/Filament power fields from these percent-like sidecar values. Also mark CV7000 lasers as `SolidState` based on the Yokogawa instrument documentation.
Keep CV7000 channel correction file metadata relative to the WPI directory while storing a resolved absolute path for used-file detection. This avoids leaking local absolute paths into metadata without losing the ability to report existing correction sidecars.
Mark preserved CV7000 XML sidecar BinaryFile BinData as little-endian when storing raw bytes, avoiding missing required BinData endianness metadata in generated OME annotations.
@Darlokt
Darlokt marked this pull request as ready for review July 6, 2026 12:30
@Darlokt

Darlokt commented Jul 6, 2026

Copy link
Copy Markdown
Author

Hej @melissalinkert , sorry, for the delay. While creating the synthetic dataset fixtures I realized that the old reader was not maintaining all associated metadata, so beyond fixing the reader to handle sparse acquisitions, I also rewrote the internal model to preserve more Yokogawa metadata and make the reader easier to maintain, hopefully reaching archival quality, so the old original data can be retired, with everything associated to it being preserved in the new reader.

Here a more detailed overview of the changes and their mappings.

As part of responsible disclosure, an AI coding Agent helped with the writing of this overview/review and as a secondary code reviewer throughout the rewrite.

New Reader Overview

The old reader could open the basic file family, but most of the reader behavior lived inside one large initFile flow.
Parsing, sparse series allocation, channel lookup, reverse plane assignment, OME metadata population,and original metadata emission were interleaved. That made sparse acquisitions, metadata-only image records, repeated raw channels, and optional Yokogawa sidecars difficult to reason about.

The new reader keeps the same reader target and file family, but changes the internal model.
It parses the dataset into explicit reader-local structures, allocates series only for TIFF-backed acquired fields, maps logical planes through a reverse lookup, enriches standard OME metadata from Yokogawa sidecars, and records Yokogawa-specific context as scoped annotations.

The central behavioral change is conservative pixel exposure.
A Bio-Formats series now represents an acquired well/field pair only when at least one readable TIFF plane exists for that field. Metadata-only records are retained for logical plane coverage, timing, fallback metadata, and provenance, but they do not create empty field series by themselves.

Executive Summary

Compared with the old reader, the new reader:

  • replaces dense realWells * maxField series allocation with exact acquired-field allocation
  • creates Image and WellSample entries only for acquired fields with readable TIFF data
  • changes missing-plane duplication from default-on to opt-in
  • fills missing logical planes by default instead of silently duplicating nearby pixels
  • changes the core dimension order from XYCZT to XYZCT
  • maps channels through timeline/action/raw-channel context before falling back to raw MLF channel indexes
  • uses representative planes per series/channel for channel metadata
  • lets TIFF-backed records replace metadata-only records for the same logical plane
  • records duplicate, filled, duplicated, metadata-only, and missing logical plane decisions as Yokogawa provenance
  • promotes more sidecar metadata into standard OME plate, image, plane, channel, instrument, detector, objective, filter, dichroic, and light path fields
  • maps Yokogawa light-source Power values to LightSourceSettings.Attenuation instead of physical laser or lamp power
  • preserves Yokogawa-specific context through scoped MapAnnotation groups
  • can embed selected raw XML sidecars as OME FileAnnotation payloads
  • separates field X/Y offsets from reference-frame Z coordinates
  • introduces explicit reader-local models for paths, raw metadata, series layout, channel mapping, annotation grouping, filters, crosstalk, OTF geometry, objectives, and plane provenance

Problems in the old reader

Dense field expansion

The old reader collected acquired wells and the largest observed field index. It then allocated realWells * fields series, where fields was the largest field index plus one.

That is only correct for dense acquisitions where every acquired well has every field slot from 1..maxField.
Sparse CV7000 acquisitions break that assumption. If one well contains field 1 and another contains field 4, the old reader could expose fields 1 through 4 for each acquired well even when several of those well/field pairs were never acquired.

The result was empty Bio-Formats series and WellSample entries for field positions with no readable pixel data.

Metadata-only records could shape pixel layout

MeasurementData.mlf can contain IMG records whose referenced TIFF is absent.
The old reader kept those records, but did not consistently separate metadata-only logical records from TIFF-backed records.

That meant a record with no readable pixels could affect:

  • which wells and fields were considered part of the dataset
  • which logical plane slot appeared occupied
  • which plane supplied WellSample position metadata
  • which channel metadata was selected
  • whether a logical plane appeared to have pixel data

The new reader keeps metadata-only records available for metadata and provenance, but TIFF-backed acquired fields decide series allocation.

Channel metadata lookup was too broad

The old reader used raw Yokogawa channel number as the primary channel lookup key.
lookupChannel returned the first Channel whose raw Ch matched Plane.channel.

That was fragile when the same raw channel was acquired in multiple timelines or actions with different optical settings. It could attach channel metadata from the wrong action to a logical plane.

The old metadata loop also used lookupPlane(series, c) while iterating channels. That assumes the first few logical planes correspond to the first few channels. Sparse Z/T/C layouts and missing early planes break that assumption.

Missing-plane duplication was enabled by default

The old default for cv7000.duplicate_missing_planes was true.
When a logical plane had no TIFF, openBytes could silently return another plane from the same channel.

That behavior invents pixel data that was not acquired.
The new reader changes the default to false, so missing planes are filled with the reader fill color unless duplication is explicitly enabled.

Sidecar metadata was underused

The old reader parsed the main plate, measurement, and measurement-setting sidecars, but much of the available CV7000 sidecar metadata was not promoted into standard OME structures.

Missing or weakly represented metadata included:

  • detector and camera settings
  • filter bands and transmittance ranges
  • dichroic candidates from OTF crosstalk metadata
  • OTF objective and affine calibration rows
  • action Z slice length
  • target system and operator metadata
  • structured provenance for raw Yokogawa sidecars

The old output either omitted these values, flattened them into generic metadata, or made them difficult to audit from exported OME-XML.

Sparse metadata gaps

Because channel metadata depended on fixed logical plane positions, otherwise available metadata could be skipped for sparse acquisitions.

Specific gaps included:

  • physical X/Y size was effectively tied to channel 0 being resolvable
  • physical Z spacing was not inferred from action slice length
  • per-image acquisition dates were not populated
  • per-plane elapsed time was not populated
  • representative channel metadata could come from the wrong action

New Reader Architecture

The old reader performed parsing, layout, reverse lookup construction, and OME metadata population as one interleaved flow.

flowchart TD
    A["Open .wpi"] --> B["Parse plate"]
    B --> C["Parse MLF records"]
    C --> D["Parse MRF and MES"]
    D --> E["Scan planes"]
    E --> F["Collect acquired wells"]
    E --> G["Find max field"]
    F --> H["Allocate dense series"]
    G --> H
    H --> I["Build lookup"]
    I --> J["Populate OME inline"]
Loading

The key problem is the dense allocation step. the old reader mixed "this well was acquired" with "all field slots up to the global maximum were acquired".

The new reader separates parsing, layout, lookup construction, metadata population, and provenance emission into staged responsibilities.

flowchart TD
    A["Open .wpi"] --> B["Reset state"]
    B --> C["Resolve dataset paths"]
    C --> D["Parse WPI and MLF"]
    C --> E["Parse optional sidecars"]
    D --> F["Build raw model"]
    E --> F
    F --> G["Normalize channels"]
    D --> H["Build acquired-field layout"]
    G --> H
    H --> I["Initialize CoreMetadata"]
    I --> J["Populate plane lookup"]
    J --> K["Populate OME metadata"]
    F --> K
    K --> L["Emit Yokogawa provenance"]
Loading

The staged model gives each phase one main decision:

Stage Main decision
Path resolution Find the entry .wpi, required MLF, and optional sidecars.
Sidecar parsing Convert Yokogawa XML into reader-local models.
Channel normalization Sort channels, index action-aware lookup keys, and resolve correction paths for used-file checks while preserving relative correction source metadata.
Series layout Decide which acquired fields become Bio-Formats series.
Core metadata Derive XYZCT, Z/T/C extents, and image counts.
Reverse lookup Map logical plane indexes to selected MLF records.
OME population Promote interoperable metadata into standard OME fields.
Provenance Preserve Yokogawa-specific context and reader decisions.

The reader source now marks the implementation into modules:

Module Responsibility
1 constants, options, known sidecar names, reader state
2 public reader API, used-file reporting, pixel access
3 path resolution and sidecar parsing
4 channel normalization and channel lookup
5 series layout and reverse plane lookup construction
6 plate, image, pixels, and plane metadata population
7 instrument, channel, filter, light path, and detector metadata
8 Yokogawa provenance and raw sidecar annotations
9 file classification, utilities, and lookup helpers
10 reader-local data model classes
11 SAX sidecar handlers
12 OTF, crosstalk, objective, channel, and plane models

The important design change is ownership.
Parsing reads Yokogawa sidecars, layout decides which series exist, channel mapping translates Yokogawa action/channel coordinates, metadata population writes standard OME fields, and provenance records decisions that do not belong in standard OME metadata.

Pixel and Series Behavior

The new reader changes series allocation from dense inferred fields to exact acquired fields.

flowchart TD
    A["MLF plane records"] --> B{"Readable TIFF?"}
    B -->|yes| C["Add exact well/field"]
    B -->|no| D["Keep metadata-only record"]
    C --> E["Sort row/column/field"]
    E --> F["Create acquired-field series"]
    D --> G{"Same field has TIFF?"}
    G -->|yes| H["Can contribute metadata"]
    G -->|no| I["No Image or WellSample"]
    F --> J["Build logical plane lookup"]
    H --> J
Loading

The difference is visible in the high-level behavior:

Area Old reader behavior New reader behavior
Series allocation realWells * fields, where fields is the largest field index plus one. One series per exact acquired well/field pair with at least one readable TIFF.
Series order Sorted acquired wells, then dense field index. Sorted acquired fields by row, column, then Yokogawa field index.
WellSample creation One sample per dense field slot for every acquired well. Samples only for acquired fields in each well.
WellSample indexes Field index doubled as sample index. Per-well sample indexes are compact over acquired fields.
PlateAcquisition.MaximumFieldCount Global maximum field count. Maximum acquired field count in any well.
Missing field series Possible when a well lacked a dense field slot. Not created.
Metadata-only field Could influence well/field layout through well acquisition state. Does not create a series unless the same field has a TIFF-backed plane.
Duplicate logical records First parsed record won; later records were ignored as extra files. TIFF-backed records replace metadata-only records; ignored candidates are annotated.
Dimension order XYCZT. XYZCT.

Reverse Plane Lookup

The reverse lookup remains the bridge between Bio-Formats logical plane index and Yokogawa plane record. The rewrite makes the assignment rules explicit.

flowchart TD
    A["Plane record"] --> B{"Acquired field?"}
    B -->|no| C["Skip lookup"]
    B -->|yes| D["Map channel"]
    D --> E["Compute XYZCT index"]
    E --> F{"Slot empty?"}
    F -->|yes| G["Select record"]
    F -->|no| H{"Candidate has TIFF?"}
    H -->|yes| I["Replace metadata-only or ignore duplicate TIFF"]
    H -->|no| J["Ignore metadata-only duplicate"]
    I --> K["Record duplicate candidate"]
    J --> K
    G --> L["Index representative plane"]
    K --> L
Loading

A metadata-only record can no longer permanently occupy a logical slot when a later TIFF-backed record maps to the same slot. If a duplicate TIFF-backed record is ignored, it is still recorded as a duplicate candidate and reported as provenance.

Missing Plane Reads

The public option still exists cv7000.duplicate_missing_planes.

The default changes from true in the old reader to false in the new reader. With default behavior, openBytes fills the output buffer and returns that fill data when a logical plane has no readable TIFF.

When duplication is explicitly enabled, the reader tries to duplicate a TIFF-backed plane from logical Z 0, the same channel, and timepoint 0. The duplication path verifies that the candidate has a real file before recursively reading it.

flowchart TD
    A["openBytes"] --> B["Fill buffer"]
    B --> C{"Requested plane has TIFF?"}
    C -->|yes| D["Read TIFF"]
    C -->|no| E{"Duplication enabled?"}
    E -->|no| F["Return fill"]
    E -->|yes| G["Find Z0/C/T0 source"]
    G --> H{"Source has TIFF?"}
    H -->|yes| I["Read source plane"]
    H -->|no| F
Loading

This makes data integrity the default while preserving the old visualization escape hatch for users who choose it.

Channel Mapping and Representative Planes

The old reader had two separate channel problems:

  • logical channel indexes were calculated from action order without recording a fallback mode when action mapping was incomplete
  • channel metadata lookup returned the first channel with the same raw Ch value, even if the plane belonged to another timeline or action

The new reader centralizes this behavior in CV7000ChannelMapper and CV7000RawModel.

flowchart TD
    A["MRF channels"] --> B["Base channel objects"]
    C["MES actions"] --> D["Timeline/action channel copies"]
    B --> E["Normalized channel list"]
    D --> E
    E --> F["Index timeline/action/raw channel"]
    G["MLF records"] --> H{"Complete action mapping?"}
    F --> H
    H -->|yes| I["ACTION_MAPPED channels"]
    H -->|no| J["RAW_MLF fallback"]
    I --> K["Compact channel axis"]
    J --> K
    K --> L["Representative plane per series/channel"]
    L --> M["OME channel metadata"]
Loading

The lookup order for OME channel metadata is:

Order Lookup
1 Exact indexed timelineIndex + actionIndex + raw channel.
2 Exact parsed-list scan for the same timelineIndex + actionIndex + raw channel.
3 Populated raw-channel fallback.
4 First raw-channel fallback.

The layout stage uses action-mapped logical channel indexes only when every MLF record in an acquired field can be mapped.
If channel sidecar metadata is absent, action/channel assignments are absent, or any acquired record cannot be mapped exactly, the layout falls back to raw MLF channel indexes and records the fallback reason in Yokogawa provenance.

That avoids a partially remapped channel axis, where some planes would use action-aware channel order and others would use raw MLF numbering.

Representative planes are indexed during reverse lookup.
They prefer TIFF-backed records and fall back to metadata-only records only when needed. Channel names, colors, light paths, detectors, filters, exposure times, and related settings are populated from the representative plane for each series/channel.

If no representative plane or matching channel metadata can be found for an OME channel, that channel metadata slot is left unset instead of borrowing metadata from an unrelated channel.

Metadata Added by the Rewrite

OME population now runs after sidecars, series layout, core metadata, and the reverse plane lookup are ready.

flowchart TD
    A["CoreMetadata ready"] --> B["Populate Pixels"]
    B --> C["Populate Plate and Wells"]
    C --> D{"MINIMUM metadata?"}
    D -->|yes| E["Stop after sparse HCS layout"]
    D -->|no| F["Populate Instrument"]
    F --> G["Populate Experimenter"]
    G --> H["Populate Image, Channel, Plane"]
    H --> I["Emit Yokogawa annotations"]
Loading

The MINIMUM path still describes pixels and sparse HCS layout because Image and WellSample objects are created from acquired fields, not dense nominal field slots.

The full metadata path creates shared instrument IDs and indexes before populating each series. Those indexes let channels link to the correct light source, detector, filter, dichroic, and objective metadata.

Source-to-OME Mapping

Source Reader role Standard OME output or provenance
.wpi Entry point and plate definition. Plate identity, dimensions, naming conventions, WPI provenance.
MeasurementData.mlf Required acquisition manifest. Series allocation, plane lookup, Image/WellSample relationships, timing, Z position, plane provenance.
MeasurementDetail.mrf Measurement summary and channel seed metadata. Plate acquisition times, operator, microscope model, physical X/Y size, detector and channel seed metadata.
.mes settings Acquisition design and optical settings. Light sources, objectives, channel names/colors/modes, excitation wavelength, exposure time, physical Z spacing, action provenance.
.wpp Plate-product sidecar. Yokogawa plate-product provenance.
PostProcess.ppf Post-processing sidecar. Yokogawa post-process provenance summary.
OTF_crosstalk_parameter.xml Filter and crosstalk metadata. Filters, transmittance ranges, dichroics, light path refs, crosstalk provenance.
OTF_geometry_parameter.xml Objective catalog and affine rows. Additional objectives, magnification, immersion, optional LensNA, OTF affine provenance.
TIFF plane files Pixel payload. Backing data for openBytes; determines acquired well/field series.

Plate, Image, Pixels, and Planes

The new reader keeps the reader in the HCS domain and exposes one OME Plate. The difference is that the plate acquisition is driven by acquired fields instead of dense nominal field slots.

Plate and well metadata changes include:

  • Plate ID, name, description, external identifier, rows, and columns
  • Plate RowNamingConvention = LETTER
  • Plate ColumnNamingConvention = NUMBER
  • Plate WellOriginX/Y = 0 micrometer
  • all OME Well rows and columns for the plate grid
  • WellSample only for acquired fields within each well
  • compact per-well WellSample indexes
  • WellSample Index equal to the emitted image index
  • WellSample ImageRef to the corresponding Image
  • PlateAcquisition MaximumFieldCount from acquired fields per well
  • PlateAcquisition WellSampleRef only for emitted samples

Each acquired well/field pair becomes one OME Image and one Bio-Formats series.
Dimensions are derived from the first readable TIFF, observed logical Z and T extents for that acquired field, and the compact dataset-wide logical channel list.

Logical raster calculations now use Bio-Formats dimension-order helpers:

  • dimensionOrder = XYZCT
  • getLogicalZCTCoords(series, no)
  • getLogicalPlaneIndex(series, z, c, t)

Plane and timing metadata changes include:

  • Image AcquisitionDate from the earliest timestamp in each series
  • WellSample Timepoint from the same series start timestamp
  • Plane DeltaT relative to the series start
  • Plane PositionZ preserving the Yokogawa Z coordinate as a reference-frame
    coordinate
  • no Plane PositionX/Y; X/Y placement is represented at
    WellSample PositionX/Y
  • Plane ExposureTime per logical plane when channel settings provide it
  • Pixels PhysicalSizeX/Y from the first resolvable representative channel
  • Pixels PhysicalSizeZ from action SliceLength only when all resolvable
    representative channels in the series agree on the same positive value

The X/Y change is intentional. CV7000 sidecars mix coordinate systems.
The reader treats MLF X/Y values as micrometer field offsets relative to the well center and writes them to WellSample PositionX/Y. It preserves MLF Z as a reference-frame plane coordinate.

Instrument, Objectives, Detectors, and Light Sources

The new reader creates an Instrument when instrument-relevant metadata is present.
Instrument creation and series-level enrichment happen only outside MINIMUM metadata.

Instrument metadata can include:

  • Microscope Manufacturer = Yokogawa
  • microscope model from the MRF target system
  • Image InstrumentRef
  • laser and lamp light sources from MES settings
  • objective objects from MES channel metadata and OTF geometry rows
  • detector objects indexed by camera number
  • filter objects from parsed detection filters
  • dichroic objects from OTF crosstalk metadata

The old reader only created an instrument when laser light sources were present.
The new reader also creates one when channels, OTF objectives, or target-system metadata provide instrument-level content.

Objective metadata now comes from MES channel metadata and OTF geometry affine rows keyed by objective ID.
Explicit sidecar magnification is used when available.
If explicit magnification is absent, recognizable objective model tokens can populate nominal magnification and immersion.

The option cv7000.infer_objective_lens_na defaults to false.
When enabled, known CV7000 objective model strings from documentation can populate inferred objective LensNA.
The option does not gate explicit magnification, parsed model-token magnification, or parsed immersion.

Detector metadata is promoted from camera metadata.
The reader creates detector objects, records detector type as OME CMOS for the CV7000 sCMOS detector case, and links channel detector settings when camera numbers can be resolved.

The MRF operator name is emitted through the separate Experimenter path and linked to each image with Image ExperimenterRef.

Channels, Filters, Light Paths, and Exposure

Channel, light path, filter, dichroic, detector, and exposure metadata now share one representative-plane lookup path.

The new reader can populate:

  • Channel Name
  • Channel Color
  • Channel Fluor
  • Channel AcquisitionMode
  • Channel ContrastMethod
  • Channel IlluminationType
  • Channel ExcitationWavelength
  • Channel EmissionWavelength
  • LightPath EmissionFilterRef
  • LightPath DichroicRef
  • LightSourceSettings Attenuation
  • DetectorSettings ID
  • DetectorSettings Gain
  • DetectorSettings Binning
  • Plane ExposureTime

The semantic change is that excitation now comes from the light source linked to the channel.
Yokogawa acquisition labels such as BP676/29 are treated as detection filter labels. They provide fallback emission filter center and bandpass range.
OTF crosstalk rows can refine the filter transmittance range and provide dichroic candidates.

Most outputs remain conditional:

Output Emitted when
LightSourceSettingsID A linked light source object was indexed.
LightSourceSettings Attenuation Yokogawa light-source Power is finite and in the accepted 0..100 range; values above 1 are divided by 100 for OME PercentFraction.
Channel ExcitationWavelength The linked light source is a laser with a positive wavelength.
EmissionFilterRef A matching filter object was indexed.
DichroicRef The matched OTF filter has exactly one indexed dichroic.
DetectorSettings The channel camera number has an indexed detector.
Plane ExposureTime MES channel exposure time is available.

If the representative plane is missing, or if channel lookup cannot find a matching channel, the reader skips that OME channel metadata slot rather than copying unrelated metadata.

Yokogawa Provenance and Raw Sidecars

The new reader introduces grouped Yokogawa metadata annotations. Instead of emitting one large flat original-metadata set, related values are grouped by scope and emitted as OME MapAnnotation objects under openmicroscopy.org/OriginalMetadata/Yokogawa/CV7000.

Examples of scopes include:

  • Yokogawa WPI WellPlate
  • Yokogawa MRF MeasurementDetail
  • Yokogawa MRF Channel N
  • Yokogawa MES LightSource NAME
  • Yokogawa MES Channel N
  • Yokogawa MES Timeline N Action M
  • Yokogawa OTF Crosstalk EMFilter N
  • Yokogawa OTF Geometry Affine N
  • Yokogawa Plane Provenance Image N
  • Yokogawa Sidecar NAME
flowchart TD
    A["Parsed sidecar fields"] --> B["Annotation group"]
    C["Plane provenance"] --> B
    D["Sidecar summary"] --> B
    B --> E["MapAnnotation"]
    E --> F{"Best scope"}
    F -->|plate/general| G["Plate ref"]
    F -->|instrument/OTF| H["Instrument ref"]
    F -->|image/action| I["Image ref"]
    F -->|channel| J["Channel ref"]
Loading

This keeps standard OME metadata focused on interoperable fields while keeping Yokogawa-specific source fields and reader decisions available in exported OME-XML.

Plane Provenance

Outside MINIMUM metadata, the reader emits one plane provenance group per OME Image.
These annotations document how the logical Bio-Formats raster maps back to MLF records and TIFF files.

Each summary includes:

  • SeriesIndex
  • ImageIndex
  • PlaneCount
  • TiffBackedCount
  • FilledCount
  • DuplicatedCount
  • MetadataOnlyCount
  • NoMLFRecordCount
  • DuplicateCandidateCount

When the field can be resolved, the summary also includes:

  • Well
  • FieldIndex

When a plane is filled, duplicated, or a duplicate logical record is ignored or replaced, the summary can include repeated Anomaly[N] rows.

Duplicate-candidate anomalies use a common DUPLICATE_CANDIDATE_IGNORED status and carry the exact handling reason, such as:

  • REPLACED_BY_TIFF
  • IGNORED_TIFF_DUPLICATE
  • IGNORED_METADATA_ONLY_DUPLICATE

Plane provenance is informational. It does not alter Pixels, Plane, or Channel structure.
It explains how missing, metadata-only, duplicated, and duplicate logical records were handled.

Raw Sidecar Preservation

The new reader adds cv7000.preserve_raw_sidecars with default true.
When enabled, selected XML sidecars are embedded as OME FileAnnotation payloads under openmicroscopy.org/OriginalMetadata/Yokogawa/CV7000/RawSidecar.

The preservation policy is selective:

File role Raw FileAnnotation payload
.wpi yes
MeasurementDetail.mrf yes
.mes settings yes
.wpp yes
OTF_crosstalk_parameter.xml yes
OTF_geometry_parameter.xml yes
MeasurementData.mlf no raw payload, but summarized
PostProcess.ppf no raw payload, but parsed and summarized
TIFF planes no

All classified non-pixel sidecars can still receive summary provenance with role, byte length, and SHA-256. Raw preservation controls embedded payloads, not whether sidecars are summarized.

Annotation Shape

The provenance output uses standard OME annotation structures:

  • MapAnnotation for grouped Yokogawa key/value metadata
  • FileAnnotation for selected raw XML sidecar payloads
  • AnnotationRef links from plate, instrument, image, or channel
  • MapPair values where both keys and values are strings

Plane anomaly rows are encoded as compact semicolon-delimited strings in Anomaly[N] keys. That keeps the output schema-compatible without inventing new OME elements.

Reader Options and Used Files

The reader now exposes three CV7000-specific options:

Option the old reader default Current default Effect
cv7000.duplicate_missing_planes true false Controls whether missing logical planes are duplicated from another plane or returned as fill pixels.
cv7000.preserve_raw_sidecars unavailable true Controls embedding of selected raw XML sidecars as OME FileAnnotation payloads.
cv7000.infer_objective_lens_na unavailable false Allows known CV7000 objective model strings to populate inferred objective LensNA.

The pixel-affecting default is conservative: missing pixels are not invented by default.
The LensNA default is also conservative because values inferred from a known-objective table are not emitted unless explicitly requested.
Raw sidecar preservation defaults to auditability, not smaller metadata output.

The new reader classifies known CV7000 files by role instead of relying on suffix checks alone.

getUsedFiles(noPixels) and getSeriesUsedFiles(noPixels) use CV7000FileRole to decide whether a file is a pixel file.
This matters because CV7000 datasets contain XML sidecars, optional calibration files, TIFF planes, and correction files. Shading-correction paths are resolved when testing readability and reporting used files, but the Yokogawa ShadingCorrectionSource provenance keeps the relative path from the sidecar when one can be derived.

The reader can now:

  • include the entry .wpi
  • include known sidecars and parsed optional files
  • include per-series TIFFs only when pixel files are requested
  • include correction files when they exist and pixel files are requested
  • include ignored duplicate TIFFs as extraFiles
  • avoid treating every .tif suffix match as the only pixel-file decision

Known dataset roles include:

Role Used-file behavior
Entry .wpi Included as the dataset entry sidecar.
Required MLF Included as required acquisition metadata.
MRF, MES, WPP, PPF Included as sidecars when present and recognized.
OTF crosstalk and geometry Included as optional calibration/optics sidecars.
TIFF planes Included when pixel files are requested.
Correction files Included for pixel-file requests when referenced and readable.

Internal Structure

The rewrite adds reader-local structures that make the data flow explicit:

Structure Purpose
CV7000DatasetPaths Resolved entry and sidecar paths for the dataset.
CV7000RawModel Parsed Yokogawa metadata and channel lookup index.
CV7000SeriesLayout Acquired fields, per-well fields, channel indexes, extents, reverse lookup, representative planes, and duplicate candidates.
CV7000ChannelMapper Action-aware channel indexing and channel lookup fallback.
YokogawaParsing XML cleanup, attribute normalization, integer parsing, gain parsing, detection filter parsing, binning normalization.
InstrumentMetadataIndexes Shared indexes for light sources, detectors, filters, dichroics, and objectives.
AnnotationRefIndexes Tracks annotation reference indexes by plate, instrument, image, and channel.
YokogawaAnnotationGroup Builds scoped MapAnnotation key/value payloads.
PlaneProvenanceSummary Counts TIFF-backed, filled, duplicated, metadata-only, and missing logical planes.
DuplicatePlaneCandidate Records ignored or replaced duplicate logical records.
CrosstalkParameters Stores OTF crosstalk filters, dichroics, and fluorophore intensity rows.
OTFGeometryParameters Stores OTF objective catalog entries and affine calibration rows.
KnownObjectiveSpec Known CV7000 objective table for optional LensNA and immersion inference.
DetectionFilter and FilterKey Parsed emission filter band and unique filter identity.

The model boundaries matter more than the helper class names.

The reader now has a clear split between:

  • Yokogawa sidecar parsing
  • acquired-field layout
  • action-aware channel mapping
  • standard OME metadata population
  • Yokogawa provenance emission
  • raw sidecar preservation

That separation makes the sparse acquisition behavior auditable.
A reviewer can follow which phase decides series existence, which phase maps logical planes, which phase enriches standard OME fields, and which phase records CV7000-specific context.

Behavior Comparison Summary

Topic the old reader New reader
Main flow One large initFile flow. Explicit staged pipeline.
Required manifest MeasurementData.mlf. Same.
Optional sidecars MRF and MES used for limited metadata. MRF, MES, WPP, PPF, OTF crosstalk, and OTF geometry are parsed or summarized.
Series creation Dense by acquired well and max field count. Sparse by exact TIFF-backed acquired field.
Series order Acquired wells, then dense field slot. Acquired fields sorted by row, column, field.
WellSample creation One sample per dense field slot for every acquired well. One sample per acquired field.
Channel axis Action-derived indexes without complete-mode guard. Action-mapped only when complete; otherwise raw MLF fallback.
Channel lookup First matching raw channel. Exact timeline/action/raw channel first.
Channel representative Fixed logical plane positions. Representative plane per series/channel.
Missing pixels Duplicate by default. Fill by default.
Duplicate planes Later duplicates ignored. TIFF replaces metadata-only; ignored candidates are annotated.
Dimension order XYCZT. XYZCT.
Physical X/Y From channel 0 when resolvable. From first resolvable representative channel.
Physical Z Not inferred from action slice spacing. From consistent action SliceLength.
Plane X/Y Plane PositionX/Y in reference frame. Moved to WellSample PositionX/Y as micrometer field offsets.
Plane Z Reference-frame PositionZ. Preserved as reference-frame PositionZ.
Timing Plate acquisition begin/end. Adds image acquisition date, well-sample timepoint, and plane deltaT.
Light sources Lasers only. Lasers and lamps.
Detectors Not promoted. Detector objects and detector settings.
Filters Not promoted. Emission filters and transmittance ranges.
Dichroics Not promoted. Dichroic objects and unambiguous light path refs.
Objective LensNA Not inferred. Optional via cv7000.infer_objective_lens_na.
Raw sidecars Not embedded. Selected XML sidecars embedded by default.
Provenance Limited flat metadata. Scoped Yokogawa MapAnnotation groups.

Overall Effect

The new reader makes the CV7000 reader more conservative about pixels and more complete about metadata.

It no longer invents empty field series from nominal or maximum field counts.
It no longer duplicates missing pixel planes unless explicitly requested.
It uses TIFF-backed records to decide acquired fields, while still retaining metadata-only records for logical metadata and provenance.

The rewrite also makes channel metadata safer.
Pixel layout and OME channel metadata both use timeline/action-aware channel instances when complete mapping is available.
If raw MLF channel indexes are the only safe mapping, the reader uses them consistently and records the fallback reason as Yokogawa provenance.

At the OME layer, the reader now exposes richer plate, timing, channel, instrument, objective, detector, filter, dichroic, light source, physical size, and provenance metadata.
Yokogawa-specific source fields are preserved in scoped annotations instead of being discarded or flattened without context.

The result is a reader that better represents sparse CV7000 acquisitions as they were actually acquired, while making sidecar-derived metadata and reader decisions auditable from exported OME-XML, reaching by my observation full preservation and archival quality, for full conversion fo exsting data without loosing metadata.

@Darlokt

Darlokt commented Jul 6, 2026

Copy link
Copy Markdown
Author

As part of this I have made minimal synthetic dataset-fixtures to check for regressions, with the associated .bioformats test files, should they be each submitted separately or as one collection of test datasets?

As real data I found available S-BIAD1013 available open at the BioImage Archive which could be included for real data testing. The other studies I found do not publish the metadata files. S-BIAD1013 passed the reader tests fully and was fully parsed.

Beyond that, I would love some guidance on the NA inference path.
As it stands, this maps all objectives which were possible to be shipped in standard options with the system correctly. I was able to find a study which had a custom order 40x water objective which was correctly rejected when tested against in NA inference path, but of course other edge cases exist. The benefit I would see is that for the other lets say 90% of systems the inference would properly populate the NA which would allow for sampling etc. estimations.

In a global view the metadata is still quite incomplete, no disk data, back projected pinhole etc. is available etc. but that is a problem of the metadata format, as no more information can be stably inferred, at least from my point of view.

@melissalinkert

Copy link
Copy Markdown
Member

As part of this I have made minimal synthetic dataset-fixtures to check for regressions, with the associated .bioformats test files, should they be each submitted separately or as one collection of test datasets?

A single submission to https://zenodo.org/communities/bio-formats is fine.

@Darlokt

Darlokt commented Jul 7, 2026

Copy link
Copy Markdown
Author

@melissalinkert Perfect! The datasets are under https://zenodo.org/records/21224717.

Store CV7000 dataset paths and measurement summaries in memo-friendly value objects instead of retaining Location and SAX handler instances. Make reader-local helper models accessible to Kryo with public classes, fields, and no-arg constructors, avoiding Java module-access failures when saving bioformats2raw memo files on Java versions newer than 11.
@Darlokt

Darlokt commented Jul 8, 2026

Copy link
Copy Markdown
Author

ed3fbc6 fixes memoization and local helper model access for Kryo in Java > 11.
Sorry, I didnt test with Java 17+.

Darlokt added 9 commits July 10, 2026 09:48
Assign stable logical channel slots across action and timeline acquisitions, qualify overlapping timeline channels, and preserve raw-channel fallback behavior. Match repeated MRF channel definitions by occurrence, mark ambiguous metadata safely, and improve duplicate-plane reuse by selecting TIFF-backed planes from the same logical channel.
Apply consistent Yokogawa channel bit depths to each series, validate values against storage width, and retain TIFF-derived fallbacks when channel metadata is missing, ambiguous, invalid, or conflicting.
Log missing sidecar metadata and unavailable exact acquisition matches, while deduplicating fallback warnings per raw channel. Guard channel lookup against null planes and channel lists, and reset warning state when reindexing metadata.
Add configurable Zlib compression for preserved raw sidecars, recording the compression type and encoded payload length while retaining an option to store the original bytes.
Include measurement data and post-process XML roles when identifying CV7000 metadata files, to allow embedding. With compression options, this seems now like a possible option.
Add namespace-independent Yokogawa XML parsing helpers and use them consistently across CV7000 sidecar handlers. Parse and summarize MLF and post-processing provenance, link record annotations to matching images, and limit emitted detail records through a configurable metadata option.
Track acquisition and shading-correction TIFFs separately instead of treating every TIFF beside the WPI as a dataset plane. Only accept readable TIFFs referenced by MLF IMG records as acquisition files, while retaining referenced correction TIFFs as non-plane dependencies.
Recover uniquely matching readable TIFF corrections when expected files are absent, while rejecting ambiguous matches and warning about their sources.
@Darlokt

Darlokt commented Jul 13, 2026

Copy link
Copy Markdown
Author

Hej @melissalinkert,

Since my previous message, I have added nine follow-up commits. These changes refine the channel model, make metadata fallback behavior more explicit, extend sidecar provenance, and tighten the distinction between acquisition pixels and other TIFF dependencies.

Channel mapping and bit depth

The reader now assigns stable logical channel slots across actions and timelines. A channel is only timeline-qualified when the same acquisition coordinate would otherwise collide across timelines; non-colliding channels retain their primary slots. This avoids both merging distinct acquisitions and unnecessarily expanding the channel axis.

Repeated MRF channel definitions are matched by occurrence rather than always selecting the first raw-channel match. Ambiguous definitions are marked as such and are not used to populate potentially incorrect OME channel metadata. Missing-plane duplication, when explicitly enabled, also now searches for a TIFF-backed plane in the same logical channel instead of relying on an earlier fixed position.

The reader additionally prefers Yokogawa InputBitDepth metadata for CoreMetadata.bitsPerPixel when all represented channels in a series provide one consistent, valid value that fits within the TIFF storage width. If the value is missing, ambiguous, invalid, too large, or inconsistent across channels, the reader retains the TIFF-derived value and logs the reason.

Channel lookup fallbacks are now visible in the log. When no exact timeline/action/raw-channel match is available and the reader has to use a broader raw-channel definition, it emits one deduplicated warning per acquisition/channel key. This preserves the existing safe fallback while making degraded metadata resolution auditable.

Sidecar preservation and structured provenance

Raw sidecar preservation now supports Zlib compression through the new cv7000.compress_raw_sidecars option, enabled by default. Embedded FileAnnotation payloads record the corresponding OME compression value and encoded payload length. Setting the option to false retains the original uncompressed-byte behavior.

With the savings from the zlib compression, it now makes sense to also embed the bigger files, so now MeasurementData.mlf and PostProcess.ppf are recognized as preservable metadata sidecars as well. These files can now be embedded alongside the WPI, MRF, MES, WPP, and OTF XML sidecars rather than being represented only by summaries.

The XML parsing code has been centralized around namespace-independent element and attribute helpers and is now used consistently by the Yokogawa sidecar handlers. On top of the raw preservation, the reader exposes more structured provenance:

  • MLF record counts, unknown-record counts, error classifications, affected wells, and selected non-image record details
  • PPF action counts and status/type summaries
  • PPF log totals, severity/title summaries, time range, and selected log details
  • links from record annotations to the matching OME images where possible

Detailed MLF and PPF records are bounded by the new cv7000.max_provenance_records option, which defaults to 500. Summary counts and truncation information are still emitted, so limiting detail does not hide how much source information was omitted. Path-like PPF values are sanitized to portable file names to avoid embedding machine-specific paths in original metadata.

TIFF and shading-correction discovery

TIFF discovery is now reference-driven. The reader tracks acquisition TIFFs referenced by MLF IMG records separately from shading-correction TIFFs referenced by channel metadata. An unrelated TIFF merely located beside the WPI is no longer treated as a dataset plane or reported as a pixel dependency. This may be a regression, as the possible dark current files are no longer mentioned/added, but they were not a part of the general metadata to begin with, so that may be something that can be defined, as inclusion on the standard metadata I think could be possible.

If a referenced shading-correction file is missing under its exact metadata name, the reader searches the expected directory for readable TIFFs whose filename stem contains the expected stem. This was implemented, as in some cases they can ave prefixes, I am unsure where they come from, but now this possibility is handled. It accepts the fallback only when the match is unique, updates the resolved dependency path, and warns rather than guessing when multiple candidates match. This handles CV7000 packages in which correction files have gained an additional filename pre/suffixes while keeping resolution deterministic.

Cleanup

The follow-up series also removes obsolete plate-description and measurement-summary accessors that were no longer used after the reader restructuring, and changes internal used-file collections to insertion-ordered sets to avoid duplicate entries while retaining deterministic ordering.

Summary

Overall, these commits do not change the general previous behavior of the reader but they make its channel axis more robust for repeated and multi-timeline acquisitions, implement/improve metadata based significant-bit reporting, preserve and summarize more of the original Yokogawa audit trail, and tighten file discovery that only metadata-referenced TIFFs are considered part of the dataset.

In line with this I have also extended/improved the synthetic test cases, adding them under a new version 2.0.0 under https://zenodo.org/records/21334895.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants