| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- # Converts the jemris simulation outputs (signals.h5 files) into data or save as .npy or .mat files
- # Gehua Tong
- # March 06, 2020
- import h5py
- import numpy as np
- import matplotlib.pyplot as plt
- def recon_jemris(file, dims):
- """Reads JEMRIS's signals.h5 output, reconstructs it (Cartesian only for now) using the dimensions specified,
- and returns both the complex k-space and image matrix AND magnitude images
- Inputs
- ------
- file : str
- Path to signals.h5
- dims : array_like
- Dimensions for reconstruction
- [Nro], [Nro, Nline], or [Nro, Nline, Nslice]
- Returns
- -------
- kspace : np.ndarray
- Complex k-space
- imspace : np.ndarray
- Complex image space
- images : np.ndarray
- Real, channel-combined images
- """
- Mxy_out, M_vec_out, times_out = read_jemris_output(file)
- kspace, imspace = recon_jemris_output(Mxy_out, dims)
- images = save_recon_images(imspace)# TODO save as png (use previous code!)
- return kspace, imspace, images
- def read_jemris_output(file):
- """Reads and parses JEMRIS's signals.h5 output
- Inputs
- ------
- file : str
- Path to signals.h5
- Returns
- -------
- Mxy_out : np.ndarray
- Complex representation of transverse magnetization sampled during readout
- Matrix dimensions : (total # readouts) x (# channels)
- M_vec_out : np.ndarray
- 3D representation of magnetization vector (Mx, My, Mz) sampled during readout
- Matrix dimensions : (total # readouts) x 3 x (# channels)
- times_out : np.ndarray
- Timing vector for all readout points
- """
- # 1. Read simulated data
- f = h5py.File(file,'r')
- signal = f['signal']
- channels = signal['channels']
- # 2. Initialize output array
- Nch = len(channels.keys())
- Nro_tot = channels[list(channels.keys())[0]].shape[0]
- M_vec_out = np.zeros((Nro_tot,3,Nch))
- Mxy_out = np.zeros((Nro_tot,Nch), dtype=complex)
- times_out = np.array(signal['times'])
- # 3. Read each channel and store in array
- for ch, key in enumerate(list(channels.keys())):
- one_ch_data = np.array(channels[key])
- M_vec_out[:,:,ch] = one_ch_data
- Mxy_out[:,ch] = one_ch_data[:,0] + 1j*one_ch_data[:,1]
- return Mxy_out, M_vec_out, times_out
- def recon_jemris_output(Mxy_out, dims):
- """Cartesian reconstruction of JEMRIS simulation output
- # (No EPI/interleave reordering)
- Inputs
- ------
- Mxy_out : np.ndarray
- Complex Nt x Nch array where Nt is the total number of data points and Nch is the number of channels
- dims : array_like
- [Nro], [Nro, Nline], or [Nro, Nline, Nslice]
- Returns
- -------
- kspace : np.ndarray
- Complex k-space matrix
- imspace : np.ndarray
- Complex image space matrix
- """
- Nt, Nch = Mxy_out.shape
- print(Nt)
- if Nt != np.prod(dims):
- raise ValueError("The dimensions provided do not match the total number of samples.")
- Nro = dims[0]
- Nline = 1
- Nslice = 1
- ld = len(dims)
- if ld >= 1:
- Nro = dims[0]
- if ld >= 2:
- Nline = dims[1]
- if ld == 3:
- Nslice = dims[2]
- if ld > 3:
- raise ValueError("dims should have at 1-3 numbers : Nro, (Nline), and (Nslice)")
- kspace = np.zeros((Nro, Nline, Nslice, Nch),dtype=complex)
- imspace = np.zeros((Nro, Nline, Nslice, Nch),dtype=complex)
- np.reshape(Mxy_out, (Nro, Nline, Nslice))
- for ch in range(Nch):
- kspace[:,:,:,ch] = np.reshape(Mxy_out[:, ch], (Nro, Nline, Nslice), order='F')
- for sl in range(Nslice):
- imspace[:,:,sl,ch] = np.fft.fftshift(np.fft.ifft2(kspace[:,:,sl,ch]))
- return kspace, imspace
- def save_recon_images(imspace, method='sum_squares'):
- """For now, this method combines channels and returns the image matrix
- (Future, for GUI use: add options to save as separate image files / mat / etc. in a directory)
- Inputs
- ------
- imspace : np.ndarray
- Complex image space. The last dimension must be # Channels.
- method : str, optional
- Method used for combining channels
- Either 'sum_squares' (default, sum of squares) or 'sum_abs' (sum of absolute values)
- Returns
- -------
- images : np.ndarray
- Real, channel_combined image matrix
- """
- if method == 'sum_squares':
- images = np.sum(np.square(np.absolute(imspace)),axis=-1)
- elif method == 'sum_abs':
- images = np.sum(np.absolute(imspace), axis=-1)
- else:
- raise ValueError("Method not recognized. Must be either sum_squares or sum_abs")
- return images
- if __name__ == '__main__':
- Mxy_out, M_vec_out, times_out = read_jemris_output('sim/test0405/signals.h5')
- kk, im = recon_jemris_output(Mxy_out, dims=[15,15])
- images = save_recon_images(im)
- plt.figure(1)
- plt.subplot(121)
- plt.imshow(np.absolute(kk[:,:,0,0]))
- plt.title("k-space")
- plt.gray()
- plt.subplot(122)
- print(images)
- plt.imshow(np.squeeze(images[:,:,0]))
- plt.title("Image space")
- plt.gray()
- plt.show()
|