# Reading Arbitrary Transforms, Compute Something if Linear

**URL:** https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553
**Category:** Engineering
**Created:** [April 5, 2024, 3:02pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553 "2024-04-05T15:02:04Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![gdevenyi](https://discourse.itk.org/user_avatar/discourse.itk.org/gdevenyi/32/355_2.png) [@gdevenyi](https://discourse.itk.org/u/gdevenyi)
#### Post date: [April 5, 2024, 3:02pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/1 "2024-04-05T15:02:04Z")

</div>

I’m working on trying to extend the `antsTransformInfo` tool to print the Determinant of a transform if its Linear as part of its summary information.

The existing implementation is very very simple, a copy of an ITK example:

> <https://github.com/ANTsX/ANTs/blob/master/Examples/antsTransformInfo.cxx>

The transform IO seems to not need to know anything about the transform, not the dimension, nor the type, and immediately supports all the ITK transform types, and can print a summary.

I implemented a partial version for linear transforms, and I’ve already had to instantiate 2D and 3D handlers separately, and this doesn’t support unpacking a composite transform at the least, and probably has other corner cases where it will fall over.

> <https://github.com/ANTsX/ANTs/pull/1712/files>
>
> I'd like to be able to easily extract the determinant of affine transforms and a…ntsTransformInfo seems like the right place.
> 
> The function has been refactored to handle reading errors.
> 
> Based primarily off
> https://github.com/InsightSoftwareConsortium/ITK/blob/master/Examples/IO/TransformReadWrite.cxx
> 
> Things that aren't done:
> \- I don't know how to automatically handle the 2D vs 3D transforms. The previous simple read/print code didn't seem to need it whereas this version does.

Am I going about this the wrong way? Is there a better way? I want this to support reading arbitrary ITK transforms and print the summary object, and if it’s Linear, add the Determinant.

Or, is the better solution to add the Determinant to all Linear transform summaries in ITK?

Thanks for your advice…

---

<div class="post-metadata">

### Author: ![cookpa](https://discourse.itk.org/user_avatar/discourse.itk.org/cookpa/32/255_2.png) [@cookpa](https://discourse.itk.org/u/cookpa)
#### Post date: [April 17, 2024, 8:03pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/2 "2024-04-17T20:03:08Z")

</div>

I think the 2D vs 3D instantiation can be solved by templating over dimension.

For determining type, maybe this example would help?

[https://itk.org/Doxygen/html/Examples\_2IO\_2TransformReadWrite\_8cxx-example.html](https://itk.org/Doxygen/html/Examples_2IO_2TransformReadWrite_8cxx-example.html)

```auto
  using ReadCompositeTransformType =
    itk::CompositeTransform<ReadScalarType, Dimension>;
  auto it = transforms->begin();
  if (!strcmp((*it)->GetNameOfClass(), "CompositeTransform"))
  {
    ReadCompositeTransformType::Pointer compositeRead =
      static_cast<ReadCompositeTransformType *>((*it).GetPointer());
    compositeRead->Print(std::cout);
  }

```

---

<div class="post-metadata">

### Author: ![blowekamp](https://discourse.itk.org/user_avatar/discourse.itk.org/blowekamp/32/79_2.png) [@blowekamp](https://discourse.itk.org/u/blowekamp)
#### Post date: [April 17, 2024, 8:14pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/3 "2024-04-17T20:14:40Z")

</div>

You can see the initial logic for loading an arbitrary Transform transforms here:

> <https://github.com/SimpleITK/SimpleITK/blob/05d85af0f48a22fc0ee3213a561a0ce124a0075c/Code/Common/src/sitkTransform.cxx#L653-L712>

The SimpleITK Transform constructor ends up doing a dynamic cast to determine what is the concrete transform type.

:edit: Additionally, you probably only need to cast to “MatrixOffsetTransformBase” to support just about all of the linear ITK transforms.

---

<div class="post-metadata">

### Author: ![cookpa](https://discourse.itk.org/user_avatar/discourse.itk.org/cookpa/32/255_2.png) [@cookpa](https://discourse.itk.org/u/cookpa)
#### Post date: [April 17, 2024, 8:36pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/4 "2024-04-17T20:36:13Z")

</div>

Thanks @blowekamp!

---

<div class="post-metadata">

### Author: ![gdevenyi](https://discourse.itk.org/user_avatar/discourse.itk.org/gdevenyi/32/355_2.png) [@gdevenyi](https://discourse.itk.org/u/gdevenyi)
#### Post date: [May 30, 2024, 4:21pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/5 "2024-05-30T16:21:12Z")

</div>

Thanks everyone. I’ve managed to successfully handle affine vs composite transforms, however, I can’t find a way to “unpack” a composite transform.

I expected it to also be a GetTransformList but that doesn’t seem to be the case.

Is there a way to get an iterator for a CompositeTransform like I do for a list?

```auto
 const TransformReaderType::TransformListType * transforms = reader->GetTransformList();
for (auto it = transforms->begin(); it != transforms->end(); ++it)

```

---

<div class="post-metadata">

### Author: ![lassoan](https://discourse.itk.org/user_avatar/discourse.itk.org/lassoan/32/27_2.png) [@lassoan](https://discourse.itk.org/u/lassoan)
#### Post date: [May 30, 2024, 4:30pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/6 "2024-05-30T16:30:52Z")

</div>

See a full composite transform reader implementation in 3D Slicer here:

> <https://github.com/Slicer/Slicer/blob/fcba379c077f5a6c3d1d7a0ec91e4a659b32fce4/Libs/MRML/Core/vtkMRMLTransformStorageNode.cxx#L303-L422>

It builds a VTK transformation pipeline from the ITK transform file that can be directly used for visualization (displaying warped images, meshes, segmentations, annotations, etc.).

---

<div class="post-metadata">

### Author: ![gdevenyi](https://discourse.itk.org/user_avatar/discourse.itk.org/gdevenyi/32/355_2.png) [@gdevenyi](https://discourse.itk.org/u/gdevenyi)
#### Post date: [May 30, 2024, 4:45pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/7 "2024-05-30T16:45:48Z")

</div>

The answer appears to be that its called a Queue for composite transforms, and I can iterate over it.

---

<div class="post-metadata">

### Author: ![gdevenyi](https://discourse.itk.org/user_avatar/discourse.itk.org/gdevenyi/32/355_2.png) [@gdevenyi](https://discourse.itk.org/u/gdevenyi)
#### Post date: [May 30, 2024, 4:50pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/8 "2024-05-30T16:50:13Z")

</div>

Now what remains is that I can’t seem to try/catch a cast of displacement fields into MatrixOffsetTransformBase, instead it segfaults.

Is this a bug, or should I be doing this another way?

```auto
          for (auto it2 = compositeTransformQueue.begin(); it2 != compositeTransformQueue.end(); ++it2)
          {
            try
            {
              using TransformType3D = itk::MatrixOffsetTransformBase<double, 3, 3>;
              TransformType3D * itktx3d = dynamic_cast<TransformType3D *>((*it2).GetPointer());
              itktx3d->Print(std::cout);
              std::cout << "Determinant: " << vnl_determinant(itktx3d->GetMatrix().GetVnlMatrix()) << std::endl;
            }
            catch (const itk::ExceptionObject & excp)
            {
              it2->Print(std::cout);
            }
          }

```

---

<div class="post-metadata">

### Author: ![blowekamp](https://discourse.itk.org/user_avatar/discourse.itk.org/blowekamp/32/79_2.png) [@blowekamp](https://discourse.itk.org/u/blowekamp)
#### Post date: [May 30, 2024, 4:53pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/9 "2024-05-30T16:53:38Z")

</div>

If a dynamic\_cast fails the results are null. I don’t see this check.

---

<div class="post-metadata">

### Author: ![gdevenyi](https://discourse.itk.org/user_avatar/discourse.itk.org/gdevenyi/32/355_2.png) [@gdevenyi](https://discourse.itk.org/u/gdevenyi)
#### Post date: [May 30, 2024, 5:00pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/10 "2024-05-30T17:00:28Z")

</div>

OK. I was expecting an exception, not a null.

This C++ metamagic is far far outside my programming experience so I’m a copy-paste monkey here.

---

<div class="post-metadata">

### Author: ![gdevenyi](https://discourse.itk.org/user_avatar/discourse.itk.org/gdevenyi/32/355_2.png) [@gdevenyi](https://discourse.itk.org/u/gdevenyi)
#### Post date: [May 30, 2024, 5:24pm UTC](https://discourse.itk.org/t/reading-arbitrary-transforms-compute-something-if-linear/6553/11 "2024-05-30T17:24:07Z")

</div>

Thanks all for the help, the final code is a PR for review here

> <https://github.com/ANTsX/ANTs/pull/1712>
>
> I'd like to be able to easily extract the determinant of affine transforms and a…ntsTransformInfo seems like the right place.
> 
> The function has been refactored to handle reading errors.
> 
> Based primarily off
> https://github.com/InsightSoftwareConsortium/ITK/blob/master/Examples/IO/TransformReadWrite.cxx
> 
> Things that aren't done:
> \- I don't know how to automatically handle the 2D vs 3D transforms. The previous simple read/print code didn't seem to need it whereas this version does.
