nibabel copying mgz header incorrectly
I am currently using nibabel 5.3.2. I wrote a script to makes an edit to an mgz image. After running the script I noticed that nibabel adds what looks like rounding error to some of the mgz header. Below is my whole script.
import nibabel as nb
import numpy as np
import sys
oldfilledmgz = nb.freesurfer.mghformat.load(sys.argv[1])
newfilledmgz = nb.freesurfer.mghformat.load(sys.argv[2])
WMmgz = nb.freesurfer.mghformat.load(sys.argv[3])
oldfilled=np.asanyarray(oldfilledmgz.dataobj)
newfilled=np.asanyarray(newfilledmgz.dataobj)
WM=np.asanyarray(WMmgz.dataobj)
if not np.equal(oldfilled,newfilled):
WM[(oldfilled == 0) & ((newfilled == 127) | (newfilled==255)) ] = 255
WM[(newfilled == 0) & ((oldfilled == 127) | (oldfilled==255)) ] = 1
WMnew = nb.freesurfer.mghformat.MGHImage(WM, WMmgz.affine, header=WMmgz)
WMnew.set_filename(sys.argv[3])
nb.save(WMnew, sys.argv[3])
Since you're passing the affine, it's being converted back into the header format. If you use affine=None, the header will not be modified.
OK, I tried that out. everything look good except it set the c_ras to zeros.
Can you print(img.header) for the WMmgz input image, the WMnew image, and then reload the file that you save and print its header too?
Ok here is the updated script
import nibabel as nb
import numpy as np
import sys
oldfilledmgz = nb.freesurfer.mghformat.load(sys.argv[1])
newfilledmgz = nb.freesurfer.mghformat.load(sys.argv[2])
WMmgz = nb.freesurfer.mghformat.load(sys.argv[3])
oldfilled=np.asanyarray(oldfilledmgz.dataobj)
newfilled=np.asanyarray(newfilledmgz.dataobj)
WM=np.asanyarray(WMmgz.dataobj)
if not np.array_equal(oldfilled,newfilled):
WM[(oldfilled == 0) & ((newfilled == 127) | (newfilled==255)) ] = 255
WM[(newfilled == 0) & ((oldfilled == 127) | (oldfilled==255)) ] = 1
print(WMmgz.header)
WMnew = nb.freesurfer.mghformat.MGHImage(WM, affine=None, header=WMmgz)
print(WMnew.header)
WMnew.set_filename(sys.argv[3])
nb.save(WMnew, sys.argv[3])
else:
print('No changes were made to the filled.mgz image.')
Here is the output
<class 'nibabel.freesurfer.mghformat.MGHHeader'> object, endian='>' version : 1 dims : [256 256 256 1] type : 0 dof : 1 goodRASFlag : 1 delta : [1. 1. 1.] Mdc : [[-9.9999982e-01 0.0000000e+00 -1.8626451e-09] [ 3.7252903e-09 6.9849193e-10 -9.9999994e-01] [ 0.0000000e+00 9.9999988e-01 -2.5611371e-09]] Pxyz_c : [-0.17240906 21.117714 19.475388 ] tr : 2400.0 flip_angle : 0.13962634 te : 3.18 ti : 1000.0 fov : 256.0 <class 'nibabel.freesurfer.mghformat.MGHHeader'> object, endian='>' version : 1 dims : [256 256 256 1] type : 3 dof : 0 goodRASFlag : 1 delta : [1. 1. 1.] Mdc : [[-1. 0. 0.] [ 0. 0. 1.] [ 0. -1. 0.]] Pxyz_c : [0. 0. 0.] tr : 0.0 flip_angle : 0.0 te : 0.0 ti : 0.0 fov : 0.0
Than I loaded the wm file in python. the header output is
<class 'nibabel.freesurfer.mghformat.MGHHeader'> object, endian='>' version : 1 dims : [256 256 256 1] type : 3 dof : 0 goodRASFlag : 1 delta : [1. 1. 1.] Mdc : [[-1. 0. 0.] [ 0. 0. 1.] [ 0. -1. 0.]] Pxyz_c : [0. 0. 0.] tr : 0.0 flip_angle : 0.0 te : 0.0 ti : 0.0 fov : 0.0
Oh,
- WMnew = nb.freesurfer.mghformat.MGHImage(WM, affine=None, header=WMmgz)
+ WMnew = nb.freesurfer.mghformat.MGHImage(WM, affine=None, header=WMmgz.header)
This does help. I ran the code again and used the output for it in FreeSurfer's recon-all and it fails. After some investigation i figured out that the output of the python script is still producing a mgz with the incorrect header. I was able to copy over the header from the original wm.mgz using FreeSurfer's mri_convert with the --in_like flag. After coping the header FreeSurfer over recon-all run all the way through with out an issue. So nibabel is till not coping over all of the header. I have place two images in the following URL, wm1.mgz and wm2.mgz. wm1.mgz is the output of the python script while wm2.mgz is after using mri_convert to correct the head. I can not tell the difference between the images. Both nibabel and FreeSurfer's mri_head says that both images have identical headers. However after decompressing the mgz to mgh I noticed the size of both files are not the same. I am assuming I am doing this all wrong.