def register_astra_geometry(proj_fix, proj_mov, geom_fix, geom_mov, subsamp=1): """ Compute a rigid transformation that makes sure that two reconstruction volumes are alligned. Args: proj_fix : projection data of the fixed volume proj_mov : projection data of the fixed volume geom_fix : projection data of the fixed volume geom_mov : projection data of the fixed volume Returns: geom : geometry for the second reconstruction volume """ print('Computing a rigid tranformation between two datasets.') # Find maximum vol size: sz = numpy.array([proj_fix.shape, proj_mov.shape]).max(0) sz += 10 # for safety... vol1 = numpy.zeros(sz, dtype='float32') vol2 = numpy.zeros(sz, dtype='float32') projector.settings.bounds = [0, 10] projector.settings.subsets = 10 projector.settings['mode'] = 'sequential' projector.FDK(proj_fix, vol1, geom_fix) projector.SIRT(proj_fix, vol1, geom_fix, iterations=5) projector.FDK(proj_mov, vol2, geom_mov) projector.SIRT(proj_mov, vol2, geom_mov, iterations=5) display.slice(vol1, title='Fixed volume preview') display.slice(vol1, title='Moving volume preview') # Find transformation between two volumes: R, T = register_volumes(vol1, vol2, subsamp=subsamp, use_moments=True, use_CG=True) return R, T
def _sample_FDK_(projections, geometry, sample): ''' Compute a subsampled version of FDK ''' geometry_ = geometry.copy() projections_ = projections[::sample[0], ::sample[2], ::sample[2]] # Apply subsampling to detector and volume: vol_sample = [sample[0], sample[1], sample[2]] det_sample = [sample[0], sample[2], sample[2]] geometry_['vol_sample'] = vol_sample geometry_['det_sample'] = det_sample volume = projector.init_volume(projections_) # Do FDK without progress_bar: projector.settings.progress_bar = False projector.FDK(projections_, volume, geometry_) projector.settings.progress_bar = True return volume
] # Sinogram that will be simultated: counts = numpy.zeros([1, 128, 128], dtype='float32') # Simulate: model.forward_spectral(vol, counts, geom, mats, E, S, n_phot=1e6) proj = -numpy.log(counts) # Display: display.slice(proj, title='Modelled sinogram') #%% Reconstruct: vol_rec = numpy.zeros_like(vol) projector.FDK(proj, vol_rec, geom) display.slice(vol_rec, title='Uncorrected FDK') display.plot(vol_rec[0, 64], title='Crossection') #%% Estimate system spectrum: print('Callibrating spectrum...') energy, spec = analyze.calibrate_spectrum(proj, vol, geom, compound='Al', density=2.7) #meta = {'energy':e, 'spectrum':s, 'description':geom.description} #data.write_toml(os.path.join(path, 'spectrum.toml'), meta)
#%% Unfiltered back-project # Make volume: vol_rec = numpy.zeros_like(vol) # Backproject: projector.backproject(proj, vol_rec, geom) display.slice(vol_rec, title = 'Backprojection') #%% Filtered back-project # Make volume: vol_rec = numpy.zeros_like(vol) # Use FDK: projector.FDK(proj, vol_rec, geom) display.slice(vol_rec, title = 'FDK') #%% Simple SIRT: vol_rec = numpy.zeros_like(vol) projector.SIRT(proj, vol_rec, geom, iterations = 20) display.slice(vol_rec, title = 'SIRT') #%% SIRT with subsets and non-negativity: # Settings: projector.settings.update_residual = True projector.settings.bounds = [0, 2] projector.settings.subsets = 10 projector.settings.sorting = 'equidistant'
proj_a = numpy.zeros([128, 32, 128], dtype='float32') proj_b = numpy.zeros([128, 32, 128], dtype='float32') # Forward project: projector.forwardproject(proj_a, vol, geom_a) projector.forwardproject(proj_b, vol, geom_b) display.slice(proj_a, dim=1, title='Proj A') display.slice(proj_b, dim=1, title='Proj B') #%% Preview reconstructions: geom_b = geom_a.copy() # First volume: vola = projector.init_volume(proj_a) projector.FDK(proj_a, vola, geom_a) # Second volume: volb = projector.init_volume(proj_b) projector.FDK(proj_b, volb, geom_b) display.projection(vola, dim=1, title='Volume A') display.projection(volb, dim=1, title='Volume B') #%% Register: R, T = process.register_volumes(vola, volb, subsamp=1, use_moments=True, use_CG=True)
display.slice(vol, title='Phantom') # Forward project: projector.forwardproject(proj, vol, geom) display.slice(proj, dim=1, title='Projection') #%% Use optimize_rotation_center: # Unmodified geometry: geom = geometry.circular(src2obj=100, det2obj=100, det_pixel=0.1, ang_range=[0, 360]) vol = projector.init_volume(proj) projector.FDK(proj, vol, geom) display.slice(vol, bounds=[0, 2], title='FDK: uncorrected') #%% Optimization: vals = numpy.linspace(0., 3., 7) process.optimize_modifier(vals, proj, geom, samp=[1, 1, 1], key='det_roll', metric='highpass') #%% Reconstruct: vol = projector.init_volume(proj)
phase_ctf *= model.ctf(proj.shape[::2], 'gaussian', [det_pixel, sigma * 1]) # Electro-magnetic field image: proj_i = numpy.exp(-proj * n) # Field intensity: data.convolve_filter(proj_i, phase_ctf) proj_i = numpy.abs(proj_i)**2 display.slice(proj_i, title='Sinogram (phase contrast)') #%% Reconstruct directly: vol_rec = numpy.zeros_like(vol) projector.FDK(-numpy.log(proj_i), vol_rec, geom) display.slice(vol_rec, title='FDK (Raw)') #%% Invertion of phase contrast based on dual-CTF model: # Propagator (Dual CTF): alpha = numpy.imag(n) / numpy.real(n) dual_ctf = model.ctf(proj.shape[::2], 'dual_ctf', [det_pixel, energy, src2obj, det2obj, alpha]) dual_ctf *= model.ctf(proj.shape[::2], 'gaussian', [det_pixel, sigma]) # Use inverse convolution to solve for blurring and phase contrast data.deconvolve_filter(proj_i, dual_ctf, epsilon=0.1) # Depending on epsilon there is some lof frequency bias introduced... proj_i /= proj_i.max()