-
-
Notifications
You must be signed in to change notification settings - Fork 381
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
Enable antsApplyTransforms to select one volume in a 4D file to resample #1555
Comments
The The second option, using a vector of transforms, is more difficult. The ITK class does not support swapping out elements of the transform stack, we'd have to keep track of the component transforms and build the composite transform for each moving volume. |
I suppose it's a question of whether the entire image is loaded into memory each time. In general, it is not difficult to load a single volume by calculating the offset in the byte stream, and this is not made much worse by compression, since NIfTIs are column-major and one volume is a contiguous segment. That said, I don't know how flexible ITK is on this. |
The default is to read the entire thing, I asked on Discourse if it's possible to do it more efficiently https://discourse.itk.org/t/random-access-to-image-data/6034 |
Looks like we can do it! https://itk.org/Doxygen/html/classitk_1_1ExtractImageFilter.html |
As a follow-up: It would be very cool if I could write to a specific volume in an existing file. I think compression would cause problems here, but if I had an uncompressed NIfTI, the problem of writing just becomes checking the header and writing to an offset with memory mapping or in In case code is clearer, I'd pre-create the image: import nibabel as nb
moving_image = nb.load('moving.nii.gz')
target_image = nb.load('target.nii.gz')
empty_output_image = nb.Nifti1Image(
np.zeros(target_image.shape[:3] + moving_image.shape[3:]),
target_image.affine,
target_image.header,
)
# No scaling
empty_output_image.header.set_data_dtype('float32')
empty_output_image.header.set_slope_inter(1, 0)
empty_output_image.to_filename('output.nii') Then, I would have ANTs target corresponding offsets in the input and output images: for IDX in {0..240}; do
antsApplyTransforms -i moving.nii.gz -r target.nii.gz -o output.nii -u float \
--index $IDX --out-index $IDX \
--transform vol${IDX}_motion.txt \
--transform susceptibility_warp.h5 \
--transform coreg.txt
done It looks like ITK 5.3 added features for working with Dask, to take advantage of parallel processing, and the ImageFileWriter::setIORegion is probably the bit that would be needed. |
Is your feature request related to a problem?
To apply a concatenated sequence of transforms to each volume in a 4D series (for example, head motion + susceptibility warp + coregistration), either the transforms must be the same for each volume or you must split the series and apply the desired transforms.
Proposed new features
I suggest adding either a flag or syntax for specifying specific volumes of 4D input. For example using array notation or an
--index
flag:Alternatives you've considered
The current approach is to split the series into individual volumes, apply the transformations, and then concatenate the resulting series. It works, but generates 2N volumes for an N time point series.
An ideal approach would be to be able to specify a per-volume transform as one in a sequence of transforms such as
However, that seems like a more significant lift. Reading from one volume in a series will at least cut the number of files generated in half, which would be helpful in itself.
Additional context
As mentioned above, splitting files before applying transforms creates 2N output files. In the context of a nipype pipeline, add in an additional factor of 5-10 inodes for working directories and their contents. This can become problematic when running a pipeline on many subjects on shared network filesystems.
The text was updated successfully, but these errors were encountered: