BRAINSia/ANTS — pull request #10 by Chaircrusher (2012-07-12 17:34:17+00:00)
Title: ENH: Move image creation/allocation into common template functions

I've been doing some code cleanup on ANTS, and I have found what I think
are some issues with how the code deals with Images, their size and
spatial orientation.

The primary thing I was addressing is that the same code -- with
variations -- was used all over ANTS in order to allocate images, to
receive results, act as temporaries, etc. To that end I wrote some simple
template functions that encapsulate several lines of boilerplate code to
allocate a new image. This went into a new file called antsAllocImage.h
in the Utilities directory.

The fundamental problem I've seen is this: In ITK4 and to some extent in
later revisions of ITK3, the spatial orientation, location, and spacing of
image volumes is important. The new registration framework does its work
in world space, not in index space. This simplifies working with image
scans that have different orientation, spacing and location -- if you
manipulate them in terms of World Coordinates instead of local pixel
index, then the code doesn't need to worry about
orientation/location/spacing. A physical point in one image is comparable
to a physical point in another -- they're in the same reference frame.

This requires a certain amount of care at times on the part of the
application developer. In particular, if you use an image as a template
for creating a new image, you need to make sure one of two invariants will
be maintained.

1) The new image will have not just the same voxel grid size, but also the
same origin, spacing, and orientation(direction cosines).
2) The new image will have the same voxel grid size, but any code using it
will work ONLY in index space.

The problem in ANTS is that I've found code that violates those invariants.

A) The size, spacing, and origin are copied from an examplar image, but
not the directions. In that case the new image will have identity
orientation -- if the examplar image isn't also in identity orientation,
the two images are not in the same space, and the spacing and origin are
meaningless.

B) Only the size is used from an examplar image, but it isn't clear
without code review if computations with the new image only occurs in
index space.

C) There's some confusion -- perhaps on my part -- what is intended. In
particular there are cases where the Image is sized by the buffered region
of an examplar image, but the origin is copied from the examplar. If the
buffered region of the examplar image is different than the largest
possible region (I.e. the whole image), then the origin being copied will
be wrong.

There is also code that is nominally correct but redundant.

1) There are places where origin, spacing, and directions are set to [0 0
0], [1 1 1], and Identity respectively and then used to create an image.
When you create an image, all of that information is already set to those
default values; it's sufficient to set the size of the image and then
allocate.

2) Sometimes, the size of the image region is set, and the index is set to
[0 0 0]. The index defaults to [0 0 0].

When my changes are merged into ANTS there will be a comment with the
phrase 'ORIENTATION ALERT' where I think there is some confusion about
what is intended. I do know that when I simply replaced all the 'create
image from examplar' code with a call to AllocImage that copied all the
image position/size/orientation information that the results of the
regression test were changed. I've gone back and been more careful to not
make changes that modify results, but at the same time I'm not sure if the
results were wrong, better, or just different.