14

I have a numpy array that I would like to covert into a nifti file. Through the documentation it seems PyNIfTI used to do this with:

image=NiftiImage(Array)               

However, PyNIfTI isn't supported anymore. NiBabel, the successor to PyNIfTI, doesn't seem to support this function. I must be missing something. Does anyone know how to do this?

Oliver W.
  • 13,169
  • 3
  • 37
  • 50
Michelle
  • 143
  • 1
  • 1
  • 4

2 Answers2

25

The replacement function in the newer NiBabel package would be called Nifty1Image. However, you are required to pass in the affine transformation defining the position of that image with respect to some frame of reference.

In its simplest form, it would look like this:

import nibabel as nib
import numpy as np

data = np.arange(4*4*3).reshape(4,4,3)

new_image = nib.Nifti1Image(data, affine=np.eye(4))

You could also write to a NIfTI-2 file format by using Nifti2Image, which also requires the affine transformation.

Aelius
  • 1,029
  • 11
  • 22
Oliver W.
  • 13,169
  • 3
  • 37
  • 50
  • Thank you so much! I totally missed that in the documentation. This was a huge help! (I can't Vote up since this was my first time on Stack Overflow.) – Michelle Feb 05 '15 at 16:06
  • @Michelle Glad to help and welcome to StackOverflow. Don't worry about not being able to upvote, it takes some time to get reputation. You can accept the answer though, which will also give you some reputation. And it will signify to the larger community that you have found an answer that works. – Oliver W. Feb 05 '15 at 16:26
  • Sorry - I'm still having problems. I'm looking to create the nifti file with vector data. I initialize the array via: vectorArray = np.zeros((3,3,3), dtype = ('float,float,float')) The nib.Nifti1Image gives the error: data dtype "[('f0', ' – Michelle Feb 05 '15 at 16:56
  • @Michelle, that's because you have created (needlessly) a [structured array](http://docs.scipy.org/doc/numpy/user/basics.rec.html). Simply put: you have created an array of records, where each element of those records is a float. To solve, simply define your array like this: `vectorArray = np.zeros((3,3,3), dtype=np.float)`. – Oliver W. Feb 05 '15 at 17:06
  • Thanks again :-) But how can I get my vector data ( (i,j,k)/voxel), i.e. (0.23, 0.48, 0.84) for array location [1,1,1] into that type? – Michelle Feb 05 '15 at 17:16
  • @Michelle, I'm not entirely sure what you're asking. I *think* you want to define the numpy array upfront, e.g. like this: `arr = np.zeros((2,4,3,3)); arr[1,1,1] = [.23, .48, .84]` and then convert to a NIfTI image. If not, I suggest asking a new question on SO and best to add a good example of what you're after ;-) – Oliver W. Feb 05 '15 at 17:21
  • 1
    @Michelle Hmmmm, I should use `np.eye(4)` all the time right? I feel confused even with the document :( – Losses Don Feb 26 '18 at 08:43
  • @LossesDon please check my answer – shantanu pathak Nov 22 '18 at 10:16
5

Accepted answer is sufficient. I am adding few lines of detailed explanation for the same.

import nibabel as nib
import numpy as np

data = np.arange(4*4*3).reshape(4,4,3)

new_image = nib.Nifti1Image(data, affine=np.eye(4))

The function np.eye(n) returns a n by n identity matrix.
Here this np.eye(4) is used to generate 4 by 4 matrix as Nifti processes 4 by 4 file format. So you 3 by 3 matrix is converted to 4 by 4 by multiplication with 4 by 4 identity matrix.

So, always affine = np.eye(4) will work.

Same is applicable to both Nifti1Image and Nifti2Image

Aelius
  • 1,029
  • 11
  • 22
shantanu pathak
  • 2,018
  • 19
  • 26