def optimize_modifier(values, projections, geometry, samp = [1, 1, 1], key = 'axs_tan', metric = 'correlation', update = True, preview = False): ''' Optimize a geometry modifier using a particular sampling of the projection array. ''' maxiter = values.size # Valuse of the objective function: func_values = numpy.zeros(maxiter) print('Starting a full search from: %0.3f' % values.min(), 'to %0.3f'% values.max()) time.sleep(0.3) # To print TQDM properly ii = 0 for val in tqdm(values, unit = 'point'): func_values[ii] = _modifier_l2cost_(projections, geometry, samp, val, key, metric = metric, preview = preview) ii += 1 min_index = func_values.argmin() display.plot2d(values, func_values, title = 'Objective: ' + key) guess = _parabolic_min_(func_values, min_index, values) if update: geometry[key] = guess print('Optimum found at %3.3f' % guess) return guess
def equivalent_density(projections, geometry, energy, spectr, compound, density, preview = False): ''' Transfrom intensity values to projected density for a single material array ''' # Assuming that we have log array! print('Generating the transfer function.') if preview: display.plot2d(energy, spectr, semilogy=False, title = 'Spectrum') # Attenuation of 1 mm: mu = model.linear_attenuation(energy, compound, density) # Make thickness range that is sufficient for interpolation: #m = (geometry['src2obj'] + geometry['det2obj']) / geometry['src2obj'] #img_pix = geometry['det_pixel'] / m img_pix = geometry['img_pixel'] thickness_min = 0 thickness_max = max(projections.shape) * img_pix * 2 print('Assuming thickness range:', [thickness_min, thickness_max]) thickness = numpy.linspace(thickness_min, thickness_max, max(projections.shape)) exp_matrix = numpy.exp(-numpy.outer(thickness, mu)) synth_counts = exp_matrix.dot(spectr) #flexUtil.plot(thickness, title = 'thickness') #flexUtil.plot(mu, title = 'mu') #flexUtil.plot(synth_counts, title = 'synth_counts') if preview: display.plot2d(thickness,synth_counts, semilogy=True, title = 'Attenuation v.s. thickness [mm].') synth_counts = -numpy.log(synth_counts) print('Callibration attenuation range:', [synth_counts[0], synth_counts[-1]]) print('array attenuation range:', [projections.min(), projections.max()]) print('Applying transfer function.') time.sleep(0.5) # Give time to print messages before the progress is created for ii in tqdm(range(projections.shape[1]), unit = 'img'): projections[:, ii, :] = numpy.array(numpy.interp(projections[:, ii, :], synth_counts, thickness * density), dtype = 'float32') return projections
def SIRT( projections, volume, geometry, iterations): """ Simultaneous Iterative Reconstruction Technique. """ ss = settings preview = ss.preview bounds = ss.bounds logger.print('Feeling SIRTy...') # Residual norms: rnorms = [] # Progress bar: pbar = _pbar_start_(iterations, 'iterations') for ii in range(iterations): # L2 update: norm = l2_update(projections, volume, geometry) if norm: rnorms.append(norm) # Apply bounds if bounds: numpy.clip(volume, a_min = bounds[0], a_max = bounds[1], out = volume) if preview: display.slice(volume, dim = 1, title = 'Preview') else: _pbar_update_(pbar) # Stop progress bar _pbar_close_(pbar) if rnorms: display.plot2d(rnorms, semilogy = True, title = 'Resudual L2')