Skip to content

VSI: surface CALIBRATION lookup table as named slope/origin/final keys#4427

Open
PEEKPerformer wants to merge 1 commit into
ome:developfrom
PEEKPerformer:vsi-calibration-summary-keys
Open

VSI: surface CALIBRATION lookup table as named slope/origin/final keys#4427
PEEKPerformer wants to merge 1 commit into
ome:developfrom
PEEKPerformer:vsi-calibration-summary-keys

Conversation

@PEEKPerformer
Copy link
Copy Markdown

Refs: #4398, #4417.

Tag 20051 contains a linear (raw, calibrated) lookup table. PR #4417 named the tag but didn't extract anything from it. A linear LUT is a slope and an offset. Two numbers. This patch writes them out as scalar keys.

Four new keys:

  • Calibration Function Slope: (cal_last - cal_first) / (raw_last - raw_first)
  • Calibration Function Origin: cal at the first raw point
  • Calibration Function Final: cal at the last raw point
  • Calibration Function NPoints

For DSX-2000 EFI height maps, Slope is the µm-per-uint16-count factor that converts a height-map pixel value to absolute Z. Without it, height-map TIFFs out of bfconvert are uncalibrated.

Code

+31 lines, 0 deletions. Single case in CellSensReader.java::readTags, in the existing DOUBLE_2 branch. Gated on:

tag == VALUE
&& "Calibration Function ".equals(tagPrefix)
&& realType == DOUBLE_2
&& nDoubleValues >= 4
&& (nDoubleValues % 2) == 0

Doesn't run on files without the tag. Doesn't modify the existing string-form output.

Validation

README pull-request testing checklist:

  • Branch merges cleanly into the current develop (verified via git merge-tree).
  • ant clean jars tools: BUILD SUCCESSFUL, 31s.
  • Maven build: BUILD SUCCESS.
  • ant test: 1833 tests across all phases (unit, long-running, no-ome-xml, no-exif, no-jhdf, spec). 0 failures, 0 skips. 3m35s.
  • No Java 1.8+ syntax (the patch is plain if/else with primitives and String.equals).
  • showinf end-to-end on representative .vsi files (see below).

showinf on the public CellSens samples at downloads.openmicroscopy.org/images/CellSens/:

  • Deconvolved MLE files, the VSI: make it easier to get calibration data #4398 case: Slope=1.290, Origin=47.23, Final=84606, NPoints=2.
  • Un-deconvolved siblings: silent.
  • Evident BF and FL_3D: Slope=0.1, Origin=-3276.8 (16-bit display LUT).
  • metadataTest_01: silent.

showinf on 10 DSX-2000 EFI height-map .vsi files from a polymer-composite study I'm running. Each produces the four-scalar quartet. For the 40× porestack:

Calibration Function NPoints: 385
Calibration Function Origin:  14930.6
Calibration Function Final:   14738.6
Calibration Function Slope:   -0.002929732204165713

EFI scan range = 192 µm. Cross-checked against a from-scratch binary parser of the same file. Agrees to 6 decimals.

Notes

I don't have access to the curated data repo, so ant test-automated against the full corpus is what I need from you.

Happy to upload a representative DSX file to the Bio-Formats Zenodo community. Polymer composite, 314 KB .vsi plus 6 MB .ets, no biological content.

The existing string-form Calibration Function Value key is still silently dropped on some files by the filter around line 1997. The summary keys here come through unconditionally because they call addGlobalMeta directly. Fixing the underlying filter touches a hotter code path. Out of scope.

cc @melissalinkert (touched the same code in #4417)

Tag 20051 (CALIBRATION) sub-volumes carry a piecewise-linear
lookup table mapping a raw axis (e.g. uint16 pixel value) to a
calibrated axis (e.g. Z position in micrometres for DSX EFI height
maps, or intensity in counts for deconvolved fluorescence). PR ome#4417
named the tag but the underlying value is currently surfaced (when
it makes it through the metadataIndex/VALUE filter at all) as a
single comma-separated string of every (raw, calibrated) pair, which
is unwieldy and silently dropped for some file types (e.g. Olympus
DSX-2000 collapsed-EFI height maps).

Since the LUT is linear by construction, expose the same information
as four scalar named keys instead:

  Calibration Function Slope    : (cal_last - cal_first)/(raw_last - raw_first)
  Calibration Function Origin   : cal value at raw_first
  Calibration Function Final    : cal value at raw_last
  Calibration Function NPoints  : number of (raw, cal) pairs

Origin and Final together work for both monotonic directions (DSX
EFI height maps decrease, deconvolved fluorescence increases).

Validated against ten DSX-2000 EFI height-map .vsi acquisitions and
the public CellSens samples on downloads.openmicroscopy.org/images/
CellSens/. Each file with a properly-formed CALIBRATION sub-volume
now produces the four-scalar summary; files without the tag remain
silent.

Refs: ome#4398, ome#4417
Signed-off-by: Brenden Ferland <brendenferland@gmail.com>
@PEEKPerformer
Copy link
Copy Markdown
Author

Spotted in #4417's diff: the existing Calibration Function Value lands in pyramid originalMetadata (so it shows as SR488 Calibration Function Value for the MLE files). My four new keys go to global. Different section of the OME XML.

Want me to switch to addMetaList when metadataIndex >= 0, addGlobalMetaList otherwise? Five-line change. Fixes the multi-LUT case for free.

@melissalinkert
Copy link
Copy Markdown
Member

Thanks, @PEEKPerformer. Before we proceed with review, please do submit the relevant dataset to Zenodo. Per OME's contributing policy, we do also need a signed Contributor License Agreement:

https://ome-contributing.readthedocs.io/en/latest/cla.html

@PEEKPerformer
Copy link
Copy Markdown
Author

Sounds good, I submitted both yesterday. Thanks!

@melissalinkert
Copy link
Copy Markdown
Member

Thanks, @PEEKPerformer. Submitted dataset is now here: https://zenodo.org/records/19893921.

@melissalinkert melissalinkert self-requested a review May 4, 2026 13:33
@melissalinkert melissalinkert added this to the 9.0.0 milestone May 5, 2026
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