def correct_lors(lors, fov_center, fov_size, lyso_center0, lyso_size0, lyso_center1, lyso_size1, weights=None, atten_coef=0.0096, lyso_atten_coef=0.087, system_shape=miil.default_system_shape, correct_lyso_atten=True, correct_uniform_atten=True, packing_frac=default_packing_frac): vec = miil.create_sparse_column_vector(lors) if correct_uniform_atten or correct_lyso_atten: line_start, line_end = miil.get_lor_positions(vec.indices, system_shape) if correct_uniform_atten: fov_length = voxel_intersection_length(line_start, line_end, fov_center, fov_size) vec.data *= np.squeeze(np.exp(atten_coef * fov_length)) if correct_lyso_atten: vec.data *= lyso_atten_weight(lors, lyso_center0, lyso_size0, lyso_center1, lyso_size1, lyso_atten_coef, packing_frac) if weights is not None: crystal0, crystal1 = miil.lor_to_crystals(vec.indices, miil.default_system_shape) vec.data *= weights[crystal0] vec.data *= weights[crystal1] return vec
def test_back_project_multiple_subsets(self): image_shape = (324, 128, 68) voxel_size_mm = 0.5 sigma = voxel_size_mm model = miil.recon.BreastPETSystemMatrix(image_shape, voxel_size_mm=voxel_size_mm, sigma=sigma, tor_width=1) lors = np.array(2 * (855655487, ), dtype=np.int64) # LOR straight across FOV x_mm = voxel_size_mm * (np.arange(0, image_shape[0]) - image_shape[0] / 2 + 0.5) z_mm = voxel_size_mm * (np.arange(0, image_shape[2]) - image_shape[2] / 2 + 0.5) pos0, pos1 = miil.get_lor_positions(lors) ref = np.ones(image_shape, dtype=np.float32) d2 = ((pos0[0,0] - x_mm[:, None, None]) / voxel_size_mm) ** 2 + \ ((pos0[0,2] - z_mm[None, None, :]) / voxel_size_mm) ** 2 d2_exp = np.exp(-d2 * sigma) d2_exp[d2 > 1.0] = 0 ref *= d2_exp # Double the reference for the two of the same lors ref *= 2 # split the two lors into two subsets. val = model.back_project(lors, subset_size=1) assert (((val == 0) == (ref == 0)).all()) assert ((np.abs(val - ref) < 1e-5).all())
def test_back_project_with_slor_weights(self): image_shape = (324, 128, 68) voxel_size_mm = 0.5 sigma = voxel_size_mm model = miil.recon.BreastPETSystemMatrix(image_shape, voxel_size_mm=voxel_size_mm, sigma=sigma, tor_width=1) weight_val = 2.0 slor_weights = weight_val * np.ones(miil.no_slors()) lors = np.array((855655487, ), dtype=np.int64) # LOR straight across FOV val = model._back_project(lors, slor_weights=slor_weights) x_mm = voxel_size_mm * (np.arange(0, image_shape[0]) - image_shape[0] / 2 + 0.5) z_mm = voxel_size_mm * (np.arange(0, image_shape[2]) - image_shape[2] / 2 + 0.5) pos0, pos1 = miil.get_lor_positions(lors) ref = np.ones(image_shape, dtype=np.float32) d2 = ((pos0[0,0] - x_mm[:, None, None]) / voxel_size_mm) ** 2 + \ ((pos0[0,2] - z_mm[None, None, :]) / voxel_size_mm) ** 2 d2_exp = np.exp(-d2 * sigma) d2_exp[d2 > 1.0] = 0 ref *= d2_exp ref *= weight_val assert (((val == 0) == (ref == 0)).all()) assert ((np.abs(val - ref) < 1e-5).all()) val = model.back_project(lors, slor_weights=slor_weights) assert (((val == 0) == (ref == 0)).all()) assert ((np.abs(val - ref) < 1e-5).all())
def lyso_length(lors, lyso_center0=default_panel0_lyso_center, lyso_size0=default_lyso_size, lyso_center1=default_panel1_lyso_center, lyso_size1=default_lyso_size, system_shape=miil.default_system_shape): line_start, line_end = miil.get_lor_positions(lors, system_shape) length = \ voxel_intersection_length( line_start, line_end, lyso_center0, lyso_size0) + \ voxel_intersection_length( line_start, line_end, lyso_center1, lyso_size1) return length
def uniform_phantom_nonuniform_illum_weight( lors, fov_center=default_fov_center, fov_size=default_fov_size, ref_length=None, system_shape=miil.default_system_shape): # If the refence length is not specified, then assume the width of the FOV # in Y. if ref_length is None: ref_length = fov_size[1] line_start, line_end = miil.get_lor_positions(lors, system_shape) fov_length = voxel_intersection_length(line_start, line_end, fov_center, fov_size) weight = fov_length / ref_length return weight
def correct_uniform_phantom_lors(lors, fov_center, fov_size, lyso_center0, lyso_size0, lyso_center1, lyso_size1, atten_coef=0.0096, lyso_atten_coef=0.087, system_shape=miil.default_system_shape, packing_frac=default_packing_frac): vec = miil.create_sparse_column_vector(lors) line_start, line_end = miil.get_lor_positions(vec.indices, system_shape) fov_length = voxel_intersection_length(line_start, line_end, fov_center, fov_size) vec.data *= np.squeeze(np.exp(atten_coef * fov_length) / fov_length) vec.data *= lyso_atten_weight(lors, lyso_center0, lyso_size0, lyso_center1, lyso_size1, lyso_atten_coef, packing_frac) return vec