3dNwarpApply ate my memory!

Dear AFNI nation,

I realize that 3dNWarpApply can consume large amounts of memory (70GB before a long beach volleyball stint) when there little overlap between source and grid datasets.

If I understand correctly, the problem can be remedied by centering the volumes before computing the warp, which means rerunning a whole lot of alignments. Is there a way to account for the shifts after the warps have been estimated?

Specifically for my case, I have 4 spaces I am working with A, B, B[sub]MNI[/sub], and C. I have an affine transform from B to A, and a NL transform from B to C. Origins of A and B can vary wildly.

My 3dNwarpApply command strings together B[sub]MNI[/sub]2C_NL, B2B[sub]MNI[/sub]_affine, and INV(B2A_affine) to take A data into C space. I suspect the answer is no, but can you think of any tricks I can do to already computed transforms to enable warping of A to C without a lot of memory use and without having to rerun 3dQwarp?


Hi Z,
I don’t see an A->B transformation in your description, so can I assume you computed all those transformations not using the A dataset? The trick then would be to move A to B with @Align_Centers as a first step. That won’t apply any interpolation, of course, because only the origin moves in the header of the dataset. The centering brings the data to a kind of B(pre) space, so you probably want to compute an A(Bpre)->B alignment and continuing on. Inverting the transformation could be done in reverse stopping at the B(pre) space before another @Align_Centers or the inverse of the shift.1D applied with 3drefit instead. This method is used in the @animal_warper script to move data in both directions, so you can look at that script for an example. HTH!

Another variant of basically the same idea is to remove the translation from the affine transformation here, B2A_affine, by zeroing out that last column of the affine matrix. Apply that transformation separately with 3drefit instead to move the origin. With nonlinear warps that already include a large translation, you could subtract the mean x,y,z deformations from each of the sub-bricks of the warp dataset. Similarly apply the translation via a 3drefit.

Hi Daniel!

Thanks for your help. A->B is as an affine transformation in my original post.
I understand correctly, the process you suggest will involve recomputing the NL transformations, otherwise the whole procedure can be scripted from existing output, correct?


Hey Z,

Note that Daniel has temporarily fled the country, so he might not reply until we can drag him back.

My ignorant take on this is that the NL transform would not need to be recomputed. But it is not the forward F:A->B transform that you could extract the xyz offsets from, but the inverse F^-1:B->A one (and then take the inverse (negatives) of those offsets).

The point is that the offset columns of F (in the forward direction) are essentially applied AFTER the rotational pieces. So in order to use 3drefit, you would have to rewrite F as a shift transform followed by the rotational one. That might mean computing F inverse, separating it as rotation and shift matrices, and then inverting those pieces. cat_matvec could probably be used for that.

Does that seem reasonable?

  • rick

Thanks Rick, Daniel.