Skip to content

ScaleLogarithmicTransform Jacobian ignores the transform center: analysis and downstream impact (tracks #6569) #6571

Description

@hjmjohnson

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.
  • BRAINSToolsGenericTransformImage.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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions