Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed parameter preservation after identity #4485

Conversation

hjmjohnson
Copy link
Member

When setting a transform to represent an Identity mapping, it is crucial that the stationary component of the transform is preserved.

tfm.SetCenter( [1,2,3] );
tfm.SetIdentity();
out=tfm.GetCenter();
assert( out == [1,2,3] );

PR Checklist

  • No API changes were made (or the changes have been approved)
  • No major design changes were made (or the changes have been approved)
  • Added test (or behavior not changed)
    files (if any)

@hjmjohnson hjmjohnson self-assigned this Feb 28, 2024
@github-actions github-actions bot added type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Core Issues affecting the Core module labels Feb 28, 2024
@hjmjohnson hjmjohnson added type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances status:Confirmed Confirmed/reproduced issue on a different machine with same or similar settings to those reported area:Remotes Issues affecting the Remote module and removed type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Core Issues affecting the Core module labels Feb 28, 2024
@hjmjohnson hjmjohnson added this to the ITK 5.4.0 milestone Feb 28, 2024
@dzenanz dzenanz requested a review from blowekamp February 28, 2024 17:36
@hjmjohnson hjmjohnson force-pushed the fixed-parameter-preservation-after-identity branch from 96270fb to f427be5 Compare February 28, 2024 19:43
@github-actions github-actions bot added type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Core Issues affecting the Core module and removed type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances area:Remotes Issues affecting the Remote module labels Feb 28, 2024
@N-Dekker
Copy link
Contributor

Just for my understanding: how is that with transform types which (may not be not derived from MatrixOffsetTransformBase)? Do (or should) they always preserve the fixed parameters, whenever transform.SetIdentity() is called?

@hjmjohnson hjmjohnson force-pushed the fixed-parameter-preservation-after-identity branch from f427be5 to 981c53a Compare February 28, 2024 20:47
@hjmjohnson
Copy link
Member Author

hjmjohnson commented Mar 2, 2024

@N-Dekker FixedParameters should never change after being chosen, they represent the static component of the structure of the transform. Similar to template parameters for a function in C++. the "Parameters" represent the current state of the Transform (i.e. Not the structure of the transform).

The SetIdentity() function should change the state of the transform, not the structure of the transform.

Consider a displacement field transform. The "Parameters" are the vector values of the underlying image. The "FixedParameters" are the Size/Origin/Spacing/Direction components that define the underlying vector image. Setting the displacement field to an identity involves setting the vector values to all zeros, and should not modify the Size/Origin/Spacing/Direction elements of the underlying vector image.

@N-Dekker
Copy link
Contributor

N-Dekker commented Mar 2, 2024

Thanks for your clear explanation, @hjmjohnson Unfortunately I think my knowledge and understanding of MatrixOffsetTransformBase derived transforms just isn't sufficient yet 🤷

FixedParameters should never change after being chosen

MatrixOffsetTransformBase::SetIdentity() does zero-fill the m_Center. The values of m_Center are also part of FixedParameters, right? When you restore the previous values of FixedParameters, but you leave m_Center zero-filled, FixedParameters and m_Center will get out of sync, right? Isn't that a problem?

BTW, I won't stop this PR, I'm just trying to understand, because it seems a bit tricky to me!

@N-Dekker
Copy link
Contributor

N-Dekker commented Mar 3, 2024

Could you possibly still explain where in the original SetIdentity() implementation the FixedParameters gets modified? Because I don't see anything like m_FixedParameters = someNewValue here:

MatrixOffsetTransformBase<TParametersValueType, VInputDimension, VOutputDimension>::SetIdentity()
{
m_Matrix.SetIdentity();
m_MatrixMTime.Modified();
m_Offset.Fill(OutputVectorValueType{});
m_Translation.Fill(OutputVectorValueType{});
m_Center.Fill(InputPointValueType{});
m_Singular = false;
m_InverseMatrix.SetIdentity();
m_InverseMatrixMTime = m_MatrixMTime;
this->Modified();
}

@hjmjohnson
Copy link
Member Author

@N-Dekker The problem (at least for the Euler3DTransform) is explicitly that the m_Center is being filled with all zeros. Initially I tried removing filling the center with all zeros, but that caused a family of "Scale*Transforms" to start failing regression tests. The issue, I think, is that the behavior of the m_Center and m_Offset parameters can be manipulated by "SetFixedParameters" of the child classes.

My solution works under the principle that transforms can be properly configured with only "SetParamters" and "SetFixedParameters" from the child classes (as is done in the TransformIO mechansims). Under this known behavior of all transforms, I concluded that restoring the fixed parameters would set the state of the class correct for whatever weird behavior a child class may choose to do.

Well. ...... that was my rational for this approach which a) Passes all regression tests, and b) fixes the nasty conceptual bug I ran into when using the Eurler3DTransform with SetIdentity.

@N-Dekker
Copy link
Contributor

N-Dekker commented Mar 4, 2024

Thanks again Hans. I just did a rebuild of the latest master branch, having locally removed the questionable m_Center zero-filling:

m_Center.Fill(InputPointValueType{});

I'll try the tests in a moment...

Update: as far as I can see, the Scale*Transform tests are passing successfully on my PC (VS2019 Debug), after having locally removed the m_Center zero-filling:

1>          Start 2931: itkScaleSkewVersor3DTransformTest
1>2932/3033 Test #2931: itkScaleSkewVersor3DTransformTest ......................................................................   Passed    0.36 sec
1>          Start 2932: itkComposeScaleSkewVersor3DTransformTest
1>2933/3033 Test #2932: itkComposeScaleSkewVersor3DTransformTest ...............................................................   Passed    0.30 sec
...
1>          Start 2937: itkScaleVersor3DTransformTest
1>2938/3033 Test #2937: itkScaleVersor3DTransformTest ..........................................................................   Passed    0.27 sec
...
1>          Start 2945: itkScaleLogarithmicTransformTest
1>2946/3033 Test #2945: itkScaleLogarithmicTransformTest .......................................................................   Passed    0.29 sec
..
1>          Start 2947: itkScaleTransformTest
1>2948/3033 Test #2947: itkScaleTransformTest ..................................................................................   Passed    0.28 sec

Which specific regression failures did you get? Do you think they were major failures, or possibly just rounding errors?

@hjmjohnson hjmjohnson force-pushed the fixed-parameter-preservation-after-identity branch from 981c53a to 8453403 Compare March 6, 2024 00:45
Comment on lines -102 to +104
m_Center.Fill(InputPointValueType{});
// Fixed parameters must be preserved when setting the transform to identity
// the center is part of the stationary fixed parameters
// and should not be modified by SetIdentity. m_Center.Fill(InputPointValueType{});
Copy link
Contributor

@N-Dekker N-Dekker Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for giving this approach a try, Hans! I think it's the right way to go. As far as I can see, the Scale*Transform tests still pass 👍 (Right? Please check!) Only itkSimilarity2DTransformTest appears to fail, but I think itkSimilarity2DTransformTest itself is wrong! I'll have another look.


I see, itkSimilarity2DTransformTest assumes that transform->SetIdentity() also resets the center. If we agree that that assumption should be dropped (the main purpose of your PR), the test should just manually reset the center. Specifically here, around line 159:

// 15 degrees in radians
transform->SetIdentity();

The test fails because it tries to do the 15 degrees rotations from the wrong center. It will pass when a transform->SetCenter({}) is added, either before or after transform->SetIdentity().

Hope that helps!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@N-Dekker Thanks. I won't be able to spend time digging into this until after next week. I appreciate any assistance I can get.

2877 - itkSimilarity2DTransformTest (Failed)

Copy link
Contributor

@N-Dekker N-Dekker Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, just adding transform->SetCenter({}) to line 159 of itkSimilarity2DTransformTest.cxx should make the CI happy.

Conceptually, people should no longer assume that transform->SetIdentity() "automagically" resets the center. It's a (potentially) breaking change. But I think it's a correct one.

When setting a transform to represent an Identity
mapping, it is crucial that the stationary component
of the transform is preserved.

```python
tfm.SetCenter( [1,2,3] );
tfm.SetIdentity();
out=tfm.GetCenter();
assert( out == [1,2,3] );
```

===============

Add test demonstrating change in fixed paramers

When applying SetIdentity(), the fixed parameters should not be modified.
The fixed paramers represent the stationary component of the transform
and setting the transform back to an identity should not modify the
stationary components.
@hjmjohnson hjmjohnson force-pushed the fixed-parameter-preservation-after-identity branch from 8453403 to 0ccf872 Compare March 12, 2024 19:42
Copy link
Contributor

@N-Dekker N-Dekker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much, Hans! 👍

@N-Dekker
Copy link
Contributor

I think this PR is ready for merge, but I would like to see one more approval! Especially because there is a tiny little chance that some user may experience slightly different behavior, because with this PR, MatrixOffsetTransformBase::SetIdentity() no longer resets the center. Again, I think the PR is entirely correct, but one more approval would be nice!

@hjmjohnson hjmjohnson merged commit db9cfea into InsightSoftwareConsortium:master Mar 17, 2024
12 checks passed
@hjmjohnson hjmjohnson deleted the fixed-parameter-preservation-after-identity branch March 17, 2024 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:Core Issues affecting the Core module status:Confirmed Confirmed/reproduced issue on a different machine with same or similar settings to those reported type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants