def test_phantom_cylinder(self): # Compare to pre-made phantom (check size and values) phantom = pht.makeCylindricalPhantom() test_data_path = constants.SERVER_SIM_BLOCH_PATH / 'test_data' / 'test_cylindrical_phantom_maps.npy' maps = np.load(test_data_path) self.assertIsInstance(phantom, pht.DTTPhantom) np.testing.assert_allclose(phantom.PDmap, maps[:,:,:,0]) np.testing.assert_allclose(phantom.T1map, maps[:,:,:,1]) np.testing.assert_allclose(phantom.T2map, maps[:,:,:,2])
def sim_sequence(seq): nn = 15 phantom = pht.makeCylindricalPhantom(dim=2, dir='z', loc=0, n=nn) # Time the code: Tic start_time = time.time() # Store seq info seq_info = blcsim.store_pulseq_commands(seq) # Get list of locations from phantom loc_ind_list = phantom.get_list_inds() # Initiate multiprocessing pool pool = mp.Pool(mp.cpu_count()) # Parallel simulation df = 0 results = pool.starmap_async(blcsim.sim_single_spingroup, [(loc_ind, df, phantom, seq_info) for loc_ind in loc_ind_list]).get() pool.close() # Add up signal across all SpinGroups signal = np.sum(results, axis=0) # Time the code: Toc print("Time used: %s seconds" % (time.time() - start_time)) return signal
import time import matplotlib as mpl mpl.use('TkAgg') import matplotlib.pyplot as plt import numpy as np import virtualscanner.server.simulation.bloch.phantom as pht import virtualscanner.server.simulation.bloch.pulseq_blochsim_methods as blcsim import virtualscanner.server.simulation.bloch.pulseq_library as psl if __name__ == '__main__': # Make a phantom nn = 49 myphantom = pht.makeCylindricalPhantom(dim=2, dir='z', loc=0, n=nn) df = 0 # Define sequence parameters # FOV = [0.24,0.24] FOV = 0.24 # N = [21,21] N = 49 FA = 90 TR = 2 TE = 0.5 slice_locs = [0] thk = 0.24 / 49 # Defining oblique encoding directions # Mrot = np.array([[1, 0, 0],
loc_vec_dict = {'x': (1, 0, 0), 'y': (0, 1, 0), 'z': (0, 0, 1)} myphantom = pht.makePlanarPhantom( n=args.n_ph, fov=args.fov_ph, T1s=args.T1s, T2s=args.T2s, PDs=args.PDs, radii=Rs, dir=args.dir_ph, loc=0) # now, 2D phantom is not moved around # args.slice_loc*np.array(loc_vec_dict[args.enc[2]])) elif args.pht_type == 'cylindrical': print("Making cylindrical phantom") myphantom = pht.makeCylindricalPhantom(dim=args.pht_dim, n=args.n_ph, dir=args.dir_ph, loc=0) elif args.pht_type == 'NIST': myphantom = [] # myphantom = pht.get_NIST_Phantom() else: raise ValueError("Phantom type non-existent!") # Slice locations Ns = args.num_slices g = args.slice_gap t = args.thk slice_locs = np.arange(-(Ns - 1) * (g + t) / 2, Ns * (g + t) / 2, g + t) print('Slice locations:', slice_locs)
def create_and_save_phantom(phantom_info, out_folder): """Generates a phantom and saves it into desired folder as .h5 file for JEMRIS purposes Inputs ------ phantom_info : dict Info of phantom to be constructed REQUIRED 'fov' : float, field-of-view [meters] 'N' : int, phantom matrix size (isotropic) 'type' : str, 'spherical', 'cylindrical' or 'custom' 'dim' : int, either 3 or 2; 3D or 2D phantom options 'dir' : str, {'x', 'y', 'z'}; orientation of 2D phantom OPTIONAL (only required for 'custom' phantom type) 'T1' : np.ndarray, T1 map matrix 'T2' : np.ndarray, T2 map matrix 'PD' : np.ndarray, PD map matrix 'dr' : float, voxel size [meters] (isotropic) 'dBmap' : optional even for 'custom' type. If not provided, dB is set to 0 everywhere. out_folder : str or pathlib Path object Path to directory where phantom will be saved Returns ------- pht_type : str phantom_info['pht_type'] (returned for naming purposes) """ out_folder = str(out_folder) FOV = phantom_info['fov'] N = phantom_info['N'] pht_type = phantom_info['type'] pht_dim = phantom_info['dim'] pht_dir = phantom_info['dir'] sim_phantom = 0 if pht_type == 'spherical': print('Making spherical phantom') T1s = [1000] T2s = [100] PDs = [1] R = 0.8 * FOV / 2 Rs = [R] if pht_dim == 3: sim_phantom = pht.makeSphericalPhantom(n=N, fov=FOV, T1s=T1s, T2s=T2s, PDs=PDs, radii=Rs) elif pht_dim == 2: sim_phantom = pht.makePlanarPhantom(n=N, fov=FOV, T1s=T1s, T2s=T2s, PDs=PDs, radii=Rs, dir=pht_dir, loc=0) elif pht_type == 'cylindrical': print("Making cylindrical phantom") sim_phantom = pht.makeCylindricalPhantom(dim=pht_dim, n=N, dir=pht_dir, loc=0) elif pht_type == 'custom': # Use a custom file! T1 = phantom_info['T1'] T2 = phantom_info['T2'] PD = phantom_info['PD'] dr = phantom_info['dr'] if 'dBmap' in phantom_info.keys(): dBmap = phantom_info['dBmap'] else: dBmap = 0 sim_phantom = pht.Phantom(T1map=T1, T2map=T2, PDmap=PD, vsize=dr, dBmap=dBmap, loc=(0, 0, 0)) else: raise ValueError("Phantom type non-existent!") # Save as h5 sim_phantom.output_h5(out_folder, pht_type) return pht_type
import virtualscanner.server.simulation.bloch.phantom as pht from pypulseq.Sequence.sequence import Sequence import time import multiprocessing as mp import virtualscanner.server.simulation.bloch.pulseq_blochsim_methods as blcsim if __name__ == '__main__': # Make phantom dfmap = np.zeros((32, 32, 1)) txmap = np.ones((32, 32, 1)) rxmap = np.ones((32, 32, 1)) myphantom = pht.makeCylindricalPhantom(dim=2, n=32, dir='z', loc=0, fov=0.25) # Load the sequence : choose your own myseq = Sequence() myseq.read( 'sim/amri_debug/b0demo/tse_ms_FOV250mm_N32_Ns1_TR2000ms_TE12ms_4echoes_dwell200.0us.seq' ) # Time the code: Tic start_time = time.time() # Store seq info seq_info = blcsim.store_pulseq_commands(myseq) # Get list of locations from phantom loc_ind_list = myphantom.get_list_inds()