Repository navigation
Conversation
|
@ntustison could you take a look when you have a moment? This makes TimeVaryingBSplineVelocityFieldImageRegistrationMethod (and its transform and parameters adaptor) give identical results with GlobalReleaseDataFlag on, by grafting the images that internal filters would otherwise release while they are still in use. |
|
The Pixi-Cxx (macos-15) failure is unrelated: |
8bf17af to
c968cc5
Compare
3c00c76 to
e64c4a9
Compare
|
The ARMBUILD-x86_64-rosetta failure is unrelated: |
|
@hjmjohnson, could you rerun the failed ARMBUILD-x86_64-rosetta job (https://github.com/InsightSoftwareConsortium/ITK/actions/runs/41748468814/job/126307315016)? I can't rerun jobs myself. |
ImageAdaptor::Graft copied the pixel container but not the pixel accessor, so a graft of an NthElementImageAdaptor or of a VectorImageToImageAdaptor read element or component 0, whatever the source selected. Graft the adapted image, which also carries a VectorImage's number of components, then copy the accessor. A GoogleTest reads both kinds of graft at every pixel, before and after UpdateOutputInformation.
…DataFlag With DataObject::GlobalReleaseDataFlag on, internal mini-pipelines released inputs that are read again: the virtual domain (a resampler reference image), the level images, the masks, the transform fields fed to the composers, inverters and integrators, and the metric images fed to the gradient filters. Feed those pipelines grafts, which share the buffers, and set resampler geometry with SetOutputParametersFromImage. The velocity field interpolator points back at the velocity field after integration. Registration results are unchanged. GoogleTests cover each case with the flag on, including adaptor inputs to the metric.
…ase flag With DataObject::GlobalReleaseDataFlag on, internal filters released inputs that are read again: the transform's control point lattice (fed to the B-spline filter and to the adaptor's component selectors), the sampled velocity field shared by the forward and inverse integrators, and the virtual domain, level images and fixed mask fed to the registration's resamplers. Feed those filters grafts, which share the buffers, and set resampler geometry with SetOutputParametersFromImage. Results are unchanged. GoogleTests compare the registration, with and without masks, with the flag off and on.
e64c4a9 to
61a2cab
Compare
Makes
TimeVaryingBSplineVelocityFieldImageRegistrationMethodgive the same result withDataObject::GlobalReleaseDataFlagon as off. Stacked on #7095; only the last commit (8bf17af) is new.Root cause
With the flag on, every internal filter releases its inputs after it runs. Several of those inputs are read again later. Turning the flag on in a small 2-D registration and fixing the first failure each time found:
TimeVaryingBSplineVelocityFieldTransformParametersAdaptorfeeds the transform's control point lattice to oneVectorIndexSelectionCastImageFilterper component. The first selector releases the lattice, and the second throws "region is outside of buffered region".TimeVaryingBSplineVelocityFieldTransform::IntegrateVelocityFieldfeeds the lattice toBSplineControlPointImageFilter, which releases the transform's parameters.ImageMaskSpatialObject::IsInsideInObjectSpace.Fix
Each of those filters now gets a graft, which shares the buffer, so no data is copied and results are unchanged. The registration uses #7095's
MakeGrafthelper. Its resamplers now set their geometry withSetOutputParametersFromImage(virtualDomainImage), the same change #7095 made in SyN.Sites left as they are, because nothing reads them again after the release:
AddImageFilterinput inUpdateTransformParameters, since the old lattice is replaced by the sum on the next line. The registration later reads only its metadata.The multi-metric resampler branch got the same change as the single-metric branch. The tests run only the single-metric path, as in #7095.
Tests
There are two new cases in #7095's
itkSyNImageRegistrationMethodReleaseDataGTest.cxx: a two-level 32x32 time-varying B-spline registration, unmasked and masked. Each compares the flag-on displacement and inverse fields exactly (bitwise) with a flag-off run, and checks that the result is nonzero.SetOutputParametersFromImage(back to the reference image)AI assistance
Tool: Claude Code (claude-opus-5-5). Role: found the failing sites by running with the flag on, wrote the fix and tests, and ran the mutation checks. All code was reviewed and tested locally before committing.