Skip to content

ENH: Add MinMaxCurvatureFlow alternate baselines for ITK 3D threshold fix - #2627

Merged
blowekamp merged 1 commit into
SimpleITK:mainfrom
hjmjohnson:update-minmax-baselines-itk6619
Aug 28, 2026
Merged

ENH: Add MinMaxCurvatureFlow alternate baselines for ITK 3D threshold fix#2627
blowekamp merged 1 commit into
SimpleITK:mainfrom
hjmjohnson:update-minmax-baselines-itk6619

Conversation

@hjmjohnson

@hjmjohnson hjmjohnson commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Adds .1.nrrd alternate baselines for the MinMaxCurvatureFlowImageFilter defaults and longer tests, so they pass with both current ITK and an ITK containing InsightSoftwareConsortium/ITK#6603 (3D polar-angle threshold fix; full context in InsightSoftwareConsortium/ITK#6619).

Data: the two objects are staged in SimpleITK/SimpleITKExternalData#50 — CI cannot fetch them until that PR merges.

Why the output changes, and by how much

ITK's 3D MinMaxCurvatureFlowFunction::ComputeThreshold normalized the gradient to length StencilRadius (2) instead of unit length before acos(), silently selecting the wrong polar angle since 2002. ITK#6603 restores the published algorithm (Sethian 1999). Measured on RA-Float.nrrd with this repo's exact test parameters, the center-slice RMS versus the current baselines is 343.0 (longer) against a tolerance of 0.01. The 2D dispatch and BinaryMinMaxCurvatureFlowImageFilter (user-supplied threshold, never calls ComputeThreshold) are unaffected — their baselines need no change.

How the alternates were generated and validated

The baselines are the actual harness outputs: BasicFilters.MinMaxCurvatureFlowImageFilter was run via ctest against an ITK main build containing the threshold fix, and the failing-compare outputs written by ImageCompare (center z-slice, 64×64×1 float NRRD) were hashed directly, byte-identical across two runs. With the alternates placed in the ExternalData store, the test passes against ITK main; the primary baselines are untouched, so current-ITK builds keep passing via ImageCompare's best-RMS selection over the name.N.nrrd series (sitkImageCompare.cxx). The generated test commands reference baselines as DATA{...nrrd,:}, so the .1.nrrd series members are fetched automatically — no CMake changes needed.

An earlier revision of this PR carried transcribed hashes that did not correspond to any real file; the content links now hold the verified hashes of the uploaded objects.

@blowekamp

Copy link
Copy Markdown
Member

Note: the two data objects are pending upload to data.kitware.com — CI will fail to fetch them until then.

Please create a PR for SimpleITK/SimpleITKExternalData with the data. I am unfortunately unable to locate developer documentation on uploading data. Hopefully making the PR to the data repo is straight forward enough.

@blowekamp

Copy link
Copy Markdown
Member

@hjmjohnson Please see the newly added sitk-upload-binary-data skill to upload data.

@hjmjohnson

Copy link
Copy Markdown
Contributor Author

Related to : InsightSoftwareConsortium/ITK#6667 for minimizing inter-project dependancies on test cases.

@hjmjohnson

Copy link
Copy Markdown
Contributor Author

Data uploaded per the sitk-upload-binary-data skill: SimpleITK/SimpleITKExternalData#50 (draft).

The previous content-link hashes were transcribed and did not match any real file; the branch is now rebased onto main with content links pointing at the verified regenerated outputs (byte-identical across two ctest runs against ITK main with the threshold fix). The test passes locally against ITK main with the alternates in the object store, and the untouched primary baselines keep current-ITK builds green via the existing name.N.nrrd best-RMS selection.

@hjmjohnson
hjmjohnson marked this pull request as ready for review July 24, 2026 16:55
@blowekamp
blowekamp force-pushed the update-minmax-baselines-itk6619 branch from 1cb3913 to 6654ed2 Compare August 27, 2026 21:54
… fix

ITK commit 2a04261664 ("BUG: Fix polar angle in MinMaxCurvatureFlowFunction
threshold", merged as InsightSoftwareConsortium/ITK#6603,
InsightSoftwareConsortium/ITK#6575 item context in #6619) fixes
MinMaxCurvatureFlowFunction::ComputeThreshold normalizing the gradient
to the stencil radius (2) instead of unit length before acos(), which
had silently selected the wrong polar angle since 2002. This changes
MinMaxCurvatureFlowImageFilter output on 3D volumes.

Add the post-fix center slices as .1.nrrd alternate baselines so the
defaults and longer tests pass with both current and fixed ITK.
Verified locally: BasicFilters.MinMaxCurvatureFlowImageFilter and
Python.MinMaxCurvatureFlowImageFilter both pass against an ITK build
containing the fix, using the corrected .1.nrrd content hashes (see
below).

Note: BinaryMinMaxCurvatureFlowFunction never calls ComputeThreshold,
so it is unaffected by ITK#6603 itself. However, it inherits
MinMaxCurvatureFlowFunction's stencil radius (2) and is therefore also
perturbed by a separate, later ITK commit, 4f0b3147be ("BUG: Decouple
CurvatureFlowFunction derivative scale from radius",
InsightSoftwareConsortium/ITK#6575 item B8), which fixes
CurvatureFlowFunction::ComputeUpdate() understating the derivative by
1/radius^2 for any subclass that repurposes GetRadius() for a larger
neighborhood, as MinMaxCurvatureFlowFunction (and by inheritance
BinaryMinMaxCurvatureFlowFunction) does. BasicFilters.
BinaryMinMaxCurvatureFlowImageFilter's defaults/longer baselines will
need their own alternates for that fix; tracked as a follow-up, not
included here.

Fixup: the defaults.1.nrrd and longer.1.nrrd content-link hashes in an
earlier revision did not match the objects actually uploaded to
SimpleITK/SimpleITKExternalData#50 (stale/transcribed hashes that
resolved on no mirror), which aborted the whole superbuild at the
ExternalData fetch step and cascaded into unrelated Java/R test
failures. Corrected to the real uploaded object hashes, confirmed
against the S3 mirror and validated locally as above.
@blowekamp
blowekamp force-pushed the update-minmax-baselines-itk6619 branch from 6654ed2 to 39d5053 Compare August 28, 2026 00:14
@blowekamp
blowekamp self-requested a review August 28, 2026 17:31
@blowekamp
blowekamp merged commit 6441ea4 into SimpleITK:main Aug 28, 2026
10 checks passed
blowekamp added a commit that referenced this pull request Aug 29, 2026
ITK commit 4f0b3147be2 ("BUG: Decouple CurvatureFlowFunction
derivative scale from radius", ITK issue #6575 item B8) fixed
CurvatureFlowFunction::ComputeUpdate(): it always samples immediate
(1-pixel-stride) neighbors, but scaled derivatives by dividing by
GetRadius(). Any subclass repurposing the radius for something else --
such as MinMaxCurvatureFlowFunction's stencil radius -- understated
the update by 1/radius^2 (4x at the default stencil radius of 2).

BinaryMinMaxCurvatureFlowFunction::ComputeUpdate() inherits this code
path unmodified (calls straight through to
CurvatureFlowFunctionType::ComputeUpdate), and SimpleITK's
BinaryMinMaxCurvatureFlowImageFilter defaults StencilRadius to 2, so
it hits the same bug every step. This is a sibling bug to the one
already fixed in #2627 for the non-binary MinMaxCurvatureFlowImageFilter,
but via a different ITK commit -- #2627 correctly noted Binary was
unaffected by *its* fix (the ComputeThreshold polar-angle bug), since
this is a separate commit.

Adds .1.nrrd alternate baselines (ImageCompare picks best-RMS across
the name.N.nrrd series) so the defaults/longer tests pass against both
pre- and post-fix ITK, without touching the primary baselines. Data
staged in SimpleITK/SimpleITKExternalData#54.

Verified the harness output is:
- byte-identical (sha512) across two separate runs
- pixel-identical between gzip-compressed and uncompressed NRRD
  encodings
- pixel-identical across C++, Python, and Java bindings

All BasicFilters/Python/Java tests pass locally against ITK main.
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