convert numpy array to 4D nifti file - python

I am doing single-voxel simulations on python to generate simulated signals with added noise. Then, I want to convert the resulting numpy array, with the following shape (100, 100) into a nifti file.
Rows represent one simulated signal under different conditions of noise and tensor rotation. Each column represents the correspondent signal intensity for that voxel under those conditions when measured with a specific sampling scheme (100 different directions).
[DWIs array]
I am to save this matrix into a nifti file with the following format (10, 10, 1, 100).
[Desired shape]
I don’t know how to properly allocate the numpy array (DWIs.shape = (100,100)) to the format I desire (10, 10, 1, 100):
data[…, ] = ?
 
converted_array = np.array(data, dtype=np.float32)
nifti_file = nib.Nifti1Image(converted_array, affine=np.eye(4))
nib.save(nifti_file, os.path.join(path_to_save, 'snr{}'.format(snr), 'full/dwi_sims_snr{}.nii.gz'.format(snr)))

In NumPy you do not need to "allocate" data arrays.
Suppose you have a 100x100 converted_array. That is
>>> converted_array.shape
(100,100)
>>> converted_array[0]
[146.4, 72.9, ..., 174.9]
then you can reshape this array as
>>> nifti_array = converted_array.reshape((10,10,1,100))
>>> nifti_array[0][0][0]
[146.4, 72.9, ..., 174.9]

Related

Converting an array from one shape to another?

I have a video i.e image sequences saved in an array. The output is:
Output:
(13,9,9)
Where the 13 represents the 13 image sequences and the two 9's represent the pixels. I wish to convert the array into an output like:
Output:
(81,13)
Where the 81 represents the 81 pixel instances and the 13 is capturing the time domain i.e. the video frames in time. I will then be feeding this into my CNN.
Does anyone have any suggestions? As using array.reshape(81,13) of course doesn't work.
Assuming x is the original video 3D array, you need this to convert it to the desired 2D array:
import numpy as np
x2d = x.transpose(1, 2, 0).reshape(-1, x.shape[0])
This also works:
x2d = x.reshape(x.shape[0], -1).T
Essentially the concept is to reshape or transpose the array in such a way that the elements you want in a row should end up in contiguous memory locations.

How do I multiply a 1D array with only one other array in a 3D array?

I have a 1D array and I would like to multiply it with only the first axis of the 3D array.
For example, my 1D array has a length of 710, and I want to multiply it only with the first axis of the 3D array which also has a length of 710. I do not want it multiplied with the other two axes (because they are different sizes and I get an error).
How would I do that?
Below is the example code:
data = sla_standard[:,:,:]
window = w
print(window.shape)
print(data.shape)
#GOAL: multiply the window with the first axis of my data array
what is printed from console:
(710,)
(710, 81, 320)
Both arrays should have the same dimensionality (i.e. should be 3D). Once it is true, numpy will broadcast missing dimensions automatically (i.e., dimensions with only one row/column will be stretched to match the other array). Use window[:, None, None] to cast it to 3D:
>>> window = np.random.random((710))
>>> data = np.random.random((710, 81, 320))
>>> (window[:, None, None] * data).shape
(710, 81, 320)

How can I convert an array of images to a 2D array in Python

I have a numpy array of images in that shape:
(50000, 32, 32, 3)
50000 is the number of images
32, 32 are the height and width
3 are the RGB values with a range of 0-1
I would like to convert it to a 2D shape of:
(50000, 1024)
Here I would have 50000 images represented in one row,
the RGB value would be converted to let's say an hexadecimal value
I've went through a lot of conversion processes into stack overflow and I've found some.
I know that if my array was a 3D array with an already converted value I could easily use reshape()function to convert it to 2D.
Now what I'm searching is the easiest way to convert RGB values and reshape my array
Would this be possible in 1 or two lines or should I use an external function?
First convert the RGB values in the last dimension to the HEX value using whatever function you like. This SO answer may help.
Reshape then works on any number of dimensions:
import numpy as np
def rgb2hex(r, g, b):
return '#%02x%02x%02x' % (r, g, b)
vfunc = np.vectorize(rgb2hex)
a = (np.random.uniform(0,1,(10,5,5,3))*255).astype(int)
c = vfunc(a[:,:,:,0], a[:,:,:,1], a[:,:,:,2])
c.reshape((10,25))
In order to do so, you firstly need to reshape the ndarray (np.reshape):
a = np.random.randint(1,10,(500, 32, 32, 3))
a_r = np.reshape(a, (500, 1024, 3))
print(a_r.shape)
# (500, 1024, 3)
Now, in order to convert the RGB values along the last dimension to hexadecimal representation as you suggest, you could define a function that returns a hexadecimal representation of the three values with a simple string formatting:
def rgb_to_hex(x):
return '#{:02X}{:02X}{:02X}'.format(*rgb.reshape(3))
In order to apply the conversion along all rows in the last axis, you can use np.apply_along_axis:
a_new = np.apply_along_axis(rgb2hex, axis=-1, arr=a_r).shape
print(a_new.shape)
# (500, 1024)
The following combines the RGB values into a single value
x=np.zeros((100,32,32,3))
x[:,:,:,0] = np.trunc(x[:,:,:,0]) + np.trunc(x[:,:,:,1] *256) + np.trunc(x[:,:,:,2] *65535)
y=x[:,:,:,0]
print(y.shape)
The resulting shape of y: (100, 32, 32)
Next you can use the reshape function on y.

How to make a Numpy 3D array with different length in the 2nd dimension?

I have some code that constructs a 3D numpy array (x_3d) on the fly using values from a 2D numpy array (x) in a forloop
x_3d = np.empty((0, 20, 10))
for i in range(num_samples):
x_3d = np.append(x_3d, [x[i*20:(i+1)*20, :]],
axis=0)
The resulting shape of the 3D array is (num_samples, 20, 10).
If I want to take slices of different length from the 2D array so that the number of rows varies how can I do that? I have looked at this post. By storing the 2D arrays initially in a list, and then transform the list back to an array gave me the shape of (num_samples, ), while each element is a 2D numpy array it is not a 3D numpy array with the shape of (num_samples, length_varies, 10).

Generating a 3D numpy array from variably-shaped 2D numpy arrays?

I am generating a large number of mel spectrograms to train a NN for phoneme detection.
Each mel spectrogram (generated with librosa.core.melspectrogram in Python) is represented as a 2D numpy array, where axis 1 (the length of the vectors) varies from spectrogram to spectrogram. They vary from shape (128, 2) to (128, 200).
In order to generate a 3D array, all spectrograms must have the same shape, so I'm guessing that I should append zeros to the ends of vectors that are shorter than 200. Then I can just add them all to a Python list, call np.array on it and a 3D numpy array will be generated, right?
I have attempted this myself unsuccessfully. All help is appreciated.
Edit: (code has been requested, this is essentially what I want to do)
spectrograms = []
for audio_array in all_audio_arrays:
audio_array, sr = librosa.core.load(audio_file, sr=sample_rate, mono=True)
melspectrogram = librosa.feature.melspectrogram(y=audio_array, sr=sample_rate, S=None, n_fft=window_size, hop_length=hop_length)
# melspectrogram is a 2D numpy array
# the shape could be between (128, 2) and (128, 200)
spectrograms.append(melspectrogram)
# I want this to be 3D
np.asarray(spectrograms)
I can't answer if it's an appropriate approach for your learner to pad with zeros. But doing so is quite easy using np.concatenate
import numpy as np
a = np.ones((128,2))
b = np.ones((128,200))
padding = np.zeros((a.shape[0], b.shape[1] - a.shape[1])) #(128, 198)
a = np.concatenate((a, padding), axis=1)
print (a.shape)
>>> (128L, 200L)

Categories

Resources