Repository navigation
same_objects is a one-to-one matching; size and plane-count warnings follow the confirmed roles (#67, #74) - #131
Merged
Conversation
The one-to-one counts took every object with any partner at the IoU threshold, so two children halving one parent counted as two matches and could give same_objects. The matches are now a maximum bipartite matching of the pairs at or above the threshold (Hopcroft-Karp on a sparse graph, per plane); its size is unique, so the counts are deterministic. The evidence adds the unmatched objects and the objects with several partners at the threshold. Report version 2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
different_sizes and different_plane_counts compared the header letters, also of plain stacks whose letters are not their roles: a plain QYX stack of (Y, X, C) arrays confirmed as YXC was compared by its X and channels (a real height difference missed) and gave "planes along Q". Preflight now leaves plain stacks out; AxisReview.combined_issues drops the header versions and recomputes both warnings with each image's confirmed roles (header letters for images with an axis error or without a mapping). The checks move to the pure size_checks module (metadata.py shrinks). Docs: contract 11 and 15.1, user guide, plan questions 60 and 61. 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
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
guijacquemet
marked this pull request as ready for review
November 2, 2026 20:18
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
…ding Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Plan questions 64 and 65 are now #128's; this PR's become 66 and 67. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Plan question 66 is now #133's; this PR's become 67 and 68. Baseline: this PR's lower metadata.py figures, #133's removal of the physical_sizes entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Contributor
Author
|
Independent review: merged as 86121db (merge commit; branch restored onto the PR head 4d2d0e2). Verified
Review commits
§9 figures (touched files)
Gate (own worktree and uv venv,
Not addressed (existing behaviour, outside #67's scope) Generated by Claude Code |
guijacquemet
pushed a commit
that referenced
this pull request
Nov 2, 2026
Conflict in plan §12 only: main's questions 67 and 68 kept, PP-12's question renumbered 69, its references in §10 updated. 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 #67, fixes #74
Both issues are fully fixed and tested. Version stays 0.4.0rc3. The branch is merged with main at feec007 (#129, #130).
#67:
same_objectsuses a one-to-one matchingDefect.
pair_countscounted every child and parent that had any partner at or abovesame_objects_iou. A 2:1 split therefore counted as 2/2 children and 1/1 parents matched, which gavesame_objects.Rule (deterministic, documented in contract §15.1 and plan question 67). For each plane, the matches are a maximum bipartite matching of the child/parent pairs whose IoU is at least the threshold. It is computed with
scipy.sparse.csgraph.maximum_bipartite_matching(Hopcroft-Karp) on a sparse graph, so no K x K matrix is built. scipy was already a dependency.New evidence keys:
children_not_matched,parents_not_matched,children_over_iou_with_several_parents,parents_over_iou_with_several_children.children_matched_one_to_oneandparents_matched_one_to_oneare kept, and are now equal.mask_relationships.jsonis now report version 2. The CLImaskscommand and the notebook both usescan_masks, so they get the same rule.HPMEC (MorphoRelate
ea19bb0,data/hpmec_perfusion, read-only; outputs in the scratch dir). The report is the same before and after, apart from the new keys and the version. This was checked again after the merge with main:same_objects[]cellsas a 4th type (scratch copy)same_objects, matched 146/146--same-objects-iou 0.1#74: size and plane-count warnings follow the confirmed roles
Defect.
different_sizesanddifferent_plane_countscompared header letters, including those of plain stacks, whose letters are not their roles.AxisReview.combined_issueskept these warnings after confirmation, so they were stale. Example: plain (Y, X, C) arrays read asQYXand confirmed asYXCmissed a real height difference (16 vs 32) and reported "planes along Q".Behaviour now:
check, preflight): the axes each header names are compared, and a plain stack is left out. Nothing is guessed.combined_issues(used byrun, the notebook's run and the conversion plan) drops the header versions. It recomputes both warnings with each image's confirmed roles (metadata.dimension_issues).The checks moved to a new pure module,
size_checks.py, sometadata.pyshrinks. One existing expectation changed (test_channel_count_follows_the_confirmed_channel_axis):IYXconfirmed with I as C no longer reportsdifferent_plane_counts, which is correct. The notebook's axis card still shows only the axis review's own issues; the corrected warnings appear in the run result (plan question 68).Plan questions: #128 (64, 65) and #133 (66) merged first, so this PR uses 67 and 68 (checked in review after merging main 491150a); #132 follows after them.
Tests that fail on main (checked against feec007)
tests/test_mask_matching.py: all 27 fail on main (7 tests, plus 20 brute-force reference cases).test_a_split_segmentation_is_not_the_same_objectsfails on the relation itself: main sayssame_objects, with matched 16/8.one_to_one_matches.tests/test_role_sizes.py: 8 of 8 fail on main (QYX→YXC, QYX→ZYX/TYX, IYX→TYX, named+plain, plain TIFF + OME-Zarr,run_experiment).tests/test_axes.py::test_channel_count_follows_the_confirmed_channel_axis(updated) fails on main.Gate (local, after merging main feec007)
ruff checkandruff format --checkpass (186 files).tools/check.py --rulespasses (exit 0).pytestwith.[dev,notebook,zarr]: 1887 passed, 1 skipped (review gate after its fixes: 1889 passed, 1 skipped) (test_discovery.py:665, running as root, as expected).§9 figures (against main feec007)
mask_scan.py519→574,metadata.py779→747 (756 before review),axes.py464→477,size_checks.py139 (new,pure).pair_counts47,one_to_one_matches5,_match_counts13,dimension_issues11,combined_issues5,plane_count_issues25,image_size_issues14;check_metadata97→96. Every function has at most 4 parameters, annotations and docstrings._check_image_sizesand_check_plane_counts(undocstringed). Lowered:check_metadata97→96 andmetadata.py779→756. Nothing added.# noqa: unchanged (ANN 53, PLR0913 3).Review fixes
size_checks.breakdownis the one summary helper;metadata._breakdowndelegates to it (the PR had copied it, §9 no duplicated helpers).metadata.py756→747 lines, baseline lowered.metadata.pyfigures and Micrometre conversions are always positive and finite; check and design exit 1 on errors (#93) #133's removedphysical_sizes.pyentries. Gate after it: 1978 passed, 2 skipped (test_discovery.py:665as root;test_cli_log.py:164from Links stay inside the experiment and masks folders; --log is checked before it opens (#81, #99) #128, on a case-sensitive file system).https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Generated by Claude Code