Open sohrabtowfighi opened 6 years ago
If you have a Nifti1Image
and save to *.hdr
, it should save as a Nifti1Pair
... What specific code did you use to save it, and was your goal actually to have an Analyze image instead of NIfTI?
I used nib.save(img, img_path) to save the image.
I wanted to scale the image, move the original image file somewhere for safe keeping, then save the new image to where the old image file was, so presumably I wanted to save as the same format as the original file, but I did not realize that the slope and intercept are not valid attributes for the original file format.
I see. So you started with an AnalyzeImage
, not a Nifti1Image
?
I believe Analyze images are valid NIfTI-1 images, so you should be able to do the following:
import nibabel as nb
img = nb.Nifti1Pair.from_filename(img_path)
...
I've verified that a Nifti1Image
saved to a out.hdr
filename will produce something that will be interpreted as a Nifti1Pair
:
In [1]: import nibabel as nb
In [2]: import numpy as np
In [3]: nb.save(nb.Nifti1Image(np.zeros((5,5,5), dtype=np.uint8), np.eye(4)), 'out.hdr')
In [4]: nb.load('out.hdr')
Out[4]: <nibabel.nifti1.Nifti1Pair at 0x111a35320>
Also, I would generally not directly modify the scale and intercept, but rather, modify the values, and allow the writing routine to select appropriate scales and intercepts. It's harder to end up in a situation with surprising values. Is there a specific reason for re-scaling in this way?
Im not super sure if it was hdr or img anymore.
Regarding modifying signal intensities ditectly, I tried modifying the values directly before then got an error saying the array needs scaling but cannot scale. In addition the documentation shows an example with setting the slope and intercept so I had no idea that it's not the best approach.
Anyways, if the image being saved does not support intercept and slope but the image has a slope and intercept that is not None or m=1,b=0 (as given by the get_slope_inter method) then it makes sense that it raise exception.
I'm sorry if I'm being obtuse, but perhaps it would be clearer if you could give replicating code that you think ought to have raised the exception you're asking for.
Regarding modifying signal intensities ditectly, I tried modifying the values directly before then got an error saying the array needs scaling but cannot scale.
This sounds like the error you're requesting. What did you then do, that you expected would change the slope and intercept? set_slope_inter
ought to have failed for an AnalyzeImage
:
And would loading the file as a Nifti1Pair
before modifying the values resolve your issue?
I called set_slope_inter against a Nifti1Image, which I then saved as an AnalyzeImage or Nifti1Pair
The call to set_slope_inter worked fine. When I subsequently called get_slope_inter against the Nifti1Image, I got the slope and intercept I assigned, but when I saved it, I saved it with a filepath that was not ending in '.nii' so nibabel saved it in a different format, without telling me that the slope and intercept would be discarded.
old_img = nb.load(image_cbv[0])
affine, did_change = r.correct_origin(dc(old_img.affine))
new_img = nb.Nifti1Image(dc(new_image_data_cbv), affine)
new_img = intensity_correction.transform(new_img, 10) # <- in here I use set_slope_inter
# move the old faulty image to the faulty cases directory
move_image(image_path, new_img_path)
# in the original data directory, replace the faulty image
# with the one we generated
image_path = replace_ext(image_path, 'nii') # <- if this line is commented, issue arises
nb.save(new_img, image_path)
To reproduce, I'll need to know the definitions of:
r.correct_origin()
dc()
intensity_correction.transform()
I assume move_image
is just os.rename
, possibly with a os.makedirs
thrown in to make sure there's a target directory?
And I can guess how replace_ext
works.
Use this as a minimum working example.
import nibabel as nb
from copy import deepcopy as dc
import os
nii_file = "C:/Users/sohra/Desktop/1010_brain_mr_02.nii"
img_file = nii_file[:-4] + '.img'
img = nb.load(nii_file)
nii = nb.Nifti1Image(dc(img.get_data()), dc(img.affine), dc(img.header))
nii.header.set_slope_inter(10,2)
nb.save(nii, img_file)
nii.header.get_slope_inter()
nii.get_data().max()
new = nb.load(img_file)
new.get_data().max()
I work with both nifti and analyze format. My image object was a Nifti1Image, but the filepath to which I was saving had the '.hdr' extension, so nibabel saved as Analyze format. When I reloaded the image, the scaling was not applied, and I had no idea what was going on. Maybe consider this for a future version.