Repository navigation
OME-Zarr axes and calibration: nothing guessed, nothing silent (#72, #73, #94) - #129
Merged
Merged
Conversation
…72, #73, #94) - #72: every OME-Zarr image is matched by the roles its OME-NGFF axes declare, also when its axis letters are the mapping's (axes.ome_zarr_mapping, used by review_axes and file_mapping_for). NGFF ZYX confirmed TYX or ZXY, and QYX confirmed CYX, are ome_zarr_axes_mismatch, naming each image with its declared axes and confirmed roles; the image is never read under them. - #73: missing axes are never guessed. Only OME-NGFF 0.1/0.2 (whose spec fixes 5-D t,c,z,y,x) keep TCZYX, by the stated version; 0.3-0.5 without axes, and a store without axes stating no or another version, are unreadable_ome_zarr. - #94: a malformed coordinateTransformations calibration (ngff_scale.read_scale) gives unknown sizes with the reason in PhysicalSizes.invalid and the warning invalid_physical_calibration naming every image; the blanket except with a debug log is gone. Contract, user guide, plan (question 60) and AGENTS.md updated; the code-rules baseline shrinks (review_axes, physical_sizes.py, test_zarr_input.py, ANN noqa). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
guijacquemet
marked this pull request as ready for review
November 2, 2026 16:07
…ning for a lost time step Owner decision (2 November 2026): no spec-default t, c, z, y, x. An OME-NGFF 0.1 or 0.2 store is unreadable_ome_zarr whatever it contains, with the message to re-save it as OME-NGFF 0.4 or later. ngff_axes loses its unused ndim. Review finding: invalid_physical_calibration disappeared once X and Y (and Z) were stated in calibration.csv, also when the malformed scale had lost the time step of a time series, which cannot be stated there: that loss became silent. The warning now stays until every size the malformed calibration leaves unknown is stated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
docs/plan.md: main's items (16) to (18) of question 59 come first, then question 60 of this PR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
…rrangement test_an_ome_zarr_copy_changed_in_place_is_not_reused (from #126) wrote a 'zyx' store into an experiment confirmed ZYX -> ZXY: the same letters under contradicted roles, which issue #72 refuses (ome_zarr_axes_mismatch). The store is now 'tzyx' with one time point, matched by its declared roles, so the test checks the reuse of a changed chunk as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
guijacquemet
pushed a commit
that referenced
this pull request
Nov 2, 2026
No conflicts; plan questions on main end at 59, so 62-64 are renumbered once #128 and #129 land. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Contributor
Author
|
Independent review: merged as 7f55ba1 (merge commit). The branch was auto-deleted on merge and has been restored at the PR head, 67bdea5. Owner decisions implemented (2026-11-02)
All of these are recorded in plan question 60. Findings fixed
Verified in code
Gate on 67bdea5 (uv venv, Python 3.11,
§9 figures
Issues #72, #73 and #94 are closed. Generated by Claude Code |
guijacquemet
pushed a commit
that referenced
this pull request
Nov 2, 2026
docs/plan.md: main's PP-11b and PP-11c items first, then this PR's links item; this PR's questions 60 and 61 become 61 and 62, after main's question 60 (OME-Zarr axes and calibration, #129). docs/contract.md: both additions to the error row kept (main's OME-Zarr codes, this PR's link codes). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
guijacquemet
pushed a commit
that referenced
this pull request
Nov 2, 2026
…version (#73) The error row still said a store without axes is refused when its version does not fix them; since the owner's decision in #129 no version fixes them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
guijacquemet
pushed a commit
that referenced
this pull request
Nov 2, 2026
docs/plan.md §12: main's question 60 (#129, OME-Zarr axes and calibration) is kept, and this PR's questions 62-64 become 61-63 so the numbers are unique and sequential; the references in contract §9.1, §11, §12 and plan §10 follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
guijacquemet
pushed a commit
that referenced
this pull request
Nov 2, 2026
Conflicts resolved hunk by hunk: - docs/plan.md: main's "Before the audit" entry (#82, #83, #98) kept, then PP-12's; main's questions 61 to 63 kept and PP-12's question renumbered 64. - run_inputs.py RunInputs.design(): main's strict read_confirmed_design, on the file PP-12's published_path names (the current generation's design). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
guijacquemet
pushed a commit
that referenced
this pull request
Nov 2, 2026
Conflicts: plan questions (main has 60 to 63; this branch's questions become 66 and 67, 64 and 65 being taken by #128) and the code-rule layers of pyproject.toml (size_checks and ngff_scale, both pure). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #72, fixes #73, fixes #94
Before-audit batch A (triage 2026-11-02): OME-Zarr axes and calibration. Design v0.4 §2, §3 and §9 apply: nothing guessed, nothing silent.
Summary (by module)
axes.py: newome_zarr_mapping. Every OME-Zarr image is matched by the roles its OME-NGFF axes declare, including one whose axis letters equal the mapping's. With the same arrangement, any confirmed role that is not the declared letter for that axis is refused ("contradicted").file_mapping_foruses it, so the consumer path has the same policy ([Audit/Scientific integrity] OME-Zarr with matching axis letters can be processed under contradictory confirmed roles #72).axis_review.py:review_axesresolves files in_resolve_filesand builds the OME-Zarr error in_ome_zarr_issues. Contradicted images getome_zarr_axes_mismatch, naming each one, e.g.declared ZYX, confirmed TYX: ctrl/a.ome.zarr. They never reachfile_mappings, so they are never read ([Audit/Scientific integrity] OME-Zarr with matching axis letters can be processed under contradictory confirmed roles #72).zarr_input.py: the version is read before the axes, andngff_axes(axes, version)refuses (NgffError→unreadable_ome_zarr) ([Audit/Scientific integrity] Missing axes metadata in NGFF 0.4/0.5 can silently default 5D images to TCZYX #73):t, c, z, y, x);axes, and a store withoutaxesthat states no version or another one (no confirmation path);axesthat are not a list.The blanket
except Exception+ debug log around the sizes is removed ([Sad Catapella B6][Scientific QA] Malformed explicit NGFF coordinate transforms are silently treated as unknown calibration #94).ngff_scale.py(new, pure):read_scalereturns the level or image scale together with plain-language problems: transformations not a list; a type other than scale, translation or identity; two scales; a scale stored in a file (path); not one number per axis; a value that is not a list of numbers; an X/Y/Z/T value that is not a positive finite number ([Sad Catapella B6][Scientific QA] Malformed explicit NGFF coordinate transforms are silently treated as unknown calibration #94).physical_sizes.py: newPhysicalSizes.invalid(the reason; not part of equality).ngff_physical_sizesrecords it instead of returning a barePhysicalSizes()([Sad Catapella B6][Scientific QA] Malformed explicit NGFF coordinate transforms are silently treated as unknown calibration #94).pixel_size_checks.py/dataset.py: new warninginvalid_physical_calibration, naming every image with its reason, also when all images are malformed. It is computed on the resolved sizes and goes once every size the malformed calibration leaves unknown is stated incalibration.csv; a time step cannot be stated there, so a lost time step of a time series stays named. InPIXEL_SIZE_CODESandCONSISTENCY_CODES, kept indiscovery_report.json([Sad Catapella B6][Scientific QA] Malformed explicit NGFF coordinate transforms are silently treated as unknown calibration #94).Docs: contract §2, §8, §11; user guide; plan question 60 (decided); AGENTS.md.
Owner decisions (2026-11-02), recorded in plan question 60
ome_zarr_axes_mismatch, not the axis-check codes, which offer conversion (an OME-Zarr image cannot be converted). AQaxis never gets a role.TCZYXfor 5-D arrays; changed in review). Stores without axes are refused, with no confirmation path.calibration.csv.Review (independent reviewer)
Commits: 718e8b5, 8fdf7de (merge of main with #126), eeae9d0, 67bdea5 (merge of main with #127).
open_ngff,inspect_imageandpreflight.ngff_axesloses its unusedndimparameter.invalid_physical_calibrationdisappeared once X and Y (and Z) were stated, even when the malformed scale had also lost the time step of a time series. The time step cannot be stated, so the loss became silent. The new_lost_rolescheck fixes this; 4 parametrised cases; the T case fails on e0e6c20.zyxstore into an experiment confirmedZYX → ZXY. That is exactly the [Audit/Scientific integrity] OME-Zarr with matching axis letters can be processed under contradictory confirmed roles #72 contradiction, now refused. The store is nowtzyxwith one time point, matched by role, so the test still checks the reuse of a changed chunk.file_mapping_forandreview_axesare the only resolvers, and the preview, sources, preflight and notebook all usefile_mapping_for;invalidwith a specific reason, and no silent fallback is left (no broad except on the scale path).run_experiment, 2 conditions × 2 images, CZYX, calibrated) on main 8db1f4a and on this branch:run_manifest.jsonanddiscovery_report.jsondiffer only in paths, mtimes and timestamps, andplane_histograms.csvis byte-identical.Tests
tests/test_ngff_axes_calibration.py: 35 tests. On main 8db1f4a, 30 fail and 5 pass (the controls).uvvenv, Python 3.11,.[dev,notebook,zarr], zarr 3.1.6, running as root):python tools/check.pypassed:test_discovery.py:665, permissions ignored as root: expected), 1 warning;Code standards (§9), measured
physical_sizes.py684 lines (baselined, 706 → 684). Newngff_scale.py113 lines;zarr_input.py439.review_axes67 executable lines (baselined, 106 → 67). New functions are all 40 lines or fewer._resolve_files10. Thenread_scaleandngff_axes8;ngff_physical_sizesand_level07.# noqa79 → 78 (ANN54 → 53); no new exemption.https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Generated by Claude Code