test(3d morphology): assert the five PCA axis features against MIRP, and two MATLAB rows nothing checked - #434
Open
darkclad wants to merge 2 commits into
Open
test(3d morphology): assert the five PCA axis features against MIRP, and two MATLAB rows nothing checked#434darkclad wants to merge 2 commits into
darkclad wants to merge 2 commits into
Conversation
added 2 commits
August 14, 2026 14:21
…and two MATLAB rows nothing checked Closes the five 3D morphology rows that read status=vetted, oracle=mirp with no in-tree oracle assertion, plus two more the family plan did not count. The five axis features ---------------------- 3MAJOR_AXIS_LEN, 3MINOR_AXIS_LEN, 3LEAST_AXIS_LEN, 3ELONGATION and 3FLATNESS carried a mirp verdict from an offline harness run (source=tracker) with target_test naming a _regression file. Nothing in the tree compared them against MIRP; the only thing touching them was the coverage sweep, which pins Nyxus' own output as a snapshot. gen_morphology3d_mirp.py now runs MIRP 2.6.0 against the segmented phantom and test_3d_morphology_mirp.h asserts all five. Same definition on both sides - 4*sqrt of the mask covariance eigenvalues, and their ratios - so the agreement is exact to double precision: 3MAJOR_AXIS_LEN 104.70681271508683 rel 0 3MINOR_AXIS_LEN 88.30145986864228 rel 0 3LEAST_AXIS_LEN 71.51449974198198 rel 2.0e-16 3ELONGATION 0.8433210559938976 rel 0 3FLATNESS 0.6829975804590384 rel 1.6e-16 Asserted at rel=1e-9, far tighter than SPEC 7's rel=1e-3 same-definition tier, because that is what the measurement supports. The generator checks the identities the old defect broke -------------------------------------------------------- This family carried an eigenvalue-ordering defect that produced 3LEAST_AXIS_LEN > 3MAJOR_AXIS_LEN and 3FLATNESS > 1, both structurally impossible. It is fixed in 3d_surface.cpp and these are the corrected values. The generator now asserts, on MIRP's own output, that MAJOR >= MINOR >= LEAST > 0, that ELONGATION and FLATNESS lie in [0,1], and that each equals its defining ratio - so a misconfigured oracle run is caught before anything is pinned. No _invariant file is added: the five oracle pins fix the exact values on this fixture and are strictly stronger than the bounds would be there. Two rows the plan did not count ------------------------------- 3VOXEL_VOLUME and 3VOLUME_CONVEXHULL read status=vetted, oracle=matlab and had a MATLAB golden and a stated band in morphology_3d_matlab_ref_vals/_ref_tols - but no oracle-named test asserted them. test_3d_morphology_matlab.h registered exactly one function, for 3MESH_VOLUME. The only thing comparing the other two against MATLAB was the parameterized sweep in test_3d_morphology_coverage.h, whose case names carry no oracle token, so the claim rested on a test that does not say what it checks (SPEC 6.2). The report generator misses this the same way it missed two rows in 2D morphology: a feature name in an oracle file counts as coverage whether an assertion reads it or only a table does. Both now have an assertion through the existing helper, goldens and bands. Both pass. MATLAB cannot be re-run, so MIRP cross-checks it ------------------------------------------------ Three rows claim oracle=matlab and revet step 3 says to run every claimed oracle. Not possible here - no licence, and Octave's image package has no regionprops3 - and the goldens have no in-repo generator (not_covered.md C). The generator prints the corresponding MIRP quantities instead, unpinned: voxel volume MIRP 274432.0 MATLAB 274432.0 exact convex-hull volume MIRP 496958.32 MATLAB 497824.0 0.17% Both MATLAB goldens are independently corroborated, which also relocates the disagreement: Nyxus' 3VOLUME_CONVEXHULL of 478516 is 3.6% from MATLAB and 3.7% from MIRP while the two tools sit 0.17% apart, so the difference is Nyxus' discrete voxel hull against two triangulated ones - which is what the existing 5% band documents, now with a second measurement behind it. The surface-area convention gap stays open ------------------------------------------ 3AREA counts exposed voxel faces (59992) where MIRP integrates a marching-cubes mesh (46739), a 28% convention difference that no tolerance turns into an agreement. 3AREA and the five features derived from it stay status=regression, with the reason recorded per row rather than left as a bare absence. Settling it changes six public feature values and belongs on its own branch. Test file cleanup ----------------- test_3d_morphology_common.h carried a dead #if 0 block - a superseded copy of the whole fixture, ending in a line of asterisks that is not valid C++ and only compiled because it was disabled. Removed. It also included test_ref_vals.h while declaring no reference table. Include hygiene across the family: _common.h relied transitively on <string>, <tuple>, <vector> and helpers/fsystem.h; _matlab.h named Pixel3 and Nyxus::calc_eigvals without including features/pixel.h or helpers/helpers.h, and used std::abs/std::vector without <cmath>/<vector>; _regression.h relied on <string>. All now direct. Three headers carried "Migrated from test_3d_shape.h (Wave 8)" history, which belongs in the audit report. Registry -------- All 14 rows get a real config_recipe id (three new: morphology3d.mirp_ibsi, morphology3d.matlab_regionprops3, morphology3d.regression_ut_phantom - one fixture, three benchmarks, so unusually they ARE comparable to each other, which is what makes the MIRP cross-check meaningful), a real tolerance, target_test cleared, source moved off tracker, and current_test synced to the files that actually cover each feature. Verified: runAllTests 780/780 on Windows and under ASan+UBSan on Linux; pytest tests/python/ full directory (92 passed, 1 skipped); check_coverage.py --check, check_test_names.py --check and audit/scan_morphology3d_coverage.py --check all clean; gen_morphology3d_mirp.py re-verifies all five goldens and all four structural identities against a fresh MIRP 2.6.0 run.
…cord the circularity check
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.
Closes the five 3D morphology rows that read status=vetted, oracle=mirp with no in-tree oracle assertion, plus two more the family plan did not count.
The five axis features
3MAJOR_AXIS_LEN, 3MINOR_AXIS_LEN, 3LEAST_AXIS_LEN, 3ELONGATION and 3FLATNESS carried a mirp verdict from an offline harness run (source=tracker) with target_test naming a _regression file. Nothing in the tree compared them against MIRP; the only thing touching them was the coverage sweep, which pins Nyxus' own output as a snapshot.
gen_morphology3d_mirp.py now runs MIRP 2.6.0 against the segmented phantom and test_3d_morphology_mirp.h asserts all five. Same definition on both sides - 4*sqrt of the mask covariance eigenvalues, and their ratios - so the agreement is exact to double precision:
3MAJOR_AXIS_LEN 104.70681271508683 rel 0
3MINOR_AXIS_LEN 88.30145986864228 rel 0
3LEAST_AXIS_LEN 71.51449974198198 rel 2.0e-16
3ELONGATION 0.8433210559938976 rel 0
3FLATNESS 0.6829975804590384 rel 1.6e-16
Asserted at rel=1e-9, far tighter than SPEC 7's rel=1e-3 same-definition tier, because that is what the measurement supports.
The generator checks the identities the old defect broke -------------------------------------------------------- This family carried an eigenvalue-ordering defect that produced 3LEAST_AXIS_LEN > 3MAJOR_AXIS_LEN and 3FLATNESS > 1, both structurally impossible. It is fixed in 3d_surface.cpp and these are the corrected values. The generator now asserts, on MIRP's own output, that MAJOR >= MINOR >= LEAST > 0, that ELONGATION and FLATNESS lie in [0,1], and that each equals its defining ratio - so a misconfigured oracle run is caught before anything is pinned. No _invariant file is added: the five oracle pins fix the exact values on this fixture and are strictly stronger than the bounds would be there.
Two rows the plan did not count
3VOXEL_VOLUME and 3VOLUME_CONVEXHULL read status=vetted, oracle=matlab and had a MATLAB golden and a stated band in morphology_3d_matlab_ref_vals/_ref_tols - but no oracle-named test asserted them. test_3d_morphology_matlab.h registered exactly one function, for 3MESH_VOLUME. The only thing comparing the other two against MATLAB was the parameterized sweep in test_3d_morphology_coverage.h, whose case names carry no oracle token, so the claim rested on a test that does not say what it checks (SPEC 6.2). The report generator misses this the same way it missed two rows in 2D morphology: a feature name in an oracle file counts as coverage whether an assertion reads it or only a table does. Both now have an assertion through the existing helper, goldens and bands. Both pass.
MATLAB cannot be re-run, so MIRP cross-checks it
Three rows claim oracle=matlab and revet step 3 says to run every claimed oracle. Not possible here - no licence, and Octave's image package has no regionprops3 - and the goldens have no in-repo generator (not_covered.md C). The generator prints the corresponding MIRP quantities instead, unpinned:
voxel volume MIRP 274432.0 MATLAB 274432.0 exact
convex-hull volume MIRP 496958.32 MATLAB 497824.0 0.17%
Both MATLAB goldens are independently corroborated, which also relocates the disagreement: Nyxus' 3VOLUME_CONVEXHULL of 478516 is 3.6% from MATLAB and 3.7% from MIRP while the two tools sit 0.17% apart, so the difference is Nyxus' discrete voxel hull against two triangulated ones - which is what the existing 5% band documents, now with a second measurement behind it.
The surface-area convention gap stays open
3AREA counts exposed voxel faces (59992) where MIRP integrates a marching-cubes mesh (46739), a 28% convention difference that no tolerance turns into an agreement. 3AREA and the five features derived from it stay status=regression, with the reason recorded per row rather than left as a bare absence. Settling it changes six public feature values and belongs on its own branch.
Test file cleanup
test_3d_morphology_common.h carried a dead #if 0 block - a superseded copy of the whole fixture, ending in a line of asterisks that is not valid C++ and only compiled because it was disabled. Removed. It also included test_ref_vals.h while declaring no reference table. Include hygiene across the family: _common.h relied transitively on , , and helpers/fsystem.h; _matlab.h named Pixel3 and Nyxus::calc_eigvals without including features/pixel.h or helpers/helpers.h, and used std::abs/std::vector without /; _regression.h relied on . All now direct. Three headers carried "Migrated from test_3d_shape.h (Wave 8)" history, which belongs in the audit report.
Registry
All 14 rows get a real config_recipe id (three new: morphology3d.mirp_ibsi, morphology3d.matlab_regionprops3, morphology3d.regression_ut_phantom - one fixture, three benchmarks, so unusually they ARE comparable to each other, which is what makes the MIRP cross-check meaningful), a real tolerance, target_test cleared, source moved off tracker, and current_test synced to the files that actually cover each feature.
Verified: runAllTests 780/780 on Windows and under ASan+UBSan on Linux; pytest tests/python/ full directory (92 passed, 1 skipped); check_coverage.py --check, check_test_names.py --check and audit/scan_morphology3d_coverage.py --check all clean; gen_morphology3d_mirp.py re-verifies all five goldens and all four structural identities against a fresh MIRP 2.6.0 run.