Tracking issue for the itk::ScaleLogarithmicTransform Jacobian correctness fix proposed in #6569 (commit 1), collecting the analysis, downstream footprint, and test results in one place. This is the independent half of #6569 and can land on its own; the coupled JointHistogram-MI fixes are tracked separately in #6570.
This issue is the focal point for ScaleLogarithmicTransform test/CI results — please report verification, CI outcomes, and downstream checks here.
This is a bug fix, not an enhancement. The old Jacobian was correct only by coincidence — at center = 0, where scale·p == scale·(p−center) — and wrong for any centered transform. The existing test exercised no Jacobian at all, so the coincidence was never even tested.
The defect and fix
ScaleLogarithmicTransform is parameterized by Log(scale) and (via ScaleTransform) maps p -> scale*(p - center) + center. ComputeJacobianWithRespectToParameters computed
jacobian(dim, dim) = scales[dim] * p[dim];
but ScaleTransform::ComputeJacobianWithRespectToParameters correctly differentiates about the center (j(dim,dim) = p[dim] - center[dim]), so the Log(scale) chain rule requires
jacobian(dim, dim) = scales[dim] * (p[dim] - center[dim]);
With a non-zero center the analytic Jacobian is wrong, and any Optimizerv4 driving a centered ScaleLogarithmicTransform received a wrong gradient. itkScaleLogarithmicTransformTest exercised no Jacobian at all, so nothing caught it; the PR adds a case (center (5,6,7), scales (2,3,4), point (10,10,10) → expected diagonal (10,12,12); the old code returns (20,30,40)).
Downstream footprint
The Jacobian is only exercised when a ScaleLogarithmicTransform is gradient-optimized about a non-zero center. Survey of the forest:
- ITK — no registration/optimization use in core. Referenced only by the transform factory registration (
itkTransformFactoryBase*, i.e. read/write) and Python wrapping (itkScaleLogarithmicTransform.wrap). So a Python user can construct and optimize it, but no in-tree pipeline does.
- SimpleITK — registered for transform I/O (
sitkTransform.cxx); not a standard optimization target in the registration framework.
- BRAINSTools —
GenericTransformImage.cxx only compares the transform-type string for file I/O / resampling; never optimizes it.
- ANTs — no source use (only the vendored ITK copy).
- elastix / ITKElastix — none.
Conclusion: essentially zero downstream registration impact — this is a latent-correctness fix. The only realistic exposure is an external/Python user directly optimizing a centered ScaleLogarithmicTransform. No baseline regeneration is required anywhere for this change, and it is CI-green in #6569.
release-5.4 backport consideration
Low-risk backport candidate. Because no in-tree or forest pipeline optimizes this transform, backporting the Jacobian fix to release-5.4 changes no existing registration baseline; it only makes the analytic Jacobian correct for the (rare) direct optimization case. If release-5.4 is still receiving correctness fixes, this is a clean, self-contained one to include (transform + test, no data changes). Contrast with the JHMI fixes (#6570), whose backport would change registration outputs and require baseline regeneration on the stable branch — a larger reproducibility decision.
Recommendation: stronger tests for the future
The defect survived because ScaleLogarithmicTransform had no Jacobian test — the coincidence at center = 0 was never exercised. Beyond the non-zero-center case this PR adds, the transform suite should:
- Assert
ComputeJacobianWithRespectToParameters against a finite-difference of the transform's TransformPoint at a non-zero center (catches any analytic-Jacobian error generically, for every transform type).
- Audit the other
MatrixOffsetTransformBase subclasses for the same gap — a transform whose Jacobian is never tested about a non-zero center is a latent version of this bug.
- Include the centered case in the shared transform test harness so new transforms inherit the coverage.
Checklist:
Tracking issue for the
itk::ScaleLogarithmicTransformJacobian correctness fix proposed in #6569 (commit 1), collecting the analysis, downstream footprint, and test results in one place. This is the independent half of #6569 and can land on its own; the coupled JointHistogram-MI fixes are tracked separately in #6570.This issue is the focal point for
ScaleLogarithmicTransformtest/CI results — please report verification, CI outcomes, and downstream checks here.This is a bug fix, not an enhancement. The old Jacobian was correct only by coincidence — at
center = 0, wherescale·p == scale·(p−center)— and wrong for any centered transform. The existing test exercised no Jacobian at all, so the coincidence was never even tested.The defect and fix
ScaleLogarithmicTransformis parameterized byLog(scale)and (viaScaleTransform) mapsp -> scale*(p - center) + center.ComputeJacobianWithRespectToParameterscomputedjacobian(dim, dim) = scales[dim] * p[dim];but
ScaleTransform::ComputeJacobianWithRespectToParameterscorrectly differentiates about the center (j(dim,dim) = p[dim] - center[dim]), so theLog(scale)chain rule requiresjacobian(dim, dim) = scales[dim] * (p[dim] - center[dim]);With a non-zero center the analytic Jacobian is wrong, and any
Optimizerv4driving a centeredScaleLogarithmicTransformreceived a wrong gradient.itkScaleLogarithmicTransformTestexercised no Jacobian at all, so nothing caught it; the PR adds a case (center (5,6,7), scales (2,3,4), point (10,10,10) → expected diagonal (10,12,12); the old code returns (20,30,40)).Downstream footprint
The Jacobian is only exercised when a
ScaleLogarithmicTransformis gradient-optimized about a non-zero center. Survey of the forest:itkTransformFactoryBase*, i.e. read/write) and Python wrapping (itkScaleLogarithmicTransform.wrap). So a Python user can construct and optimize it, but no in-tree pipeline does.sitkTransform.cxx); not a standard optimization target in the registration framework.GenericTransformImage.cxxonly compares the transform-type string for file I/O / resampling; never optimizes it.Conclusion: essentially zero downstream registration impact — this is a latent-correctness fix. The only realistic exposure is an external/Python user directly optimizing a centered
ScaleLogarithmicTransform. No baseline regeneration is required anywhere for this change, and it is CI-green in #6569.release-5.4 backport consideration
Low-risk backport candidate. Because no in-tree or forest pipeline optimizes this transform, backporting the Jacobian fix to
release-5.4changes no existing registration baseline; it only makes the analytic Jacobian correct for the (rare) direct optimization case. Ifrelease-5.4is still receiving correctness fixes, this is a clean, self-contained one to include (transform + test, no data changes). Contrast with the JHMI fixes (#6570), whose backport would change registration outputs and require baseline regeneration on the stable branch — a larger reproducibility decision.Recommendation: stronger tests for the future
The defect survived because
ScaleLogarithmicTransformhad no Jacobian test — the coincidence atcenter = 0was never exercised. Beyond the non-zero-center case this PR adds, the transform suite should:ComputeJacobianWithRespectToParametersagainst a finite-difference of the transform'sTransformPointat a non-zero center (catches any analytic-Jacobian error generically, for every transform type).MatrixOffsetTransformBasesubclasses for the same gap — a transform whose Jacobian is never tested about a non-zero center is a latent version of this bug.Checklist:
release-5.4backport (low-risk; no baseline impact)