Editing/Saving CIFTI

Dear Experts,

I am currently seeking a way to open a cifti *.pscalar.nii or *.ptseries.nii file and change the bold indexed using nibabel my_cifti.get_fdata() to save into a new cifti file with the replacement bold. It is not clear to me with the current documentation how to directly alter the original cifti file and save those changes using nibabel.

So far I have been able to access the BOLD using my_cifti.get_fdata(), altering it here and attempting to save the file only for this to not save: Here is what I have done:

In:
Pscale_load=nib.load(’/path/to/cifti/My_Cifti.pscalar.nii’)
Pscale_load
Out:
<nibabel.cifti2.cifti2.Cifti2Image at 0x7fd84186f978>

my_indeces is a list of indeces of the same length and dtype as my_values where each element is a float

In:
for i,value in zip(my_indeces,my_values):
Pscale_load.get_fdata()[0][i] = value
Out:
Output reflects changed values with call: Pscale_load.get_fdata()[0][<Pick_an_index>]

In:
cifti2.cifti2.save(Pscale_load, ‘/path/to/save/file/My_New_Cifti.pscalar.nii’)

In:
Test=nib.load(’/path/to/save/file/My_New_Cifti.pscalar.nii’)
Out:
<nibabel.cifti2.cifti2.Cifti2Image at 0x7fd84278f990>

In:
Test.get_fdata()[0]
Output:
Unchanged from original Pscale_load.get_fdata()

How can I retain the same parcellated scalar cifti2 file structure and arrangement while only manipulating the BOLD values (and save the changes)?

1 Like

Any follow-up on this?

Just to re-format what came in:

Pscale_load=nib.load("/path/to/cifti/My_Cifti.pscalar.nii")
# my_indeces is a list of indeces of the same length and dtype as my_values where each element is a float
for i,value in zip(my_indeces, my_values):
    Pscale_load.get_fdata()[0][i] = value
cifti2.cifti2.save(Pscale_load, ‘/path/to/save/file/My_New_Cifti.pscalar.nii’)

Pscale_load.get_fdata() returns a (cached after the first call) data array. Modifying the cached data array in place will affect how future calls get get_fdata() look, but do not affect how the write process works, which will look directly at the data object for the image.

What you want to do is create a new image with the same header:

pscalars = nib.load("/path/to/cifti/My_Cifti.pscalar.nii")
new_img = nb.Cifti2Image(my_values, header=pscalars.header,
                         nifti_header=pscalars.nifti_header)
new_img.to_filename("/path/to/save/file/My_New_Cifti.pscalar.nii")

I am assuming that my_indeces is just [0, ..., pscalars.shape[1] - 1]. If not, create your data array and pass it in place of my_values.

2 Likes

Sorry for the late reply. This is great and basically what I ended up doing.