# Convert .nii.gz warp to .h5 (with proper header)

**URL:** https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673
**Category:** Beginner Questions
**Tags:** itk, registration
**Created:** [June 5, 2024, 3:37pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673 "2024-06-05T15:37:44Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![smeisler](https://discourse.itk.org/user_avatar/discourse.itk.org/smeisler/32/4106_2.png) [@smeisler](https://discourse.itk.org/u/smeisler)
#### Post date: [June 5, 2024, 3:37pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/1 "2024-06-05T15:37:45Z")

</div>

Hi!

I have been modifying an anatomical processing workflow that largely uses ANTs. I have been trying to incorporate FreeSurfer’s `synthmorph` to calculate a registration, which outputs in RAS convention. I have been able to convert this deformation to a LPS (like ITK/ANTs expects) NIFTI file fine with FreeSurfer’s `mri_warp_convert`.

However, for the final step of the pipeline when a set of registrations are combined and applied, I would need a `.h5` file with the proper formatting/header information. FreeSurfer doesn’t know what kind of formatting is expected, so simply specifying the output of `.h5` in `mri_warp_convert` doesn’t work, as I am met with the following error when trying to apply it with `antsApplyRegistration`:

```auto
Description: ITK ERROR: TransformFileReaderTemplate(0x55565df6abb0): Could not create Transform IO object for reading file /home/smeisler/projects/fmriprep_ants/single_subject_bids/derivatives/synthmorph_test/sub-NDARINV1Y40DZT8/ses-baselineYear1Arm1/anat/sub-NDARINV1Y40DZT8_ses-baselineYear1Arm1_rec-normalized_from-T1w_to-MNI152NLin2009cAsym_mode-image_xfm.h5
	  Tried to create one of the following:
	    HDF5TransformIOTemplate
	    HDF5TransformIOTemplate
	    MINCTransformIOTemplate
	    MINCTransformIOTemplate
	    MatlabTransformIOTemplate
	    MatlabTransformIOTemplate
	    TxtTransformIOTemplate
	    TxtTransformIOTemplate
	  You probably failed to set a file suffix, or
	    set the suffix to an unsupported type.

```

I am hoping `Convert3D` will help, but I am not sure exactly how I would implement this. Any thoughts would be appreciated.

Thank you,  
Steven

---

<div class="post-metadata">

### Author: ![smeisler](https://discourse.itk.org/user_avatar/discourse.itk.org/smeisler/32/4106_2.png) [@smeisler](https://discourse.itk.org/u/smeisler)
#### Post date: [June 5, 2024, 5:06pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/2 "2024-06-05T17:06:10Z")

</div>

As an update, I have tried the following to manually convert,

```auto
   def convert_nifti_to_ants_h5_deformation(self, nifti_file, h5_file):
        # Load the NIfTI file
        img = nib.load(nifti_file)
        data = img.get_fdata()

        # Ensure the data is in float32 format for compatibility
        if data.dtype != np.float32:
            data = data.astype(np.float32)

        # Create the HDF5 file with ANTs specific structure
        with h5py.File(h5_file, 'w') as f:
            # Create the Transform group
            xform_group = f.create_group('/TransformGroup/0')
            
            # Write out the transformation parameters
            xform_group.create_dataset('TransformParameters', data=data.flatten(order='C'))
            
            # Write additional attributes and datasets expected by ANTs
            xform_group.attrs['TransformType'] = 'DisplacementFieldTransform'
            xform_group.attrs['TransformDisplacementField'] = 'DisplacementField'
            xform_group.attrs['TransformFixedParameters'] = img.affine.flatten().tolist()
            
            f.attrs['ITKTransformType'] = 'DisplacementFieldTransform_double_3_3'
            f.attrs['ITKVersion'] = '4.11.0'
            f.attrs['HDFVersion'] = '1.8.15'

```

and now ANTs returns the following errors when I go to apply the registration:

```auto
Stderr:
	HDF5-DIAG: Error detected in HDF5 (1.14.3) thread 1:
	  #000: H5D.c line 403 in H5Dopen2(): unable to synchronously open dataset
	    major: Dataset
	    minor: Can't open object
	  #001: H5D.c line 364 in H5D__open_api_common(): unable to open dataset
	    major: Dataset
	    minor: Can't open object
	  #002: H5VLcallback.c line 1980 in H5VL_dataset_open(): dataset open failed
	    major: Virtual Object Layer
	    minor: Can't open object
	  #003: H5VLcallback.c line 1947 in H5VL__dataset_open(): dataset open failed
	    major: Virtual Object Layer
	    minor: Can't open object
	  #004: H5VLnative_dataset.c line 331 in H5VL__native_dataset_open(): unable to open dataset
	    major: Dataset
	    minor: Can't open object
	  #005: H5Dint.c line 1418 in H5D__open_name(): not found
	    major: Dataset
	    minor: Object not found
	  #006: H5Gloc.c line 421 in H5G_loc_find(): can't find object
	    major: Symbol table
	    minor: Object not found
	  #007: H5Gtraverse.c line 816 in H5G_traverse(): internal path traversal failed
	    major: Symbol table
	    minor: Object not found
	  #008: H5Gtraverse.c line 596 in H5G__traverse_real(): traversal operator failed
	    major: Symbol table
	    minor: Callback failed
	  #009: H5Gloc.c line 381 in H5G__loc_find_cb(): object 'TransformType' doesn't exist
	    major: Symbol table
	    minor: Object not found
	Transform reader for /home/smeisler/projects/fmriprep_ants/single_subject_bids/derivatives/synthmorph_test/sub-NDARINV1Y40DZT8/ses-baselineYear1Arm1/anat/sub-NDARINV1Y40DZT8_ses-baselineYear1Arm1_rec-normalized_from-T1w_to-MNI152NLin2009cAsym_mode-image_xfm.h5 caught an ITK exception:

	itk::ExceptionObject (0x560251e0ed50)
	Location: "unknown" 
	File: /home/conda/feedstock_root/build_artifacts/libitk_1717078286681/work/Modules/IO/TransformHDF5/src/itkHDF5TransformIO.cxx
	Line: 365
	Description: ITK ERROR: HDF5TransformIOTemplate(0x560251d81890): H5Dopen2 failed

```

Is this manual setting a good direction to go down or are there more automated tools for this?

Thanks,  
Steven

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)
#### Post date: [June 5, 2024, 5:18pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/3 "2024-06-05T17:18:06Z")

</div>

Have you tried putting your warp field into a [DisplacementFieldTransform](https://itk.org/Doxygen/html/classitk_1_1DisplacementFieldTransform.html)? And then save that via `itk.transformwrite()`?

---

<div class="post-metadata">

### Author: ![smeisler](https://discourse.itk.org/user_avatar/discourse.itk.org/smeisler/32/4106_2.png) [@smeisler](https://discourse.itk.org/u/smeisler)
#### Post date: [June 5, 2024, 5:26pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/4 "2024-06-05T17:26:45Z")

</div>

Hi @dzenanz, thanks for responding!

Just to make sure, do you mean something like:

```auto
import SimpleITK as sitk
import nibabel as nib

# Load nifti warp
img = nib.load(nifti_file)
data = img.get_fdata()

# Define and save ITK warp
displacement_image = sitk.GetImageFromArray(data, isVector=True)
tx = sitk.DisplacementFieldTransform(displacement_image)
sitk.WriteTransform(tx, "out_warp.h5");

```

Best,  
Steven

---

<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: [June 5, 2024, 5:34pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/5 "2024-06-05T17:34:13Z")

</div>

That is close, but you’ll need to use SimpleITK/ITK to read the NIFTI deformation field to preserve all the metadata.

You can see an example here using the `sitk.DisplacementFieldTransform` with a displacement field image:  
[https://simpleitk.readthedocs.io/en/master/link\_DemonsRegistration1\_docs.html](https://simpleitk.readthedocs.io/en/master/link_DemonsRegistration1_docs.html)

---

<div class="post-metadata">

### Author: ![smeisler](https://discourse.itk.org/user_avatar/discourse.itk.org/smeisler/32/4106_2.png) [@smeisler](https://discourse.itk.org/u/smeisler)
#### Post date: [June 5, 2024, 5:35pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/6 "2024-06-05T17:35:29Z")

</div>

Great, I’ll give this a shot and report back, thanks @dzenanz and @blowekamp !

---

<div class="post-metadata">

### Author: ![smeisler](https://discourse.itk.org/user_avatar/discourse.itk.org/smeisler/32/4106_2.png) [@smeisler](https://discourse.itk.org/u/smeisler)
#### Post date: [June 5, 2024, 6:57pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/7 "2024-06-05T18:57:58Z")

</div>

Hi @blowekamp and @dzenanz,

I tried the following:

```auto
import SimpleITK as sitk
in_nii="path_to_LPS_warp.nii.gz"
out_h5="path_to_LPS_warp.h5"
displacement_image = sitk.ReadImage(in_nii, sitk.sitkFloat64, imageIO="NiftiImageIO")
tx = sitk.DisplacementFieldTransform(displacement_image)
sitk.WriteTransform(tx,out_h5)

```

and am met with the following error:

```auto
File "/opt/conda/envs/fmriprep/lib/python3.11/site-packages/niworkflows/interfaces/itk.py", line 346, in _run_interface
  tx = sitk.DisplacementFieldTransform(displacement_image)
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/conda/envs/fmriprep/lib/python3.11/site-packages/SimpleITK/SimpleITK.py", line 5608, in __init__
  _SimpleITK.DisplacementFieldTransform_swiginit(self, _SimpleITK.new_DisplacementFieldTransform(*args))
                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: Exception thrown in SimpleITK new_DisplacementFieldTransform: /tmp/SimpleITK/Code/Common/src/sitkDisplacementFieldTransform.cxx:66:
sitk::ERROR: Expected input displacement field image must be of pixel type: vector of 64-bit float

```

I thought that hard-coding that precision with `sitk.sitkFloat64` would get past this error. Do you have any suggestions about how I may proceed?

Thanks,  
Steven

---

<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: [June 5, 2024, 7:01pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/8 "2024-06-05T19:01:18Z")

</div>

> [@smeisler](#):
>
> `displacement_image = sitk.ReadImage(in_nii, sitk.sitkFloat64, imageIO="NiftiImageIO")`

The above line converts the vector pixels to scalars, the correct type would be `sitk.sitkVectorFloat64`. However the above specificity is not needed. Why not just do:

```auto
displacement_image = sitk.ReadImage(in_nii)

```

P.S. If the error continues do a `print(displacement_image.ToString())` to get the details about the image that was read.

---

<div class="post-metadata">

### Author: ![smeisler](https://discourse.itk.org/user_avatar/discourse.itk.org/smeisler/32/4106_2.png) [@smeisler](https://discourse.itk.org/u/smeisler)
#### Post date: [June 5, 2024, 7:13pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/9 "2024-06-05T19:13:54Z")

</div>

Thanks @blowekamp,

I got the same error when just doing `displacement_image = sitk.ReadImage(in_nii)`, but seem to have gotten past it when hard coding the correct `sitk.sitkVectorFloat64` precision!

Waiting until my pipeline finishes to see if registration looks like it should, but thank you so much for helping me get to this point!

Best,  
Steven

---

<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: [June 5, 2024, 7:37pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/10 "2024-06-05T19:37:08Z")

</div>

The displacement field may have been save as 32-bit float ( the print statement should show), white the ITK Transform requires 64-bits.

---

<div class="post-metadata">

### Author: ![smeisler](https://discourse.itk.org/user_avatar/discourse.itk.org/smeisler/32/4106_2.png) [@smeisler](https://discourse.itk.org/u/smeisler)
#### Post date: [July 10, 2024, 8:08pm UTC](https://discourse.itk.org/t/convert-nii-gz-warp-to-h5-with-proper-header/6673/11 "2024-07-10T20:08:11Z")

</div>

Forgot to follow up earlier, just providing closure that this indeed worked! 🙂
