def calc_cost(x): cost = 0 for i in range(proj.nsubsets): # get the slice for the current subset ss = proj.subset_slices[i] exp = ppp.pet_fwd_model(x, proj, attn_sino[ss], sens_sino[ss], i, fwhm = fwhm) + contam_sino[ss] cost += (exp - em_sino[ss]*np.log(exp)).sum() return cost
sino_params = ppp.PETSinogramParameters(scanner, ntofbins=17, tofbin_width=15.) proj = ppp.SinogramProjector(scanner, sino_params, img.shape, nsubsets=1, voxsize=voxsize, img_origin=img_origin, ngpus=ngpus, tof=True, sigma_tof=60. / 2.35, n_sigmas=3.) # estimate the norm of the operator test_img = np.random.rand(*img.shape) for i in range(10): fwd = ppp.pet_fwd_model(test_img, proj, attn_sino, sens_sino, 0, fwhm=fwhm) back = ppp.pet_back_model(fwd, proj, attn_sino, sens_sino, 0, fwhm=fwhm) norm = np.linalg.norm(back) print(i, norm) test_img = back / norm # normalize sensitivity sinogram to get PET forward model for 1 view with norm 1 # this is important otherwise the step size T in SPDHG get dominated by the gradient sens_sino /= (np.sqrt(norm) / proj.sino_params.nviews) # forward project the image img_fwd = ppp.pet_fwd_model(img, proj, attn_sino, sens_sino, 0, fwhm=fwhm_data) # scale sum of fwd image to counts
#--------------------------------------------------------------------------- # generate the sensitivity sinogram sens_sino = np.ones((nsubsets, sino_shape_nt[0], sino_shape_nt[1] // nsubsets, sino_shape_nt[2], sino_shape_nt[3]), dtype=np.float32) / pr_norm img_fwd = np.zeros((nsubsets, sino_shape[0], sino_shape[1] // nsubsets, sino_shape[2], sino_shape[3]), dtype=np.float32) # forward project the image for i in range(nsubsets): img_fwd[i, ...] = ppp.pet_fwd_model(img, proj, attn_sino, sens_sino, i, fwhm=fwhm_data) # scale sum of fwd image to counts if counts > 0: scale_fac = (counts / img_fwd.sum()) img_fwd *= scale_fac img *= scale_fac # contamination sinogram with scatter and randoms contam_sino = np.full(img_fwd.shape, 0.2 * img_fwd.mean(), dtype=np.float32) em_sino = np.random.poisson(img_fwd + contam_sino)