def my_dePierroMap(image, obj_fun, beta, filter, num_subsets, num_subiterations, weights, sensitivity_image): # Check that weights are normalised if (np.abs(np.sum(weights, axis=1) - 1) > 1.0e-6).any(): raise ValueError("Weights should sum to 1 for each voxel") # Create OSEM reconstructor OSEM_reconstructor = pet.OSMAPOSLReconstructor() OSEM_reconstructor.set_output_filename_prefix('subiter') OSEM_reconstructor.set_objective_function(obj_fun) OSEM_reconstructor.set_num_subsets(num_subsets) OSEM_reconstructor.set_num_subiterations(num_subiterations) OSEM_reconstructor.set_up(image) current_image = image.clone() for iter in range(1, num_subiterations + 1): print('\n------------- Subiteration %d' % iter) # Calculate imageReg and return as an array imageReg_array = dePierroReg(current_image.as_array(), weights) # OSEM image update OSEM_reconstructor.update(current_image) imageEM_array = current_image.as_array() # Final image update imageUpdated_array = dePierroUpdate \ (imageEM_array, imageReg_array, beta, sensitivity_image.as_array()) # Fill image and truncate to cylindrical field of view current_image.fill(imageUpdated_array) filter.apply(current_image) image_out = current_image.clone() return image_out
imshow(acquisition_array[0, 0, :, :, ], [], 'Forward projection') #%% close all plots plt.close('all') #%% create objective function obj_fun = pet.make_Poisson_loglikelihood(acquired_data) # We could set acquisition model but the default (ray-tracing) is in this case ok # obj_fun.set_acquisition_model(am) #obj_fun.set_prior(prior) #%% create OSMAPOSL reconstructor # This implements the Ordered Subsets Maximum A-Posteriori One Step Late # Since we are not using a penalty, or prior in this example, it # defaults to using MLEM, but we will modify it to OSEM recon = pet.OSMAPOSLReconstructor() recon.set_objective_function(obj_fun) recon.set_num_subsets(4) num_iters = 10 recon.set_num_subiterations(num_iters) #%% create initial image # we could just use a uniform image but here we will create a disk with a different # initial value (this will help the display later on) init_image = image.clone() init_image.fill(cmax / 4) make_cylindrical_FOV(init_image) # display idata = init_image.as_array() slice_num = idata.shape[0] // 2 plt.figure() imshow(idata[slice_num, :, :], [0, cmax], 'initial image')