def test_scgrog(self): '''Make sure we get the same interpolation as MATLAB implementation.''' from mr_utils.gridding.scgrog import get_gx_gy from mr_utils.gridding import scgrog # Load in the test data data = load_test_data('mr_utils/test_data/tests/gridding/scgrog/', ['kspace_gridder', 'traj_gridder', 'cartdims']) kspace, traj, cartdims = data[0], data[1], data[2] # First get Gx,Gy Gx, Gy = get_gx_gy(kspace, traj, cartdims=cartdims) # Check to make sure Gx,Gy are correct data = load_test_data('mr_utils/test_data/tests/gridding/scgrog/', ['Gxm_data', 'Gym_data']) Gxm, Gym = data[0], data[1] self.assertTrue(np.allclose(Gx, Gxm)) self.assertTrue(np.allclose(Gy, Gym)) # Now use Gx,Gy to regrid using grog kspace, mask = scgrog(kspace, traj, Gx, Gy, cartdims) # Check our work to see if it worked data = load_test_data('mr_utils/test_data/tests/gridding/scgrog/', ['kspace_res', 'mask_res']) kspacem, maskm = data[0], data[1] self.assertTrue(np.allclose(kspace, kspacem)) self.assertTrue(np.allclose(mask, maskm))
def setUp(self): self.config = GadgetronConfig() path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'grappa_test_data.h5' load_test_data(path, [file], do_return=False) self.filename = '%s/%s' % (path, file)
def test_create_default_config(self): '''Make sure default config lines up with actual.''' config = configs.default() path = 'mr_utils/test_data/tests/gadgetron/config/' file = 'default.xml' load_test_data(path, [file], do_return=False) with open('%s/%s' % (path, file), 'r') as f: truth = f.read() res = len(main.diff_texts(truth.encode(), config.tostring().encode())) self.assertTrue(res == 0)
def test_use_generic_cartesian_grappa_config(self): '''Compare homegrown to Gagdetron config.''' config = configs.generic_cartesian_grappa() path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'meas_MID00450_FID76726_SAX_TE62_DIR_TSE.dat' load_test_data(path, [file], do_return=False) filename = '%s/%s' % (path, file) # print(config.tostring()) data, _header = client(filename, config_local=config.tostring()) data_true, _header_true = client(self.filename, config='Generic_Cartesian_Grappa.xml') self.assertTrue(np.allclose(data, data_true))
def test_generate_prior(self): '''Verify prior variable is the same as MATLAB''' prior_true = load_test_data( self.path, ['prior'], ) self.assertTrue(np.allclose(self.prior, prior_true))
def test_client_filename(self): '''Give the client only the filename.''' # Get the test input data path so we can send file to gadgetron path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'input.h5' load_test_data(path, [file], do_return=False) filename = '%s/%s' % (path, file) data, _header = client(filename) # Make sure we get the thing we expected path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'true_output.h5' load_test_data(path, [file], do_return=False) with h5py.File('%s/%s' % (path, file), 'r') as f: true_output_data = f['2018-11-02 20:35:19.785688']['image_0'][ 'data'][:] self.assertTrue(np.allclose(data, true_output_data))
def test_nIdx_real_and_imag(self): '''Verify nIdx_real/imag variables are the same as MATLAB''' real, imag = load_test_data(self.path, ['nIdx_real', 'nIdx_imag']) # print(np.unravel_index(self.nIdx_real, self.prior.shape)) self.assertTrue(np.allclose(self.nIdx_real, real - 1)) self.assertTrue(np.allclose(self.nIdx_imag, imag - 1))
def test_client_raw_input(self): '''Give the client the path to the raw data.''' # Give the filename of raw data to the client path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'input.dat' load_test_data(path, [file], do_return=False) filename = '%s/%s' % (path, file) data, _header = client(filename) # Make sure the output is the same as when h5 is given path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'true_output.h5' load_test_data(path, [file], do_return=False) with h5py.File('%s/%s' % (path, file), 'r') as f: true_output_data = f['2018-11-02 20:35:19.785688']['image_0'][ 'data'][:] self.assertTrue(np.allclose(data, true_output_data))
def test_client_ismrmrd_hdf5_input(self): '''Give the client the hdf5 file.''' # Load in the data so we can pass the client the ismrmrd.Dataset path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'input.h5' load_test_data(path, [file], do_return=False) filename = '%s/%s' % (path, file) dataset = ismrmrd.Dataset(filename, 'dataset', False) data, _header = client(dataset) # Make sure we still get the thing we expected path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'true_output.h5' load_test_data(path, [file], do_return=False) with h5py.File('%s/%s' % (path, file), 'r') as f: true_output_data = f['2018-11-02 20:35:19.785688']['image_0'][ 'data'][:] self.assertTrue(np.allclose(data, true_output_data))
def test_monotonic_sort_real_imag_parts(self): '''Verify sort orders are the same as MATLAB''' real_true, imag_true = load_test_data( self.path, ['sort_order_real', 'sort_order_imag']) # 0-based indexing real_true -= 1 imag_true -= 1 self.assertTrue(np.alltrue(self.sort_order_real == real_true)) self.assertTrue(np.alltrue(self.sort_order_imag == imag_true))
def test_get_gx_gy_results(self): '''Validate generation of GRAPPA kernels, Gx, Gy.''' from mr_utils.gridding.scgrog import get_gx_gy # Load in test data # kspace, traj = SCGROG.test_grog_data_4D() data = load_test_data('mr_utils/test_data/tests/gridding/scgrog/', ['kspace', 'traj']) kspace, traj = data[0], data[1] # Run the function Gx, Gy = get_gx_gy(kspace, traj) # Test it against the known truth data = load_test_data('mr_utils/test_data/tests/gridding/scgrog/', ['Gxm', 'Gym']) Gxm, Gym = data[0], data[1] self.assertTrue(np.allclose(Gx, Gxm)) self.assertTrue(np.allclose(Gy, Gym))
def setUpClass(cls): # Point self to cls so we can use it like in a normal method self = cls # Load in test data self.path = ('mr_utils/test_data/tests/cs/convex/' 'temporal_gd_tv') self.Coil, self.mask = load_test_data(self.path, ['Coil6', 'mask']) # For some reason they are the wrong dimensions coming out # of MATLAB, probably because they are old format self.Coil = self.Coil.T self.mask = self.mask.T # Set the recon parameters self.weight_fidelity = 1 self.weight_temporal = .01 self.beta_sqrd = 0.0000001 self.niter = 200 # Get an encoding model self.uft = UFT(self.mask, axes=(0, 1)) # Compute reduced kspace self.reduced_kspace = self.Coil * self.mask # Compute prior self.prior = generate_prior(self.Coil * self.mask, self.uft.inverse_s) # Compute monotonic sort order (self.sort_order_real, self.sort_order_imag) = sort_real_imag_parts(self.prior, axis=-1) # Compute measured image domain self.measuredImgDomain = self.uft.inverse_s(self.reduced_kspace) # Get reduced data, whatever that is self.reduced_data = np.abs(self.measuredImgDomain) # Get initial estimates self.img_est = self.measuredImgDomain.copy() self.W_img_est = self.measuredImgDomain.copy() # Construct R and C (rows and columns, I assume) rows, cols, pages = self.img_est.shape[:] self.R = np.tile(np.arange(rows), (cols, pages, 1)).transpose( (2, 0, 1)) self.C = np.tile(np.arange(cols), (rows, pages, 1)).transpose( (0, 2, 1)) # From R and C get the indices we'll actually use self.nIdx_real = self.R + self.C * rows + ( self.sort_order_real) * rows * cols self.nIdx_imag = self.R + self.C * rows + ( self.sort_order_imag) * rows * cols
def test_use_default_config(self): '''Send default config to gadgetron to verify that it runs.''' # Give the filename of raw data to the client path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'input.dat' load_test_data(path, [file], do_return=False) filename = '%s/%s' % (path, file) # Send gadgetron the local default configuration file config = configs.default() # print(config) # data,header = client(filename,config_local=config.get_filename()) data, _header = client(filename, config_local=config.tostring()) # Make sure the output is the same as when h5 is given path = 'mr_utils/test_data/tests/gadgetron/client/' file = 'true_output.h5' load_test_data(path, [file], do_return=False) with h5py.File('%s/%s' % (path, file), 'r') as f: true_output_data = f['2018-11-02 20:35:19.785688']['image_0'][ 'data'][:] self.assertTrue(np.allclose(data, true_output_data))
def setUp(self): from mr_utils.test_data import load_test_data path = 'mr_utils/test_data/tests/recon/ssfp/gs_recon/' files = [ 'I1', 'I2', 'I3', 'I4', 'I_max_mag', 'CS', 'Id', 'w13', 'w24', 'I' ] data = load_test_data(path, files) # Load in truth data self.I1 = data[0] self.I2 = data[1] self.I3 = data[2] self.I4 = data[3] self.Is = np.stack((data[:4])) self.I_max_mag = data[4] self.CS = data[5] self.Id = data[6] self.w13 = data[7] self.w24 = data[8] self.I = data[9]
def test_reduced_kspace(self): '''Verify reduced_kspace variable is the same as MATLAB''' reduced_kspace_true = load_test_data(self.path, ['reduced_kspace']) self.assertTrue(np.allclose(self.reduced_kspace, reduced_kspace_true))
def test_recon(self): '''Replicate MATLAB results.''' # Get the shepp logan phantom path = 'mr_utils/test_data/tests/recon/grappa/' im = load_test_data(path, ['phantom_shl'])[0] dim = im.shape[0] # Get simple coil sensitivities N = 6 # csm = simple_csm(N,(dim,dim)) csm = load_test_data(path, ['ch_sensitivity'])[0] # self.assertTrue(np.allclose(csm,csm_mat)) # Apply csm to image to get coil images coils = csm * im coils_mat = load_test_data(path, ['phantom_ch']) self.assertTrue(np.allclose(coils, coils_mat)) # Put each channel into kspace kspace = np.fft.fftshift( np.fft.fft2(np.fft.ifftshift(coils), axes=(1, 2))) kspace_mat = GRAPPA.phantom_ch_k() self.assertTrue(np.allclose(kspace, kspace_mat)) # Undersample by Rx Rx = 2 kspace_d = np.zeros(kspace.shape, dtype='complex') kspace_d[:, ::Rx, :] = kspace[:, ::Rx, :] kspace_d_mat = GRAPPA.phantom_ch_k_u() self.assertTrue(np.allclose(kspace_d, kspace_d_mat)) # Choose center fully samples lines as autocalibration signal (ACS) center_row, pad = int(dim / 2), 8 mask = np.zeros(kspace_d.shape, dtype=bool) mask[:, center_row - pad:center_row + pad, :] = True autocal = kspace[mask].reshape((N, -1, mask.shape[-1])) autocal_mat = GRAPPA.phantom_ch_k_acl() self.assertTrue( np.allclose( np.pad(autocal, ((0, 0), (24, 24), (0, 0)), mode='constant'), autocal_mat)) # Separate the autocalibration region into patches to get source matrix patch_size = (3, 3) S0 = np.zeros((N, (autocal.shape[1] - 2) * (autocal.shape[2] - 2), patch_size[0] * patch_size[1]), dtype='complex') for ii in range(N): S0[ii, :, :] = view_as_windows(autocal[ii, :, :], patch_size).reshape( (S0.shape[1], S0.shape[2])) S0_mat = GRAPPA.S_ch_temp() self.assertTrue(np.allclose(np.conj(S0), S0_mat)) # Remove the unknown values. The remaiming values form source matrix, # S, for each coil S_temp = S0[:, :, [0, 1, 2, 6, 7, 8]] S_temp_mat = GRAPPA.S_ch() self.assertTrue(np.allclose(np.conj(S_temp), S_temp_mat)) S = np.hstack(S_temp[:]) S_mat = GRAPPA.S() self.assertTrue(np.allclose(np.conj(S), S_mat)) # The middle pts form target vector, T, for each coil T = S0[:, :, 4].T T_mat = GRAPPA.T() self.assertTrue(np.allclose(np.conj(T), T_mat)) # Invert S to find weights, W W = np.linalg.pinv(S).dot(T) W_mat = GRAPPA.W() self.assertTrue(np.allclose(np.conj(W), W_mat)) # Now onto the forward problem to fill in the missing lines... # Make patches out of all acquired data (skip the missing lines) S0 = np.zeros((N, int((kspace_d.shape[1] - 2) / Rx) * (kspace_d.shape[2] - 2), patch_size[0] * patch_size[1]), dtype='complex') for ii in range(N): S0[ii, :, :] = view_as_windows(kspace_d[ii, :, :], patch_size, step=(Rx, 1)).reshape( (S0.shape[1], S0.shape[2])) S0_mat = GRAPPA.S_ch_new_temp() self.assertTrue(np.allclose(np.conj(S0), S0_mat)) # Remove the unknown values. The remaiming values form source matrix, # S, for each coil S_new_temp = S0[:, :, [0, 1, 2, 6, 7, 8]] S_new_temp_mat = GRAPPA.S_ch_new() self.assertTrue(np.allclose(np.conj(S_new_temp), S_new_temp_mat)) S_new = np.hstack(S_new_temp[:]) S_new_mat = GRAPPA.S_new() self.assertTrue(np.allclose(np.conj(S_new), S_new_mat)) T_new = S_new.dot(W) T_new_mat = GRAPPA.T_new() self.assertTrue(np.allclose(np.conj(T_new), T_new_mat)) # Back fill in the missing lines to recover the image lines = np.reshape(T_new.T, (N, -1, dim - 2)) lines_mat = GRAPPA.T_ch_new_M() self.assertTrue(np.allclose(lines, lines_mat)) kspace_d[:, 1:-1:Rx, 1:-1] = lines recon = sos(np.fft.fftshift( np.fft.ifft2(np.fft.ifftshift(kspace_d), axes=(1, 2))), axes=0) recon_mat = GRAPPA.Im_Recon() self.assertTrue(np.allclose(recon, recon_mat))
def test_R_and_C(self): '''Verify R, C variables are the same as MATLAB''' R, C = load_test_data(self.path, ['R', 'C']) self.assertTrue(np.allclose(self.R, R - 1)) self.assertTrue(np.allclose(self.C, C - 1))
def test_reduced_data(self): '''Verify reduced_data variable same as MATLAB''' reduced_data = load_test_data(self.path, ['reduced_data']) self.assertTrue(np.allclose(self.reduced_data, reduced_data))
from scipy.io.wavfile import read, write from scipy.fftpack import dct, idct from tqdm import tqdm from skimage.measure import compare_mse from mr_utils.utils.orderings import inverse_permutation from mr_utils.cs import relaxed_ordinator from mr_utils.utils import rank2pi, pi2rank from mr_utils.test_data import load_test_data if __name__ == '__main__': # Get some sample audio path = 'mr_utils/test_data/examples/music/' file = 'sample.wav' load_test_data(path, [file], do_return=False) filename = '%s/%s' % (path, file) rate, data = read(filename, mmap=True) orig_num_int16 = data.size # We're going to have to split this into chunks to make any sense. # These chunks should be small enough that we can compute the # rank of the permutations fairly easily. chunk_size = 16 tol = 1000 use_ordinator = False ranks1 = [] ranks2 = [] # Store coefficients like sparse vectors -- just locations and # values of nonzero elements
def setUp(self): data = load_test_data('mr_utils/test_data/tests/cs/thresholding/amp', ['cdf97', 'mask', 'x0', 'y']) self.cdf97, self.mask, self.x0, self.y = data[:] #pylint: disable=W0632 self.uft = UFT(self.mask) self.level = 5
from tqdm import tqdm import matplotlib.pyplot as plt from skimage.measure import compare_mse, compare_ssim from mr_utils.test_data import load_test_data from mr_utils import view from mr_utils.cs import proximal_GD from mr_utils.cs.models import UFT from mr_utils.utils.wavelet import cdf97_2d_forward, cdf97_2d_inverse from mr_utils.utils.orderings import bulk_up, whittle_down, colwise, rowwise from mr_utils.utils.sort2d import sort2d if __name__ == '__main__': # We need a mask mask = load_test_data('mr_utils/test_data/tests/recon/reordering', ['mask'])[0] mask = np.fft.fftshift(mask) # Get the encoding model uft = UFT(mask) # Load in the test data kspace = load_test_data('mr_utils/test_data/tests/recon/reordering', ['coil1'])[0] kspace = np.fft.fftshift(kspace) imspace = uft.inverse(kspace) # Undersample data to get prior kspace_u = kspace * mask imspace_u = uft.inverse(kspace_u)
def test_measuredImgDomain(self): '''Verify measuredImgDomain variable same as MATLAB''' mid = load_test_data(self.path, ['measuredImgDomain']) self.assertTrue(np.allclose(self.measuredImgDomain, mid))
This is a sanity check example to make sure we can recreate the results from the reference implementation. See mr_utils.cs.amp2d for details. ''' import numpy as np from mr_utils.cs import amp2d from mr_utils.cs.models import UFT from mr_utils.test_data import load_test_data from mr_utils import view if __name__ == '__main__': # Grab data for the example data = load_test_data('mr_utils/test_data/tests/cs/thresholding/amp/', ['x0', 'mask']) x, mask = data[0], data[1] uft = UFT(mask) # Simulate measurement y = uft.forward_ortho(x) # Reconstruct with AMP x_hat = amp2d( y, forward_fun=uft.forward_ortho, inverse_fun=uft.inverse_ortho, sigmaType=1, randshift=True, tol=1e-5, x=x,
see approximately uniform distributing between -pi and pi. So as long as var(real/imag) < var(magnitude), then we prefer to operate separately on real and imaginary components. ''' import numpy as np import matplotlib.pyplot as plt from mr_utils.test_data import load_test_data if __name__ == '__main__': # Load in STCR recon path = ('mr_utils/test_data/examples/cs/temporal/') imspace = load_test_data(path, ['stcr_recon'])[0] real = imspace.real.flatten() imag = imspace.imag.flatten() mag = np.abs(imspace.flatten()) phase = np.angle(imspace.flatten()) # Show the variance of the measurements print('Var of real: %g' % np.var(real)) # Laplacian? print('Var of imag: %g' % np.var(imag)) # Laplacian? print('Var of mag: %g' % np.var(mag)) # One-sided # Phase is approximately uniformly distributed it looks like # print(np.var(phase), (2*np.pi)**2/12) # This is wrapped though # nbins = 'auto'
import matplotlib.pyplot as plt from skimage.filters import threshold_li from skimage.measure import compare_mse from mr_utils.test_data import load_test_data from mr_utils.recon.ssfp import gs_recon from mr_utils.utils import sos from mr_utils import view from examples.coils.coil_combination_abstract.coil_combine_funs import get_coil_combine_funs if __name__ == '__main__': # Load in phantom data, shape: (512, 256, 4, 16) path = 'mr_utils/test_data/examples/coils/' imspace, kspace = load_test_data(path, ['imspace', 'kspace']) print(imspace.shape) nx, ny, nc, npcs = imspace.shape[:] trim = int(nx / 4) pcs = np.linspace(0, 2 * np.pi, npcs, endpoint=False) # Get mask ngs = int(npcs / 4) tmp = np.zeros((nx, ny, nc, ngs), dtype='complex') for coil in range(nc): for ii in range(ngs): tmp[..., coil, ii] = gs_recon(imspace[..., coil, ii::4], pc_axis=-1) im_true = np.mean(tmp, axis=-1) im_true = sos(im_true, axes=-1) thresh = threshold_li(im_true)
from mr_utils.test_data import load_test_data from mr_utils.sim.traj import radial from mr_utils.cs.models import UFT from mr_utils.cs import ordinator1d, relaxed_ordinator from mr_utils.utils import Sparsify from mr_utils import view if __name__ == '__main__': # Load in STCR recon sl0 = 0 # which of the two slices to use skip = 11 # skip beginning to reduce computational burden slash = 25 # skip end "" path = ('mr_utils/test_data/examples/cs/temporal/') imspace_true = load_test_data( path, ['stcr_recon'])[0][..., skip:-slash, sl0] sx, sy, st = imspace_true.shape[:] # view(imspace_true) # We want to mask out the areas we want, start with a simple # circle xx = np.linspace(0, sx, sx) yy = np.linspace(0, sy, sy) X, Y = np.meshgrid(xx, yy) radius = 9 ctr = (128, 130) roi = (X - ctr[0])**2 + (Y - ctr[1])**2 < radius**2 roi0 = np.tile(roi, (st, 1, 1)).transpose((1, 2, 0)) print('%d curves in roi' % int(np.sum(roi.flatten()))) # view(roi) S = Sparsify()
mu = np.median(x) b = 1 / N * np.sum(np.abs(x - mu)) return 2 * b**2 def exp_sample_var(x): '''Sample variance of exponential random variable.''' N = x.size return (1 / (N / np.sum(x)))**2 if __name__ == '__main__': # Load in brain path = 'mr_utils/test_data/examples/cs/reordering/paper/figures/' im = load_test_data(path, ['ssfp_brain'])[0] im /= np.max(np.abs(im.flatten())) * .1 plt.subplot(1, 3, 1) plt.hist(im.real.flatten(), density=True) plt.title('Distribution of Real') plt.xlabel('Variance: %g' % laplace_sample_var(im.real.flatten())) plt.subplot(1, 3, 2) plt.hist(im.imag.flatten(), density=True) plt.title('Distribution of Imag') plt.xlabel('Variance: %g' % laplace_sample_var(im.imag.flatten())) plt.subplot(1, 3, 3) plt.hist(np.abs(im.flatten()), density=True) plt.title('Distribution of Mag')