def clean_sino(h5fname, chunks=None): import tomopy import dxchange # Read APS 32-BM raw data. #print('reading data') proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=chunks) #proj, flat, dark, theta = dxchange.read_aps_32id(h5fname) # # Manage the missing angles: # if blocked_views is not None: # print("Blocked Views: ", blocked_views) # proj = np.concatenate((proj[0:blocked_views[0],:,:], proj[blocked_views[1]+1:-1,:,:]), axis=0) # theta = np.concatenate((theta[0:blocked_views[0]], theta[blocked_views[1]+1:-1])) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) #data = tomopy.normalize(proj, flat, dark, cutoff=(1,2)) # remove stripes #print('removing stripes, may take a while',flush=True) data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) #print("Raw data: ", h5fname) #print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 data=np.swapaxes(data,0,1) return data, theta
def find_rotation_axis(h5fname, nsino): data_size = get_dx_dims(h5fname, 'data') ssino = int(data_size[1] * nsino) # Select sinogram range to reconstruct sino = None start = ssino end = start + 1 sino = (start, end) # Read APS 32-BM raw data proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Flat-field correction of raw data data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=5, wname='sym16', sigma=1, pad=True) # find rotation center rot_center = tomopy.find_center_vo(data) return rot_center
def rec_try(h5fname, nsino, rot_center, center_search_width, algorithm, binning): zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white data_shape = get_dx_dims(h5fname, 'data') print(data_shape) ssino = int(data_shape[1] * nsino) center_range = (rot_center-center_search_width, rot_center+center_search_width, 0.5) #print(sino,ssino, center_range) #print(center_range[0], center_range[1], center_range[2]) # Select sinogram range to reconstruct sino = None start = ssino end = start + 1 sino = (start, end) # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # zinger_removal proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) stack = np.empty((len(np.arange(*center_range)), data_shape[0], data_shape[2])) index = 0 for axis in np.arange(*center_range): stack[index] = data[:, 0, :] index = index + 1 # Reconstruct the same slice with a range of centers. rec = tomopy.recon(stack, theta, center=np.arange(*center_range), sinogram_order=True, algorithm='gridrec', filter_name='parzen', nchunk=1) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) index = 0 # Save images to a temporary folder. fname = os.path.dirname(h5fname) + '/' + 'try_rec/' + 'recon_' + os.path.splitext(os.path.basename(h5fname))[0] for axis in np.arange(*center_range): rfname = fname + '_' + str('{0:.2f}'.format(axis) + '.tiff') dxchange.write_tiff(rec[index], fname=rfname, overwrite=True) index = index + 1 print("Reconstructions: ", fname)
def rec_test(file_name, sino_start, sino_end, astra_method, extra_options, num_iter=1): print '\n#### Processing '+ file_name sino_start = sino_start + 200 sino_end = sino_start + 2 print "Test reconstruction of slice [%d]" % sino_start # Read HDF5 file. prj, flat, dark = tomopy.io.exchange.read_aps_32id(file_name, sino=(sino_start, sino_end)) # Manage the missing angles: theta = tomopy.angles(prj.shape[0]) prj = np.concatenate((prj[0:miss_angles[0],:,:], prj[miss_angles[1]+1:-1,:,:]), axis=0) theta = np.concatenate((theta[0:miss_angles[0]], theta[miss_angles[1]+1:-1])) # normalize the prj prj = tomopy.normalize(prj, flat, dark) # remove ring artefacts prjn = tomopy.remove_stripe_fw(prj) # reconstruct rec = tomopy.recon(prj[:,::reduce_amount,::reduce_amount], theta, center=float(best_center)/reduce_amount, algorithm=tomopy.astra, options={'proj_type':proj_type,'method':astra_method,'extra_options':extra_options,'num_iter':num_iter}, emission=False) # Write data as stack of TIFs. tomopy.io.writer.write_tiff_stack(rec, fname=output_name) print "Slice saved as [%s_00000.tiff]" % output_name
def preprocess_data(prj, flat, dark, FF_norm=flat_field_norm, remove_rings=remove_rings, FF_drift_corr=flat_field_drift_corr, downsapling=binning): if FF_norm: # dark-flat field correction prj = tomopy.normalize(prj, flat, dark) if FF_drift_corr: # flat field drift correction prj = tomopy.normalize_bg(prj, air=50) prj[prj <= 0] = 1 # check dark<data prj = tomopy.minus_log(prj) # -logarithm if remove_rings: # remove rings prj = tomopy.remove_stripe_fw(prj, level=7, wname='sym16', sigma=1, pad=True) #prj = tomopy.remove_stripe_ti(prj,2) # prj = tomopy.remove_all_stripe(prj) if downsapling > 0: # binning prj = tomopy.downsample(prj, level=binning) prj = tomopy.downsample(prj, level=binning, axis=1) return prj
def remove_stripe(data, params): log.info(' *** remove stripe:') if (params.remove_stripe_method == 'fw'): log.info(' *** *** fourier wavelet') data = tomopy.remove_stripe_fw(data, level=params.fw_level, wname=params.fw_filter, sigma=params.fw_sigma, pad=params.fw_pad) log.info(' *** *** *** fw level %d ' % params.fw_level) log.info(' *** *** *** fw wname %s ' % params.fw_filter) log.info(' *** *** *** fw sigma %f ' % params.fw_sigma) log.info(' *** *** *** fw pad %r ' % params.fw_pad) elif (params.remove_stripe_method == 'ti'): log.info(' *** *** titarenko') data = tomopy.remove_stripe_ti(data, nblock=params.ti_nblock, alpha=params.ti_alpha) log.info(' *** *** *** ti nblock %d ' % params.ti_nblock) log.info(' *** *** *** ti alpha %f ' % params.ti_alpha) elif (params.remove_stripe_method == 'sf'): log.info(' *** *** smoothing filter') data = tomopy.remove_stripe_sf(data, size == params.sf_size) log.info(' *** *** *** sf size %d ' % params.sf_size) elif (params.remove_stripe_method == 'none'): log.warning(' *** *** OFF') return data
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 30 # Propagation distance of the wavefront in cm detector_pixel_size_x = 1.17e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) monochromator_energy = 25.74 # Energy of incident wave in keV alpha = 1e-02 # Phase retrieval coeff. zinger_level = 1000 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white miss_angles = [141,226] # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) print (theta) # Manage the missing angles: #proj_size = np.shape(proj) #theta = np.linspace(0,180,proj_size[0]) proj = np.concatenate((proj[0:miss_angles[0],:,:], proj[miss_angles[1]+1:-1,:,:]), axis=0) theta = np.concatenate((theta[0:miss_angles[0]], theta[miss_angles[1]+1:-1])) # zinger_removal #proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) #flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=0.8) # remove stripes data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) # phase retrieval # data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center/np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # Reconstruct object. if algorithm == 'sirtfbp': rec = rec_sirtfbp(data, theta, rot_center) else: rec = tomopy.recon(data, theta, center=rot_center, algorithm=algorithm, filter_name='parzen') print("Algorithm: ", algorithm) # Mask each reconstructed slice with a circle. ##rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
def find_rotation_axis(h5fname, nsino): data_size = get_dx_dims(h5fname, 'data') ssino = int(data_size[1] * nsino) # Select sinogram range to reconstruct sino = None start = ssino end = start + 1 sino = (start, end) # Read APS 32-BM raw data proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Flat-field correction of raw data data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data,level=5,wname='sym16',sigma=1,pad=True) # find rotation center rot_center = tomopy.find_center_vo(data) return rot_center
def preprocess_data(prj, flat, dark, FF_norm=flat_field_norm, remove_rings = remove_rings, medfilt_size=medfilt_size, FF_drift_corr=flat_field_drift_corr, downspling=binning): if FF_norm: # normalize the prj print('\n*** Applying flat field correction:') start_norm_time = time.time() prj = tomopy.normalize(prj, flat, dark) print(' done in %0.3f min' % ((time.time() - start_norm_time)/60)) if FF_drift_corr: print('\n*** Applying flat field drift correction:') start_norm_bg_time = time.time() prj = tomopy.normalize_bg(prj, air=100) print(' done in %0.3f min' % ((time.time() - start_norm_bg_time)/60)) # Applying -log print('\n*** Applying -log:') start_log_time = time.time() prj = tomopy.minus_log(prj) print(' done in %0.3f min' % ((time.time() - start_log_time)/60)) prj = tomopy.misc.corr.remove_neg(prj, val=0.000) prj = tomopy.misc.corr.remove_nan(prj, val=0.000) prj[np.where(prj == np.inf)] = 0.000 # prj[np.where(prj == 0)] = 0.000,2 print('\n*** Min and max val in prj before recon: %0.3f, %0.3f' % (np.min(prj), np.max(prj))) if remove_rings: # remove ring artefacts tmp = prj[-1,:,:] # use to fixe the bug of remove_stripe_ti print('\n*** Applying ring removal algo:') start_ring_time = time.time() # prj = tomopy.remove_stripe_ti(prj, nblock=0, alpha=2) prj = tomopy.remove_stripe_fw(prj) # prj = tomopy.remove_stripe_sf(prj,10); prj = tomopy.misc.corr.remove_neg(prj, val=0.000) # remove the neg values coming from remove_stripe_sf print(' done in %0.3f min' % ((time.time() - start_ring_time)/60)) prj[-1,:,:] = tmp # fixe the bug of remove_stripe_ti # Filtering data with 2D median filter before downsampling and recon if medfilt_size>1: start_filter_time = time.time() print('\n*** Applying median filter') #prj = tomopy.median_filter(prj,size=1) prj = ndimage.median_filter(prj,footprint=np.ones((1, medfilt_size, medfilt_size))) print(' done in %0.3f min' % ((time.time() - start_filter_time)/60)) # Downsampling data: if downspling>0: print('\n** Applying downsampling') start_down_time = time.time() prj = tomopy.downsample(prj, level=binning) prj = tomopy.downsample(prj, level=binning, axis=1) print(' done in %0.3f min' % ((time.time() - start_down_time)/60)) print('\n*** Shape of the data:'+str(np.shape(prj))) print(' Dimension of theta:'+str(np.shape(theta))) return prj
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 8 # Propagation distance of the wavefront in cm detector_pixel_size_x = 2.247e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) monochromator_energy = 24.9 # Energy of incident wave in keV alpha = 1e-02 # Phase retrieval coeff. zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # zinger_removal # proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) # flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. ##data = tomopy.normalize(proj, flat, dark, cutoff=0.8) data = tomopy.normalize(proj, flat, dark) # remove stripes data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) # data = tomopy.remove_stripe_ti(data, alpha=1.5) # data = tomopy.remove_stripe_sf(data, size=150) # phase retrieval #data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center/np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # Reconstruct object. if algorithm == 'sirtfbp': rec = rec_sirtfbp(data, theta, rot_center) elif algorithm == 'astrasirt': extra_options ={'MinConstraint':0} options = {'proj_type':'cuda', 'method':'SIRT_CUDA', 'num_iter':200, 'extra_options':extra_options} rec = tomopy.recon(data, theta, center=rot_center, algorithm=tomopy.astra, options=options) else: rec = tomopy.recon(data, theta, center=rot_center, algorithm=algorithm, filter_name='parzen') print("Algorithm: ", algorithm) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
def reconstruct(h5fname, sino, rot_center, args, blocked_views=None): # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Manage the missing angles: if blocked_views is not None: print("Blocked Views: ", blocked_views) proj = np.concatenate((proj[0:blocked_views[0], :, :], proj[blocked_views[1] + 1:-1, :, :]), axis=0) theta = np.concatenate( (theta[0:blocked_views[0]], theta[blocked_views[1] + 1:-1])) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=1, pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 algorithm = args.algorithm ncores = args.ncores nitr = args.num_iter # always add algorithm _kwargs = {"algorithm": algorithm} # assign number of cores _kwargs["ncore"] = ncores # don't assign "num_iter" if gridrec or fbp if algorithm not in ["fbp", "gridrec"]: _kwargs["num_iter"] = nitr # Reconstruct object. with timemory.util.auto_timer( "[tomopy.recon(algorithm='{}')]".format(algorithm)): rec = tomopy.recon(proj, theta, **_kwargs) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 8 # Propagation distance of the wavefront in cm detector_pixel_size_x = 2.247e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) monochromator_energy = 24.9 # Energy of incident wave in keV alpha = 1e-02 # Phase retrieval coeff. zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white # h5fname_norm = '/local/data/2019-02/Burke/C47M_0015.h5' h5fname_norm = '/local/data/2019-02/Burke/kc78_Menardii_0003.h5' proj1, flat, dark, theta1 = dxchange.read_aps_32id(h5fname_norm, sino=sino) proj, dummy, dummy1, theta = dxchange.read_aps_32id(h5fname, sino=sino) # zinger_removal proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. ##data = tomopy.normalize(proj, flat, dark, cutoff=0.8) data = tomopy.normalize(proj, flat, dark) # remove stripes data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) #data = tomopy.remove_stripe_ti(data, alpha=1.5) data = tomopy.remove_stripe_sf(data, size=20) # phase retrieval #data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center/np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # Reconstruct object. if algorithm == 'sirtfbp': rec = rec_sirtfbp(data, theta, rot_center) else: rec = tomopy.recon(data, theta, center=rot_center, algorithm=algorithm, filter_name='parzen') print("Algorithm: ", algorithm) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
def reconstruct(sname, rot_center, ovlpfind, s_start, s_end): fname = dfolder + sname + '.h5' print(fname) start = s_start end = s_end chunks = 24 num_sino = (end - start) // chunks for m in range(chunks): sino_start = start + num_sino * m sino_end = start + num_sino * (m + 1) start_read_time = time.time() proj, flat, dark, thetat = dxchange.read_aps_2bm(fname, sino=(sino_start, sino_end)) print(' done read in %0.1f min' % ((time.time() - start_read_time) / 60)) dark = proj[9001:9002] flat = proj[0:1] proj = proj[1:9000] theta = tomopy.angles(proj.shape[0], 0., 360.) proj = tomopy.sino_360_to_180(proj, overlap=ovlpfind, rotation='right') proj = tomopy.remove_outlier(proj, dif=0.4) proj = tomopy.normalize_bg(proj, air=10) proj = tomopy.minus_log(proj) center = rot_center start_ring_time = time.time() proj = tomopy.remove_stripe_fw(proj, wname='sym5', sigma=4, pad=False) proj = tomopy.remove_stripe_sf(proj, size=3) print(' done pre-process in %0.1f min' % ((time.time() - start_ring_time) / 60)) start_phase_time = time.time() proj = tomopy.retrieve_phase(proj, pixel_size=detector_pixel_size_x, dist=sample_detector_distance, energy=energy, alpha=alpha, pad=True, ncore=None, nchunk=None) print(' done phase retrieval in %0.1f min' % ((time.time() - start_phase_time) / 60)) start_recon_time = time.time() rec = tomopy.recon(proj, theta, center=center, algorithm='gridrec', filter_name='ramalk') tomopy.circ_mask(rec, axis=0, ratio=0.95) print("Reconstructed", rec.shape) dxchange.write_tiff_stack(rec, fname=dfolder + '/' + sname + '/' + sname, overwrite=True, start=sino_start) print(' Chunk reconstruction done in %0.1f min' % ((time.time() - start_recon_time) / 60)) print("Done!")
def rec_try(h5fname, nsino, rot_center, center_search_width, algorithm, binning): data_shape = get_dx_dims(h5fname, 'data') print(data_shape) ssino = int(data_shape[1] * nsino) center_range = (rot_center-center_search_width, rot_center+center_search_width, 0.5) #print(sino,ssino, center_range) #print(center_range[0], center_range[1], center_range[2]) # Select sinogram range to reconstruct sino = None start = ssino end = start + 1 sino = (start, end) # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) stack = np.empty((len(np.arange(*center_range)), data_shape[0], data_shape[2])) index = 0 for axis in np.arange(*center_range): stack[index] = data[:, 0, :] index = index + 1 # Reconstruct the same slice with a range of centers. rec = tomopy.recon(stack, theta, center=np.arange(*center_range), sinogram_order=True, algorithm='gridrec', filter_name='parzen', nchunk=1) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) index = 0 # Save images to a temporary folder. fname = os.path.dirname(h5fname) + '/' + 'try_rec/' + 'recon_' + os.path.splitext(os.path.basename(h5fname))[0] for axis in np.arange(*center_range): rfname = fname + '_' + str('{0:.2f}'.format(axis) + '.tiff') dxchange.write_tiff(rec[index], fname=rfname, overwrite=True) index = index + 1 print("Reconstructions: ", fname)
def reconstruct(h5fname, sino, rot_center, args, blocked_views=None): # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Manage the missing angles: if blocked_views is not None: print("Blocked Views: ", blocked_views) proj = np.concatenate((proj[0:blocked_views[0], :, :], proj[blocked_views[1]+1:-1, :, :]), axis=0) theta = np.concatenate((theta[0:blocked_views[0]], theta[blocked_views[1]+1: -1])) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=1, pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 algorithm = args.algorithm ncores = args.ncores nitr = args.num_iter # always add algorithm _kwargs = {"algorithm": algorithm} # assign number of cores _kwargs["ncore"] = ncores # don't assign "num_iter" if gridrec or fbp if algorithm not in ["fbp", "gridrec"]: _kwargs["num_iter"] = nitr # Reconstruct object. with timemory.util.auto_timer( "[tomopy.recon(algorithm='{}')]".format(algorithm)): rec = tomopy.recon(proj, theta, **_kwargs) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
def main(): oversamp_factor = 1.25 #For NUFFT parser = argparse.ArgumentParser() inputs = bl832inputs_parser(parser) num_slice = inputs['z_numElts'] num_angles= inputs['num_views']/inputs['view_subsmpl_fact'] pad_size = np.int16(inputs['x_width']*oversamp_factor) num_iter = inputs['num_iter'] nufft_scaling = (np.pi/pad_size)**2 tomo, flats, darks, floc = tomopy.read_als_832h5(inputs['input_hdf5'],ind_tomo=range(1,inputs['num_views']+1,inputs['view_subsmpl_fact']),sino=(inputs['z_start'], inputs['z_start']+inputs['z_numElts'], 1)) print('Data read complete') print('Generating angles') theta = tomopy.angles(num_angles) #Need to modify to return the raw counts for noise estimation print('Normalization') tomo,weight = normalize_bo(tomo, flats, darks,inputs['num_dark']) print('Ring removal') tomo = tomopy.remove_stripe_fw(tomo) ################## GPU MBIR ###################### input_params={} input_params['gpu_device']=inputs['gpu_device'] input_params['oversamp_factor']=oversamp_factor input_params['num_iter']=num_iter input_params['p']=inputs['p'] input_params['smoothness']=inputs['smoothness'] t=time.time() rec_mbir_final = gpuMBIR(tomo,theta,inputs['rot_center'],input_params) elapsed_time = (time.time()-t) print('Time for reconstucting using GPU-MBIR of %d slices with %d iter : %f' % (num_slice,num_iter,elapsed_time)) pg.image(rec_mbir_final);pg.QtGui.QApplication.exec_() # np.save('/home/svvenkatakrishnan/results/mbir_notch1080_70slice',rec_mbir_final) # fig = plt.figure() # sirt_camTomo = rec_sirt_final[124] # plt.imshow(sirt_camTomo,cmap=plt.cm.Greys_r,vmin=0,vmax=0.00075) # plt.colorbar() # fig.suptitle('Tomopy GPU-SIRT Reconstruction') # plt.draw() # plt.show() print 'main: Done!'
def test_fw(self): # Prepare some test data prj = self.phantom_prj() # Prepare parameters (different from tomopy_cli or tomopy defaults) params = make_params() params.remove_stripe_method = 'fw' params.fw_level = 5 params.fw_filter = "haar" params.fw_sigma = 1.3 result = remove_stripe(np.copy(prj), params) # Compare results expected = tomopy.remove_stripe_fw(np.copy(prj), level=5, wname="haar", sigma=1.3) np.testing.assert_array_equal(result, expected)
def rec_full(file_name, sino_start, sino_end, astra_method, extra_options, num_iter=1): print '\n#### Processing '+ file_name chunks = 10 # number of data chunks for the reconstruction nSino_per_chunk = (sino_end - sino_start)/chunks print "Reconstructing [%d] slices from slice [%d] to [%d] in [%d] chunks of [%d] slices each" % ((sino_end - sino_start), sino_start, sino_end, chunks, nSino_per_chunk) strt = 0 for iChunk in range(0,chunks): print '\n -- chunk # %i' % (iChunk+1) sino_chunk_start = sino_start + nSino_per_chunk*iChunk sino_chunk_end = sino_start + nSino_per_chunk*(iChunk+1) print '\n --------> [%i, %i]' % (sino_chunk_start, sino_chunk_end) if sino_chunk_end > sino_end: break # Read HDF5 file. prj, flat, dark = tomopy.io.exchange.read_aps_32id(file_name, sino=(sino_chunk_start, sino_chunk_end)) # Manage the missing angles: theta = tomopy.angles(prj.shape[0]) prj = np.concatenate((prj[0:miss_angles[0],:,:], prj[miss_angles[1]+1:-1,:,:]), axis=0) theta = np.concatenate((theta[0:miss_angles[0]], theta[miss_angles[1]+1:-1])) # normalize the prj prj = tomopy.normalize(prj, flat, dark) # remove ring artefacts prj = tomopy.remove_stripe_fw(prj) # reconstruct rec = tomopy.recon(prj[:,::reduce_amount,::reduce_amount], theta, center=float(best_center)/reduce_amount, algorithm=tomopy.astra, options={'proj_type':proj_type,'method':astra_method,'extra_options':extra_options,'num_iter':num_iter}, emission=False) print output_name # Write data as stack of TIFs. tomopy.io.writer.write_tiff_stack(rec, fname=output_name, start=strt) strt += prj[:,::reduce_amount,:].shape[1]
def reconstruct(sname, rot_center, ovlpfind, s_start, s_end): fname = dfolder + sname + '.h5' print (fname) start = s_start end = s_end chunks = 24 num_sino = (end - start) // chunks for m in range(chunks): sino_start = start + num_sino * m sino_end = start + num_sino * (m + 1) start_read_time = time.time() proj, flat, dark, thetat = dxchange.read_aps_2bm(fname, sino=(sino_start, sino_end)) print(' done read in %0.1f min' % ((time.time() - start_read_time)/60)) dark = proj[9001:9002] flat = proj[0:1] proj = proj[1:9000] theta = tomopy.angles(proj.shape[0], 0., 360.) proj = tomopy.sino_360_to_180(proj, overlap=ovlpfind, rotation='right') proj = tomopy.remove_outlier(proj, dif=0.4) proj = tomopy.normalize_bg(proj, air=10) proj = tomopy.minus_log(proj) center = rot_center start_ring_time = time.time() proj = tomopy.remove_stripe_fw(proj, wname='sym5', sigma=4, pad=False) proj = tomopy.remove_stripe_sf(proj, size=3) print(' done pre-process in %0.1f min' % ((time.time() - start_ring_time)/60)) start_phase_time = time.time() proj = tomopy.retrieve_phase(proj, pixel_size=detector_pixel_size_x, dist=sample_detector_distance, energy=energy, alpha=alpha, pad=True, ncore=None, nchunk=None) print(' done phase retrieval in %0.1f min' % ((time.time() - start_phase_time)/60)) start_recon_time = time.time() rec = tomopy.recon(proj, theta, center=center, algorithm='gridrec', filter_name='ramalk') tomopy.circ_mask(rec, axis=0, ratio=0.95) print ("Reconstructed", rec.shape) dxchange.write_tiff_stack(rec, fname = dfolder + '/' + sname + '/' + sname, overwrite=True, start=sino_start) print(' Chunk reconstruction done in %0.1f min' % ((time.time() - start_recon_time)/60)) print ("Done!")
def reconstruct(h5fname, sino, rot_center, blocked_views=None): # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Manage the missing angles: if blocked_views is not None: print("Blocked Views: ", blocked_views) proj = np.concatenate((proj[0:blocked_views[0],:,:], proj[blocked_views[1]+1:-1,:,:]), axis=0) theta = np.concatenate((theta[0:blocked_views[0]], theta[blocked_views[1]+1:-1])) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) # # phase retrieval # data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=8e-3,pad=True) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 # Reconstruct object. rec = tomopy.recon(data, theta, center=rot_center, algorithm='gridrec') # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 25 # Propagation distance of the wavefront in cm detector_pixel_size_x = 2.143e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) #monochromator_energy = 24.9 # Energy of incident wave in keV # used pink beam alpha = 1e-02 # Phase retrieval coeff. zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white # Read APS 2-BM raw data. # DIMAX saves 3 files: proj, flat, dark # when loading the data set select the proj file (larger size) fname = os.path.splitext(h5fname)[0] fbase = fname.rsplit('_', 1)[0] fnum = fname.rsplit('_', 1)[1] fext = os.path.splitext(h5fname)[1] fnum_flat = str("%4.4d" % (int(fnum) + 1)) fnum_dark = str("%4.4d" % (int(fnum) + 2)) fnproj = fbase + '_' + fnum + fext fnflat = fbase + '_' + fnum_flat + fext fndark = fbase + '_' + fnum_dark + fext fnflat = '/local/data/2018-11/Chawla/1G_A/1G_A_0002.hdf' fndark = '/local/data/2018-11/Chawla/1G_A/1G_A_0003.hdf' print('proj', fnproj) print('flat', fnflat) print('dark', fndark) # Read APS 2-BM DIMAX raw data. proj, dum, dum2, theta = dxchange.read_aps_32id(fnproj, sino=sino) dum3, flat, dum4, dum5 = dxchange.read_aps_32id(fnflat, sino=sino) dum6, dum7, dark, dum8 = dxchange.read_aps_32id(fndark, sino=sino) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=1, pad=True) # zinger_removal proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. ##data = tomopy.normalize(proj, flat, dark, cutoff=0.8) data = tomopy.normalize(proj, flat, dark) # remove stripes #data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) #data = tomopy.remove_stripe_ti(data, alpha=1.5) data = tomopy.remove_stripe_sf(data, size=150) # phase retrieval #data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center / np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # Reconstruct object. if algorithm == 'sirtfbp': rec = rec_sirtfbp(data, theta, rot_center) else: rec = tomopy.recon(data, theta, center=rot_center, algorithm=algorithm, filter_name='parzen') print("Algorithm: ", algorithm) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) #rec = np.swapaxes(rec,0,2) return rec
def fast_tomo_recon(argv): """ Reconstruct subset slices (sinograms) equally spaced within tomographic dataset """ logger = logging.getLogger('fast_tomopy.fast_tomo_recon') # Parse arguments passed to function parser = argparse.ArgumentParser() parser.add_argument('-i', '--input', type=str, help='path to input raw ' 'dataset', required=True) parser.add_argument('-o', '--output-file', type=str, help='full path to h5 output ' 'file', default=os.path.join(os.getcwd(), "fast-tomopy.h5")) parser.add_argument('-sn', '--sino-num', type=int, help='Number of slices ' 'to reconstruct', default=5) parser.add_argument('-a', '--algorithm', type=str, help='Reconstruction' ' algorithm', default='gridrec', choices=['art', 'bart', 'fbp', 'gridrec', 'mlem', 'ospml_hybrid', 'ospml_quad', 'pml_hybrid', 'pml_quad', 'sirt']) parser.add_argument('-c', '--center', type=float, help='Center of rotation', default=None) parser.add_argument('-fn', '--filter-name', type=str, help='Name of filter' ' used for reconstruction', choices=['none', 'shepp', 'cosine', 'hann', 'hamming', 'ramlak', 'parzen', 'butterworth'], default='butterworth') parser.add_argument('-rr', '--ring-remove', type=str, help='Ring removal ' 'method', choices=['Octopus', 'Tomopy-FW', 'Tomopy-T'], default='Tomopy-FW') parser.add_argument('-lf', '--log-file', type=str, help='log file name', default='fast-tomopy.log') args = parser.parse_args() fh = logging.FileHandler(args.log_file) fh.setLevel(logging.INFO) fh.setFormatter(formatter) logger.addHandler(fh) if os.path.isdir(os.path.dirname(args.output_file)) is False: raise IOError(2, 'Directory of output file does not exist', args.output_file) # Read file metadata logger.info('Reading input file metadata') fdata, gdata = tomopy.read_als_832h5_metadata(args.input) proj_total = int(gdata['nangles']) last = proj_total - 1 sino_total = int(gdata['nslices']) ray_total = int(gdata['nrays']) px_size = float(gdata['pxsize'])/10 # cm # Set parameters for sinograms to read step = sino_total // (args.sino_num + 2) start = step end = step*(args.sino_num + 1) sino = (start, end, step) # Read full first and last projection to determine center of rotation if args.center is None: logger.info('Reading full first and last projection for COR') first_last, flats, darks, floc = tomopy.read_als_832h5(args.input, ind_tomo=(0, last)) first_last = tomopy.normalize_nf(first_last, flats, darks, floc) args.center = tomopy.find_center_pc(first_last[0, :, :], first_last[1, :, :], tol=0.1) logger.info('Detected center: %f', args.center) # Read and normalize raw sinograms logger.info('Reading raw data') tomo, flats, darks, floc = tomopy.read_als_832h5(args.input, sino=sino) logger.info('Normalizing raw data') tomo = tomopy.normalize_nf(tomo, flats, darks, floc) # Remove stripes from sinograms (remove rings) logger.info('Preprocessing normalized data') if args.ring_remove == 'Tomopy-FW': logger.info('Removing stripes from sinograms with %s', args.ring_remove) tomo = tomopy.remove_stripe_fw(tomo) elif args.ring_remove == 'Tomopy-T': logger.info('Removing stripes from sinograms with %s', args.ring_remove) tomo = tomopy.remove_stripe_ti(tomo) # Pad sinograms with edge values npad = int(np.ceil(ray_total*np.sqrt(2)) - ray_total)//2 tomo = tomopy.pad(tomo, 2, npad=npad, mode='edge') args.center += npad # account for padding filter_name = np.array(args.filter_name, dtype=(str, 16)) theta = tomopy.angles(tomo.shape[0], 270, 90) logger.info('Reconstructing normalized data') # Reconstruct sinograms rec = tomopy.recon(tomo, theta, center=args.center, emission=False, algorithm=args.algorithm, filter_name=filter_name) rec = tomopy.circ_mask(rec[:, npad:-npad, npad:-npad], 0) rec = rec/px_size # Remove rings from reconstruction if args.ring_remove == 'Octopus': logger.info('Removing rings from reconstructions with %s', args.ring_remove) thresh = float(gdata['ring_threshold']) thresh_max = float(gdata['upp_ring_value']) thresh_min = float(gdata['low_ring_value']) theta_min = int(gdata['max_arc_length']) rwidth = int(gdata['max_ring_size']) rec = tomopy.remove_rings(rec, center_x=args.center, thresh=thresh, thresh_max=thresh_max, thresh_min=thresh_min, theta_min=theta_min, rwidth=rwidth) # Write reconstruction data to new hdf5 file fdata['stage'] = 'fast-tomopy' fdata['stage_flow'] = '/raw/' + fdata['stage'] fdata['stage_version'] = 'fast-tomopy-0.1' # WHAT ABOUT uuid ????? Who asigns this??? del fdata['uuid'] # I'll get rid of it altogether then... gdata['Reconstruction_Type'] = 'tomopy-gridrec' gdata['ring_removal_method'] = args.ring_remove gdata['rfilter'] = args.filter_name logger.info('Writing reconstructed data to h5 file') write_als_832h5(rec, args.input, fdata, gdata, args.output_file, step) return
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 25 # Propagation distance of the wavefront in cm detector_pixel_size_x = 2.143e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) #monochromator_energy = 24.9 # Energy of incident wave in keV # used pink beam alpha = 1e-02 # Phase retrieval coeff. zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white # Read APS 2-BM raw data. # DIMAX saves 3 files: proj, flat, dark # when loading the data set select the proj file (larger size) fname = os.path.splitext(h5fname)[0] fbase = fname.rsplit('_', 1)[0] fnum = fname.rsplit('_', 1)[1] fext = os.path.splitext(h5fname)[1] fnum_flat = str("%4.4d" % (int(fnum)+1)) fnum_dark = str("%4.4d" % (int(fnum)+2)) fnproj = fbase + '_' + fnum + fext fnflat = fbase + '_' + fnum_flat + fext fndark = fbase + '_' + fnum_dark + fext fnflat = '/local/data/2018-11/Chawla/1G_A/1G_A_0002.hdf' fndark = '/local/data/2018-11/Chawla/1G_A/1G_A_0003.hdf' print('proj', fnproj) print('flat', fnflat) print('dark', fndark) # Read APS 2-BM DIMAX raw data. proj, dum, dum2, theta = dxchange.read_aps_32id(fnproj, sino=sino) dum3, flat, dum4, dum5 = dxchange.read_aps_32id(fnflat, sino=sino) dum6, dum7, dark, dum8 = dxchange.read_aps_32id(fndark, sino=sino) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) # zinger_removal proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. ##data = tomopy.normalize(proj, flat, dark, cutoff=0.8) data = tomopy.normalize(proj, flat, dark) # remove stripes #data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) #data = tomopy.remove_stripe_ti(data, alpha=1.5) data = tomopy.remove_stripe_sf(data, size=150) # phase retrieval #data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center/np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # Reconstruct object. if algorithm == 'sirtfbp': rec = rec_sirtfbp(data, theta, rot_center) else: rec = tomopy.recon(data, theta, center=rot_center, algorithm=algorithm, filter_name='parzen') print("Algorithm: ", algorithm) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) #rec = np.swapaxes(rec,0,2) return rec
start = 500 end = 501 sino = (start, end) # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(fname, sino=sino) # zinger_removal #proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) #flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data,level=5,wname='sym16',sigma=1,pad=True) #data = tomopy.prep.stripe.remove_stripe_ti(data,alpha=7) #data = tomopy.prep.stripe.remove_stripe_sf(data,size=51) # phase retrieval data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) # Find rotation center # rot_center = 955 # rot_center = 953.25 # rot_center = tomopy.find_center(data, theta, init=rot_center, ind=0, tol=0.5) rot_center = tomopy.find_center_vo(data) print(h5name, rot_center) data = tomopy.minus_log(data)
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 8 # Propagation distance of the wavefront in cm detector_pixel_size_x = 2.247e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) monochromator_energy = 24.9 # Energy of incident wave in keV alpha = 1e-02 # Phase retrieval coeff. zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # zinger_removal # proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) # flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. ##data = tomopy.normalize(proj, flat, dark, cutoff=0.8) data = tomopy.normalize(proj, flat, dark) # remove stripes data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=2,pad=True) #data = tomopy.remove_stripe_ti(data, alpha=1.5) data = tomopy.remove_stripe_sf(data, size=150) # phase retrieval #data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center/np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # padding N = data.shape[2] data_pad = np.zeros([data.shape[0],data.shape[1],3*N//2],dtype = "float32") data_pad[:,:,N//4:5*N//4] = data data_pad[:,:,0:N//4] = np.tile(np.reshape(data[:,:,0],[data.shape[0],data.shape[1],1]),(1,1,N//4)) data_pad[:,:,5*N//4:] = np.tile(np.reshape(data[:,:,-1],[data.shape[0],data.shape[1],1]),(1,1,N//4)) data = data_pad rot_center = rot_center+N//4 # Reconstruct object. if algorithm == 'sirtfbp': rec = rec_sirtfbp(data, theta, rot_center) else: rec = tomopy.recon(data, theta, center=rot_center, algorithm=algorithm, filter_name='parzen') rec = rec[:,N//4:5*N//4,N//4:5*N//4] print("Algorithm: ", algorithm) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
sino = (int(sino_chunk_start), int(sino_chunk_end)) # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(fname, sino=sino) # zinger_removal #proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) #flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=5, wname='sym16', sigma=1, pad=True) #data = tomopy.prep.stripe.remove_stripe_ti(data,alpha=7) #data = tomopy.prep.stripe.remove_stripe_sf(data,size=51) # phase retrieval data = tomopy.prep.phase.retrieve_phase( data, pixel_size=detector_pixel_size_x, dist=sample_detector_distance, energy=monochromator_energy, alpha=alpha, pad=True) # Find rotation center
def reconstruct(h5fname, sino, nframes, frame, nproj, binning, tv): # Read APS 32-BM raw data. print("Read data") proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) print("Processing") proj = proj[(frame - nframes / 2) * nproj:(frame + nframes / 2) * nproj, :, :] # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=1, pad=True) print("Raw data: ", h5fname) print("Frames for reconstruction:", (frame - nframes / 2), "..", (frame + nframes / 2)) # Phase retrieval for tomobank id 00080 # sample_detector_distance = 25 # detector_pixel_size_x = 3.0e-4 # monochromator_energy = 16 # phase retrieval # data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=8e-03,pad=True) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 # Binning data = tomopy.downsample(data, level=binning, axis=2) if data.shape[1] > 1: data = tomopy.downsample(data, level=binning, axis=1) rot_center = data.shape[2] / 2 theta = np.linspace(0, np.pi * nframes, nproj * nframes, endpoint=False) if tv: import rectv # Reconstruct. Iterative TV. [Ntheta, Nz, N] = data.shape Nzp = 4 # number of slices to process simultaniously by gpus M = nframes # number of basis functions, must be a multiple of nframes lambda0 = pow(2, -9) # regularization parameter 1 lambda1 = pow(2, 2) # regularization parameter 2 niters = 1024 # number of iterations ngpus = 1 # number of gpus # reorder input data for compatibility data = np.ndarray.flatten(data.swapaxes(0, 1)) rec = np.zeros([N * N * Nz * M], dtype='float32') # memory for result # Make a class for tv cl = rectv.rectv(N, Ntheta, M, nframes, Nz, Nzp, ngpus, lambda0, lambda1) # Run iterations cl.itertvR_wrap(rec, data, niters) rec = np.rot90( np.reshape(rec, [Nz, M, N, N]).swapaxes(0, 1), axes=(2, 3) ) / Ntheta * nframes * 2 # reorder result for compatibility rec = rec[::M / nframes] else: # Reconstruct object. FBP. rec = np.zeros((nframes, data.shape[1], data.shape[2], data.shape[2]), dtype='float32') for time_frame in range(0, nframes): rec0 = tomopy.recon( data[time_frame * nproj:(time_frame + 1) * nproj], theta[time_frame * nproj:(time_frame + 1) * nproj], center=rot_center - np.mod(time_frame, 2), algorithm='gridrec') # Mask each reconstructed slice with a circle. rec[time_frame] = tomopy.circ_mask(rec0, axis=0, ratio=0.95) return rec
start = 290 end = 294 # Read the APS 5-BM data proj, flat, dark = dxchange.read_aps_5bm(fname, sino=(start, end)) # Set data collection angles as equally spaced between 0-180 degrees. theta = tomopy.angles(proj.shape[0]) # Flat-field correction of raw data. proj = tomopy.normalize(proj, flat, dark) # remove stripes proj = tomopy.remove_stripe_fw(proj, level=7, wname='sym16', sigma=1, pad=True) # Set rotation center. rot_center = proj.shape[2] / 2 print("Center of rotation: ", rot_center) proj = tomopy.minus_log(proj) # Reconstruct object using Gridrec algorithm. rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95)
def recon( filename, inputPath = './', outputPath = None, outputFilename = None, doOutliers1D = False, # outlier removal in 1d (along sinogram columns) outlier_diff1D = 750, # difference between good data and outlier data (outlier removal) outlier_size1D = 3, # radius around each pixel to look for outliers (outlier removal) doOutliers2D = False, # outlier removal, standard 2d on each projection outlier_diff2D = 750, # difference between good data and outlier data (outlier removal) outlier_size2D = 3, # radius around each pixel to look for outliers (outlier removal) doFWringremoval = True, # Fourier-wavelet ring removal doTIringremoval = False, # Titarenko ring removal doSFringremoval = False, # Smoothing filter ring removal ringSigma = 3, # damping parameter in Fourier space (Fourier-wavelet ring removal) ringLevel = 8, # number of wavelet transform levels (Fourier-wavelet ring removal) ringWavelet = 'db5', # type of wavelet filter (Fourier-wavelet ring removal) ringNBlock = 0, # used in Titarenko ring removal (doTIringremoval) ringAlpha = 1.5, # used in Titarenko ring removal (doTIringremoval) ringSize = 5, # used in smoothing filter ring removal (doSFringremoval) doPhaseRetrieval = False, # phase retrieval alphaReg = 0.0002, # smaller = smoother (used for phase retrieval) propagation_dist = 75, # sample-to-scintillator distance (phase retrieval) kev = 24, # energy level (phase retrieval) butterworth_cutoff = 0.25, #0.1 would be very smooth, 0.4 would be very grainy (reconstruction) butterworth_order = 2, # for reconstruction doTranslationCorrection = False, # correct for linear drift during scan xshift = 0, # undesired dx transation correction (from 0 degree to 180 degree proj) yshift = 0, # undesired dy transation correction (from 0 degree to 180 degree proj) doPolarRing = False, # ring removal Rarc=30, # min angle needed to be considered ring artifact (ring removal) Rmaxwidth=100, # max width of rings to be filtered (ring removal) Rtmax=3000.0, # max portion of image to filter (ring removal) Rthr=3000.0, # max value of offset due to ring artifact (ring removal) Rtmin=-3000.0, # min value of image to filter (ring removal) cor=None, # center of rotation (float). If not used then cor will be detected automatically corFunction = 'pc', # center of rotation function to use - can be 'pc', 'vo', or 'nm' voInd = None, # index of slice to use for cor search (vo) voSMin = -40, # min radius for searching in sinogram (vo) voSMax = 40, # max radius for searching in sinogram (vo) voSRad = 10, # search radius (vo) voStep = 0.5, # search step (vo) voRatio = 2.0, # ratio of field-of-view and object size (vo) voDrop = 20, # drop lines around vertical center of mask (vo) nmInd = None, # index of slice to use for cor search (nm) nmInit = None, # initial guess for center (nm) nmTol = 0.5, # desired sub-pixel accuracy (nm) nmMask = True, # if True, limits analysis to circular region (nm) nmRatio = 1.0, # ratio of radius of circular mask to edge of reconstructed image (nm) nmSinoOrder = False, # if True, analyzes in sinogram space. If False, analyzes in radiograph space use360to180 = False, # use 360 to 180 conversion doBilateralFilter = False, # if True, uses bilateral filter on image just before write step # NOTE: image will be converted to 8bit if it is not already bilateral_srad = 3, # spatial radius for bilateral filter (image will be converted to 8bit if not already) bilateral_rrad = 30, # range radius for bilateral filter (image will be converted to 8bit if not already) castTo8bit = False, # convert data to 8bit before writing cast8bit_min=-10, # min value if converting to 8bit cast8bit_max=30, # max value if converting to 8bit useNormalize_nf = False, # normalize based on background intensity (nf) chunk_proj = 100, # chunk size in projection direction chunk_sino = 100, # chunk size in sinogram direction npad = None, # amount to pad data before reconstruction projused = None, #should be slicing in projection dimension (start,end,step) sinoused = None, #should be sliceing in sinogram dimension (start,end,step). If first value is negative, it takes the number of slices from the second value in the middle of the stack. correcttilt = 0, #tilt dataset tiltcenter_slice = None, # tilt center (x direction) tiltcenter_det = None, # tilt center (y direction) angle_offset = 0, #this is the angle offset from our default (270) so that tomopy yields output in the same orientation as previous software (Octopus) anglelist = None, #if not set, will assume evenly spaced angles which will be calculated by the angular range and number of angles found in the file. if set to -1, will read individual angles from each image. alternatively, a list of angles can be passed. doBeamHardening = False, #turn on beam hardening correction, based on "Correction for beam hardening in computed tomography", Gabor Herman, 1979 Phys. Med. Biol. 24 81 BeamHardeningCoefficients = None, #6 values, tomo = a0 + a1*tomo + a2*tomo^2 + a3*tomo^3 + a4*tomo^4 + a5*tomo^5 projIgnoreList = None, #projections to be ignored in the reconstruction (for simplicity in the code, they will not be removed and will be processed as all other projections but will be set to zero absorption right before reconstruction. *args, **kwargs): start_time = time.time() print("Start {} at:".format(filename)+time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())) outputPath = inputPath if outputPath is None else outputPath outputFilename = filename if outputFilename is None else outputFilename outputFilename = outputFilename.replace('.h5','') tempfilenames = [outputPath+'tmp0.h5',outputPath+'tmp1.h5'] filenametowrite = outputPath+'/rec'+filename.strip(".h5")+'/'+outputFilename #filenametowrite = outputPath+'/rec'+filename+'/'+outputFilename print("cleaning up previous temp files", end="") for tmpfile in tempfilenames: try: os.remove(tmpfile) except OSError: pass print(", reading metadata") datafile = h5py.File(inputPath+filename, 'r') gdata = dict(dxchange.reader._find_dataset_group(datafile).attrs) pxsize = float(gdata['pxsize'])/10 # /10 to convert units from mm to cm numslices = int(gdata['nslices']) numangles = int(gdata['nangles']) angularrange = float(gdata['arange']) numrays = int(gdata['nrays']) npad = int(np.ceil(numrays * np.sqrt(2)) - numrays)//2 if npad is None else npad projused = (0,numangles-1,1) if projused is None else projused # ndark = int(gdata['num_dark_fields']) # ind_dark = list(range(0, ndark)) # group_dark = [numangles - 1] inter_bright = int(gdata['i0cycle']) nflat = int(gdata['num_bright_field']) ind_flat = list(range(0, nflat)) if inter_bright > 0: group_flat = list(range(0, numangles, inter_bright)) if group_flat[-1] != numangles - 1: group_flat.append(numangles - 1) elif inter_bright == 0: group_flat = [0, numangles - 1] else: group_flat = None ind_tomo = list(range(0, numangles)) floc_independent = dxchange.reader._map_loc(ind_tomo, group_flat) #figure out the angle list (a list of angles, one per projection image) dtemp = datafile[list(datafile.keys())[0]] fltemp = list(dtemp.keys()) firstangle = float(dtemp[fltemp[0]].attrs.get('rot_angle',0)) if anglelist is None: #the offset angle should offset from the angle of the first image, which is usually 0, but in the case of timbir data may not be. #we add the 270 to be inte same orientation as previous software used at bl832 angle_offset = 270 + angle_offset - firstangle anglelist = tomopy.angles(numangles, angle_offset, angle_offset-angularrange) elif anglelist==-1: anglelist = np.zeros(shape=numangles) for icount in range(0,numangles): anglelist[icount] = np.pi/180*(270 + angle_offset - float(dtemp[fltemp[icount]].attrs['rot_angle'])) #if projused is different than default, need to chnage numangles and angularrange #can't do useNormalize_nf and doOutliers2D at the same time, or doOutliers2D and doOutliers1D at the same time, b/c of the way we chunk, for now just disable that if useNormalize_nf==True and doOutliers2D==True: useNormalize_nf = False print("we cannot currently do useNormalize_nf and doOutliers2D at the same time, turning off useNormalize_nf") if doOutliers2D==True and doOutliers1D==True: doOutliers1D = False print("we cannot currently do doOutliers1D and doOutliers2D at the same time, turning off doOutliers1D") #figure out how user can pass to do central x number of slices, or set of slices dispersed throughout (without knowing a priori the value of numslices) if sinoused is None: sinoused = (0,numslices,1) elif sinoused[0]<0: sinoused=(int(np.floor(numslices/2.0)-np.ceil(sinoused[1]/2.0)),int(np.floor(numslices/2.0)+np.floor(sinoused[1]/2.0)),1) num_proj_per_chunk = np.minimum(chunk_proj,projused[1]-projused[0]) numprojchunks = (projused[1]-projused[0]-1)//num_proj_per_chunk+1 num_sino_per_chunk = np.minimum(chunk_sino,sinoused[1]-sinoused[0]) numsinochunks = (sinoused[1]-sinoused[0]-1)//num_sino_per_chunk+1 numprojused = (projused[1]-projused[0])//projused[2] numsinoused = (sinoused[1]-sinoused[0])//sinoused[2] BeamHardeningCoefficients = (0, 1, 0, 0, 0, .1) if BeamHardeningCoefficients is None else BeamHardeningCoefficients if cor is None: print("Detecting center of rotation", end="") if angularrange>300: lastcor = int(np.floor(numangles/2)-1) else: lastcor = numangles-1 #I don't want to see the warnings about the reader using a deprecated variable in dxchange with warnings.catch_warnings(): warnings.simplefilter("ignore") tomo, flat, dark, floc = dxchange.read_als_832h5(inputPath+filename,ind_tomo=(0,lastcor)) tomo = tomo.astype(np.float32) if useNormalize_nf: tomopy.normalize_nf(tomo, flat, dark, floc, out=tomo) else: tomopy.normalize(tomo, flat, dark, out=tomo) if corFunction == 'vo': # same reason for catching warnings as above with warnings.catch_warnings(): warnings.simplefilter("ignore") cor = tomopy.find_center_vo(tomo, ind=voInd, smin=voSMin, smax=voSMax, srad=voSRad, step=voStep, ratio=voRatio, drop=voDrop) elif corFunction == 'nm': cor = tomopy.find_center(tomo, tomopy.angles(numangles, angle_offset, angle_offset-angularrange), ind=nmInd, init=nmInit, tol=nmTol, mask=nmMask, ratio=nmRatio, sinogram_order=nmSinoOrder) elif corFunction == 'pc': cor = tomopy.find_center_pc(tomo[0], tomo[1], tol=0.25) else: raise ValueError("\'corFunction\' must be one of: [ pc, vo, nm ].") print(", {}".format(cor)) else: print("using user input center of {}".format(cor)) function_list = [] if doOutliers1D: function_list.append('remove_outlier1d') if doOutliers2D: function_list.append('remove_outlier2d') if useNormalize_nf: function_list.append('normalize_nf') else: function_list.append('normalize') function_list.append('minus_log') if doBeamHardening: function_list.append('beam_hardening') if doFWringremoval: function_list.append('remove_stripe_fw') if doTIringremoval: function_list.append('remove_stripe_ti') if doSFringremoval: function_list.append('remove_stripe_sf') if correcttilt: function_list.append('correcttilt') if use360to180: function_list.append('do_360_to_180') if doPhaseRetrieval: function_list.append('phase_retrieval') function_list.append('recon_mask') if doPolarRing: function_list.append('polar_ring') if castTo8bit: function_list.append('castTo8bit') if doBilateralFilter: function_list.append('bilateral_filter') function_list.append('write_output') # Figure out first direction to slice for func in function_list: if slice_dir[func] != 'both': axis = slice_dir[func] break done = False curfunc = 0 curtemp = 0 while True: # Loop over reading data in certain chunking direction if axis=='proj': niter = numprojchunks else: niter = numsinochunks for y in range(niter): # Loop over chunks print("{} chunk {} of {}".format(axis, y+1, niter)) if curfunc==0: with warnings.catch_warnings(): warnings.simplefilter("ignore") if axis=='proj': tomo, flat, dark, floc = dxchange.read_als_832h5(inputPath+filename,ind_tomo=range(y*num_proj_per_chunk+projused[0],np.minimum((y + 1)*num_proj_per_chunk+projused[0],numangles)),sino=(sinoused[0],sinoused[1], sinoused[2]) ) else: tomo, flat, dark, floc = dxchange.read_als_832h5(inputPath+filename,ind_tomo=range(projused[0],projused[1],projused[2]),sino=(y*num_sino_per_chunk+sinoused[0],np.minimum((y + 1)*num_sino_per_chunk+sinoused[0],numslices),1) ) else: if axis=='proj': start, end = y * num_proj_per_chunk, np.minimum((y + 1) * num_proj_per_chunk,numprojused) tomo = dxchange.reader.read_hdf5(tempfilenames[curtemp],'/tmp/tmp',slc=((start,end,1),(0,numslices,1),(0,numrays,1))) #read in intermediate file else: start, end = y * num_sino_per_chunk, np.minimum((y + 1) * num_sino_per_chunk,numsinoused) tomo = dxchange.reader.read_hdf5(tempfilenames[curtemp],'/tmp/tmp',slc=((0,numangles,1),(start,end,1),(0,numrays,1))) dofunc = curfunc keepvalues = None while True: # Loop over operations to do in current chunking direction func_name = function_list[dofunc] newaxis = slice_dir[func_name] if newaxis != 'both' and newaxis != axis: # We have to switch axis, so flush to disk if y==0: try: os.remove(tempfilenames[1-curtemp]) except OSError: pass appendaxis = 1 if axis=='sino' else 0 dxchange.writer.write_hdf5(tomo,fname=tempfilenames[1-curtemp],gname='tmp',dname='tmp',overwrite=False,appendaxis=appendaxis) #writing intermediate file... break print(func_name, end=" ") curtime = time.time() if func_name == 'remove_outlier1d': tomo = tomo.astype(np.float32,copy=False) remove_outlier1d(tomo, outlier_diff1D, size=outlier_size1D, out=tomo) if func_name == 'remove_outlier2d': tomo = tomo.astype(np.float32,copy=False) tomopy.remove_outlier(tomo, outlier_diff2D, size=outlier_size2D, axis=0, out=tomo) elif func_name == 'normalize_nf': tomo = tomo.astype(np.float32,copy=False) tomopy.normalize_nf(tomo, flat, dark, floc_independent, out=tomo) #use floc_independent b/c when you read file in proj chunks, you don't get the correct floc returned right now to use here. elif func_name == 'normalize': tomo = tomo.astype(np.float32,copy=False) tomopy.normalize(tomo, flat, dark, out=tomo) elif func_name == 'minus_log': mx = np.float32(0.00000000000000000001) ne.evaluate('where(tomo>mx, tomo, mx)', out=tomo) tomopy.minus_log(tomo, out=tomo) elif func_name == 'beam_hardening': loc_dict = {'a{}'.format(i):np.float32(val) for i,val in enumerate(BeamHardeningCoefficients)} tomo = ne.evaluate('a0 + a1*tomo + a2*tomo**2 + a3*tomo**3 + a4*tomo**4 + a5*tomo**5', local_dict=loc_dict, out=tomo) elif func_name == 'remove_stripe_fw': tomo = tomopy.remove_stripe_fw(tomo, sigma=ringSigma, level=ringLevel, pad=True, wname=ringWavelet) elif func_name == 'remove_stripe_ti': tomo = tomopy.remove_stripe_ti(tomo, nblock=ringNBlock, alpha=ringAlpha) elif func_name == 'remove_stripe_sf': tomo = tomopy.remove_stripe_sf(tomo, size=ringSize) elif func_name == 'correcttilt': if tiltcenter_slice is None: tiltcenter_slice = numslices/2. if tiltcenter_det is None: tiltcenter_det = tomo.shape[2]/2 new_center = tiltcenter_slice - 0.5 - sinoused[0] center_det = tiltcenter_det - 0.5 #add padding of 10 pixels, to be unpadded right after tilt correction. This makes the tilted image not have zeros at certain edges, which matters in cases where sample is bigger than the field of view. For the small amounts we are generally tilting the images, 10 pixels is sufficient. # tomo = tomopy.pad(tomo, 2, npad=10, mode='edge') # center_det = center_det + 10 cntr = (center_det, new_center) for b in range(tomo.shape[0]): tomo[b] = st.rotate(tomo[b], correcttilt, center=cntr, preserve_range=True, order=1, mode='edge', clip=True) #center=None means image is rotated around its center; order=1 is default, order of spline interpolation # tomo = tomo[:, :, 10:-10] elif func_name == 'do_360_to_180': # Keep values around for processing the next chunk in the list keepvalues = [angularrange, numangles, projused, num_proj_per_chunk, numprojchunks, numprojused, numrays, anglelist] #why -.5 on one and not on the other? if tomo.shape[0]%2>0: tomo = sino_360_to_180(tomo[0:-1,:,:], overlap=int(np.round((tomo.shape[2]-cor-.5))*2), rotation='right') angularrange = angularrange/2 - angularrange/(tomo.shape[0]-1) else: tomo = sino_360_to_180(tomo[:,:,:], overlap=int(np.round((tomo.shape[2]-cor))*2), rotation='right') angularrange = angularrange/2 numangles = int(numangles/2) projused = (0,numangles-1,1) num_proj_per_chunk = np.minimum(chunk_proj,projused[1]-projused[0]) numprojchunks = (projused[1]-projused[0]-1)//num_proj_per_chunk+1 numprojused = (projused[1]-projused[0])//projused[2] numrays = tomo.shape[2] anglelist = anglelist[:numangles] elif func_name == 'phase_retrieval': tomo = tomopy.retrieve_phase(tomo, pixel_size=pxsize, dist=propagation_dist, energy=kev, alpha=alphaReg, pad=True) elif func_name == 'translation_correction': tomo = linear_translation_correction(tomo,dx=xshift,dy=yshift,interpolation=False): elif func_name == 'recon_mask': tomo = tomopy.pad(tomo, 2, npad=npad, mode='edge') if projIgnoreList is not None: for badproj in projIgnoreList: tomo[badproj] = 0 rec = tomopy.recon(tomo, anglelist, center=cor+npad, algorithm='gridrec', filter_name='butterworth', filter_par=[butterworth_cutoff, butterworth_order]) rec = rec[:, npad:-npad, npad:-npad] rec /= pxsize # convert reconstructed voxel values from 1/pixel to 1/cm rec = tomopy.circ_mask(rec, 0) elif func_name == 'polar_ring': rec = np.ascontiguousarray(rec, dtype=np.float32) rec = tomopy.remove_ring(rec, theta_min=Rarc, rwidth=Rmaxwidth, thresh_max=Rtmax, thresh=Rthr, thresh_min=Rtmin,out=rec) elif func_name == 'castTo8bit': rec = convert8bit(rec, cast8bit_min, cast8bit_max) elif func_name == 'bilateral_filter': rec = pyF3D.run_BilateralFilter(rec, spatialRadius=bilateral_srad, rangeRadius=bilateral_rrad) elif func_name == 'write_output': dxchange.write_tiff_stack(rec, fname=filenametowrite, start=y*num_sino_per_chunk + sinoused[0]) print('(took {:.2f} seconds)'.format(time.time()-curtime)) dofunc+=1 if dofunc==len(function_list): break if y<niter-1 and keepvalues: # Reset original values for next chunk angularrange, numangles, projused, num_proj_per_chunk, numprojchunks, numprojused, numrays, anglelist = keepvalues curtemp = 1 - curtemp curfunc = dofunc if curfunc==len(function_list): break axis = slice_dir[function_list[curfunc]] print("cleaning up temp files") for tmpfile in tempfilenames: try: os.remove(tmpfile) except OSError: pass print("End Time: "+time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())) print('It took {:.3f} s to process {}'.format(time.time()-start_time,inputPath+filename))
def reconstruct(h5fname, sino, rot_center, blocked_views=None): # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Manage the missing angles: if blocked_views is not None: print("Blocked Views: ", blocked_views) proj = np.concatenate((proj[0:blocked_views[0], :, :], proj[blocked_views[1] + 1:-1, :, :]), axis=0) theta = np.concatenate( (theta[0:blocked_views[0]], theta[blocked_views[1] + 1:-1])) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=1, pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) # Phase retrieval for tomobank id from 00032 to 00056 # sample_detector_distance = 6.0 # detector_pixel_size_x = 0.65e-4 # monochromator_energy = 27.4 # Phase retrieval for tomobank id 00058 and tomobank id 00059 # sample_detector_distance = 6.0 # detector_pixel_size_x = 0.65e-4 # monochromator_energy = 27.4 # Phase retrieval for tomobank id 00060 and tomobank id 00063 # sample_detector_distance = 2.5 # detector_pixel_size_x = 0.65e-4 # monochromator_energy = 27.4 # Phase retrieval for tomobank id 00064 # sample_detector_distance = 0.8 # detector_pixel_size_x = 1.4e-4 # monochromator_energy = 55.0 # Phase retrieval for tomobank id 00065 # sample_detector_distance = 5.8 # detector_pixel_size_x = 1.4e-4 # monochromator_energy = 55.0 # Phase retrieval for tomobank id 00066 # sample_detector_distance = 15.8 # detector_pixel_size_x = 1.4e-4 # monochromator_energy = 55.0 # Phase retrieval for tomobank id 00067 # sample_detector_distance = 30.8 # detector_pixel_size_x = 1.4e-4 # monochromator_energy = 55.0 # Phase retrieval for tomobank id 00068 # sample_detector_distance = 15.0 # detector_pixel_size_x = 4.1e-4 # monochromator_energy = 14.0 # Phase retrieval for tomobank id 00069 # sample_detector_distance = 0.4 # detector_pixel_size_x = 3.7e-4 # monochromator_energy = 36.085 # Phase retrieval for tomobank id 00070 # sample_detector_distance = 5.0 # detector_pixel_size_x = 0.65e-4 # monochromator_energy = 24.999 # Phase retrieval for tomobank id 00071 # sample_detector_distance = 1.5 # detector_pixel_size_x = 0.65e-4 # monochromator_energy = 24.999 # Phase retrieval for tomobank id 00072 # sample_detector_distance = 1.5 # detector_pixel_size_x = 1.43e-4 # monochromator_energy = 20.0 # Phase retrieval for tomobank id 00073 # sample_detector_distance = 1.0 # detector_pixel_size_x = 0.74e-4 # monochromator_energy = 25.0 # Phase retrieval for tomobank id 00074 # sample_detector_distance = 1.0 # detector_pixel_size_x = 0.74e-4 # monochromator_energy = 25.0 # Phase retrieval for tomobank id 00075 # sample_detector_distance = 11.0 # detector_pixel_size_x = 1.43e-4 # monochromator_energy = 60 # Phase retrieval for tomobank id 00076 # sample_detector_distance = 9.0 # detector_pixel_size_x = 2.2e-4 # monochromator_energy = 65 # # phase retrieval # data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=8e-3,pad=True) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 # Reconstruct object. rec = tomopy.recon(data, theta, center=rot_center, algorithm='gridrec') # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
for dataset in datasets: f.write('*****************************************************************************************************\n') f.write(dataset + '\n\n') for algorithm in algorithms: for sino in sinos: for core in cores: start_time = time.time() tomo, flats, darks, floc = tomopy.read_als_832h5(dataset, sino=(0, sino, 1)) end_time = time.time() - start_time f.write('Function: {0}, Number of sinos: {1}, Runtime (s): {2}\n'.format('read', sino, end_time)) theta = tomopy.angles(tomo.shape[0]) tomo = tomopy.normalize(tomo, flats, darks, ncore=core) end_time = time.time() - start_time - end_time f.write('Function: {0}, Number of sinos: {1}, Number of cores: {2}, Runtime (s): {3}\n'.format('normalize', sino, core, end_time)) tomo = tomopy.remove_stripe_fw(tomo, ncore=core) end_time = time.time() - start_time - end_time f.write('Function: {0}, Number of sinos: {1}, Number of cores: {2}, Runtime (s): {3}\n'.format('stripe_fw', sino, core, end_time)) rec = tomopy.recon(tomo, theta, center=datasets[dataset], algorithm=algorithm, emission=False, ncore=core) end_time = time.time() - start_time - end_time rec = tomopy.circ_mask(rec, 0) f.write('Function: {0}, Number of sinos: {1}, Number of cores: {2}, Algorithm: {3}, Runtime (s): {4}\n'.format('recon', sino, core, algorithm, end_time)) outname = os.path.join('.', '{0}_{1}_slices_{2}_cores_{3}'.format(dataset.split('.')[0], str(algorithm), str(sino), str(core)), dataset.split('.')[0]) tomopy.write_tiff_stack(rec, fname=outname) end_time = time.time() - start_time - end_time f.write('Function: {0}, Number of images: {1}, Runtime (s): {2}\n\n'.format('write', rec.shape[0], end_time)) f.flush() f.close()
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 8 # Propagation distance of the wavefront in cm detector_pixel_size_x = 2.247e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) monochromator_energy = 24.9 # Energy of incident wave in keV alpha = 1e-02 # Phase retrieval coeff. zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # zinger_removal # proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) # flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. ##data = tomopy.normalize(proj, flat, dark, cutoff=0.8) data = tomopy.normalize(proj, flat, dark) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=2, pad=True) #data = tomopy.remove_stripe_ti(data, alpha=1.5) data = tomopy.remove_stripe_sf(data, size=150) # phase retrieval #data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center / np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # padding N = data.shape[2] data_pad = np.zeros([data.shape[0], data.shape[1], 3 * N // 2], dtype="float32") data_pad[:, :, N // 4:5 * N // 4] = data data_pad[:, :, 0:N // 4] = np.tile( np.reshape(data[:, :, 0], [data.shape[0], data.shape[1], 1]), (1, 1, N // 4)) data_pad[:, :, 5 * N // 4:] = np.tile( np.reshape(data[:, :, -1], [data.shape[0], data.shape[1], 1]), (1, 1, N // 4)) data = data_pad rot_center = rot_center + N // 4 # Reconstruct object. if algorithm == 'sirtfbp': rec = rec_sirtfbp(data, theta, rot_center) else: rec = tomopy.recon(data, theta, center=rot_center, algorithm=algorithm, filter_name='parzen') rec = rec[:, N // 4:5 * N // 4, N // 4:5 * N // 4] print("Algorithm: ", algorithm) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
def rec_try(h5fname, nsino, rot_center, center_search_width, algorithm, binning): data_shape = get_dx_dims(h5fname, 'data') print(data_shape) ssino = int(data_shape[1] * nsino) rot_center+=data_shape[2]//4 center_range = (rot_center-center_search_width, rot_center+center_search_width, 0.5) #print(sino,ssino, center_range) #print(center_range[0], center_range[1], center_range[2]) # Select sinogram range to reconstruct sino = None start = ssino end = start + 1 sino = (start, end) # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=2,pad=True) #data = tomopy.remove_stripe_ti(data, alpha=1.5) data = tomopy.remove_stripe_sf(data, size=150) # remove stripes # data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) # padding N = data.shape[2] data_pad = np.zeros([data.shape[0],data.shape[1],3*N//2],dtype = "float32") data_pad[:,:,N//4:5*N//4] = data data_pad[:,:,0:N//4] = np.tile(np.reshape(data[:,:,0],[data.shape[0],data.shape[1],1]),(1,1,N//4)) data_pad[:,:,5*N//4:] = np.tile(np.reshape(data[:,:,-1],[data.shape[0],data.shape[1],1]),(1,1,N//4)) data = data_pad stack = np.empty((len(np.arange(*center_range)), data.shape[0], data.shape[2])) print(stack.shape) print(data.shape) index = 0 for axis in np.arange(*center_range): stack[index] = data[:, 0, :] index = index + 1 # Reconstruct the same slice with a range of centers. rec = tomopy.recon(stack, theta, center=np.arange(*center_range), sinogram_order=True, algorithm='gridrec', filter_name='parzen', nchunk=1) rec = rec[:,N//4:5*N//4,N//4:5*N//4] # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) index = 0 # Save images to a temporary folder. fname = os.path.dirname(h5fname) + '/' + 'try_rec/' + 'recon_' + os.path.splitext(os.path.basename(h5fname))[0] for axis in np.arange(*center_range): rfname = fname + '_' + str('{0:.2f}'.format(axis-N//4) + '.tiff') dxchange.write_tiff(rec[index], fname=rfname, overwrite=True) index = index + 1 print("Reconstructions: ", fname)
def recon( filename, inputPath='./', outputPath=None, outputFilename=None, doOutliers1D=False, # outlier removal in 1d (along sinogram columns) outlier_diff1D=750, # difference between good data and outlier data (outlier removal) outlier_size1D=3, # radius around each pixel to look for outliers (outlier removal) doOutliers2D=False, # outlier removal, standard 2d on each projection outlier_diff2D=750, # difference between good data and outlier data (outlier removal) outlier_size2D=3, # radius around each pixel to look for outliers (outlier removal) doFWringremoval=True, # Fourier-wavelet ring removal doTIringremoval=False, # Titarenko ring removal doSFringremoval=False, # Smoothing filter ring removal ringSigma=3, # damping parameter in Fourier space (Fourier-wavelet ring removal) ringLevel=8, # number of wavelet transform levels (Fourier-wavelet ring removal) ringWavelet='db5', # type of wavelet filter (Fourier-wavelet ring removal) ringNBlock=0, # used in Titarenko ring removal (doTIringremoval) ringAlpha=1.5, # used in Titarenko ring removal (doTIringremoval) ringSize=5, # used in smoothing filter ring removal (doSFringremoval) doPhaseRetrieval=False, # phase retrieval alphaReg=0.0002, # smaller = smoother (used for phase retrieval) propagation_dist=75, # sample-to-scintillator distance (phase retrieval) kev=24, # energy level (phase retrieval) butterworth_cutoff=0.25, #0.1 would be very smooth, 0.4 would be very grainy (reconstruction) butterworth_order=2, # for reconstruction doPolarRing=False, # ring removal Rarc=30, # min angle needed to be considered ring artifact (ring removal) Rmaxwidth=100, # max width of rings to be filtered (ring removal) Rtmax=3000.0, # max portion of image to filter (ring removal) Rthr=3000.0, # max value of offset due to ring artifact (ring removal) Rtmin=-3000.0, # min value of image to filter (ring removal) cor=None, # center of rotation (float). If not used then cor will be detected automatically corFunction='pc', # center of rotation function to use - can be 'pc', 'vo', or 'nm' voInd=None, # index of slice to use for cor search (vo) voSMin=-40, # min radius for searching in sinogram (vo) voSMax=40, # max radius for searching in sinogram (vo) voSRad=10, # search radius (vo) voStep=0.5, # search step (vo) voRatio=2.0, # ratio of field-of-view and object size (vo) voDrop=20, # drop lines around vertical center of mask (vo) nmInd=None, # index of slice to use for cor search (nm) nmInit=None, # initial guess for center (nm) nmTol=0.5, # desired sub-pixel accuracy (nm) nmMask=True, # if True, limits analysis to circular region (nm) nmRatio=1.0, # ratio of radius of circular mask to edge of reconstructed image (nm) nmSinoOrder=False, # if True, analyzes in sinogram space. If False, analyzes in radiograph space use360to180=False, # use 360 to 180 conversion doBilateralFilter=False, # if True, uses bilateral filter on image just before write step # NOTE: image will be converted to 8bit if it is not already bilateral_srad=3, # spatial radius for bilateral filter (image will be converted to 8bit if not already) bilateral_rrad=30, # range radius for bilateral filter (image will be converted to 8bit if not already) castTo8bit=False, # convert data to 8bit before writing cast8bit_min=-10, # min value if converting to 8bit cast8bit_max=30, # max value if converting to 8bit useNormalize_nf=False, # normalize based on background intensity (nf) chunk_proj=100, # chunk size in projection direction chunk_sino=100, # chunk size in sinogram direction npad=None, # amount to pad data before reconstruction projused=None, #should be slicing in projection dimension (start,end,step) sinoused=None, #should be sliceing in sinogram dimension (start,end,step). If first value is negative, it takes the number of slices from the second value in the middle of the stack. correcttilt=0, #tilt dataset tiltcenter_slice=None, # tilt center (x direction) tiltcenter_det=None, # tilt center (y direction) angle_offset=0, #this is the angle offset from our default (270) so that tomopy yields output in the same orientation as previous software (Octopus) anglelist=None, #if not set, will assume evenly spaced angles which will be calculated by the angular range and number of angles found in the file. if set to -1, will read individual angles from each image. alternatively, a list of angles can be passed. doBeamHardening=False, #turn on beam hardening correction, based on "Correction for beam hardening in computed tomography", Gabor Herman, 1979 Phys. Med. Biol. 24 81 BeamHardeningCoefficients=None, #6 values, tomo = a0 + a1*tomo + a2*tomo^2 + a3*tomo^3 + a4*tomo^4 + a5*tomo^5 projIgnoreList=None, #projections to be ignored in the reconstruction (for simplicity in the code, they will not be removed and will be processed as all other projections but will be set to zero absorption right before reconstruction. *args, **kwargs): start_time = time.time() print("Start {} at:".format(filename) + time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())) outputPath = inputPath if outputPath is None else outputPath outputFilename = filename if outputFilename is None else outputFilename tempfilenames = [outputPath + 'tmp0.h5', outputPath + 'tmp1.h5'] filenametowrite = outputPath + '/rec' + filename.strip( ".h5") + '/' + outputFilename #filenametowrite = outputPath+'/rec'+filename+'/'+outputFilename print("cleaning up previous temp files", end="") for tmpfile in tempfilenames: try: os.remove(tmpfile) except OSError: pass print(", reading metadata") datafile = h5py.File(inputPath + filename, 'r') gdata = dict(dxchange.reader._find_dataset_group(datafile).attrs) pxsize = float(gdata['pxsize']) / 10 # /10 to convert unites from mm to cm numslices = int(gdata['nslices']) numangles = int(gdata['nangles']) angularrange = float(gdata['arange']) numrays = int(gdata['nrays']) npad = int(np.ceil(numrays * np.sqrt(2)) - numrays) // 2 if npad is None else npad projused = (0, numangles - 1, 1) if projused is None else projused # ndark = int(gdata['num_dark_fields']) # ind_dark = list(range(0, ndark)) # group_dark = [numangles - 1] inter_bright = int(gdata['i0cycle']) nflat = int(gdata['num_bright_field']) ind_flat = list(range(0, nflat)) if inter_bright > 0: group_flat = list(range(0, numangles, inter_bright)) if group_flat[-1] != numangles - 1: group_flat.append(numangles - 1) elif inter_bright == 0: group_flat = [0, numangles - 1] else: group_flat = None ind_tomo = list(range(0, numangles)) floc_independent = dxchange.reader._map_loc(ind_tomo, group_flat) #figure out the angle list (a list of angles, one per projection image) dtemp = datafile[list(datafile.keys())[0]] fltemp = list(dtemp.keys()) firstangle = float(dtemp[fltemp[0]].attrs.get('rot_angle', 0)) if anglelist is None: #the offset angle should offset from the angle of the first image, which is usually 0, but in the case of timbir data may not be. #we add the 270 to be inte same orientation as previous software used at bl832 angle_offset = 270 + angle_offset - firstangle anglelist = tomopy.angles(numangles, angle_offset, angle_offset - angularrange) elif anglelist == -1: anglelist = np.zeros(shape=numangles) for icount in range(0, numangles): anglelist[icount] = np.pi / 180 * (270 + angle_offset - float( dtemp[fltemp[icount]].attrs['rot_angle'])) #if projused is different than default, need to chnage numangles and angularrange #can't do useNormalize_nf and doOutliers2D at the same time, or doOutliers2D and doOutliers1D at the same time, b/c of the way we chunk, for now just disable that if useNormalize_nf == True and doOutliers2D == True: useNormalize_nf = False print( "we cannot currently do useNormalize_nf and doOutliers2D at the same time, turning off useNormalize_nf" ) if doOutliers2D == True and doOutliers1D == True: doOutliers1D = False print( "we cannot currently do doOutliers1D and doOutliers2D at the same time, turning off doOutliers1D" ) #figure out how user can pass to do central x number of slices, or set of slices dispersed throughout (without knowing a priori the value of numslices) if sinoused is None: sinoused = (0, numslices, 1) elif sinoused[0] < 0: sinoused = ( int(np.floor(numslices / 2.0) - np.ceil(sinoused[1] / 2.0)), int(np.floor(numslices / 2.0) + np.floor(sinoused[1] / 2.0)), 1) num_proj_per_chunk = np.minimum(chunk_proj, projused[1] - projused[0]) numprojchunks = (projused[1] - projused[0] - 1) // num_proj_per_chunk + 1 num_sino_per_chunk = np.minimum(chunk_sino, sinoused[1] - sinoused[0]) numsinochunks = (sinoused[1] - sinoused[0] - 1) // num_sino_per_chunk + 1 numprojused = (projused[1] - projused[0]) // projused[2] numsinoused = (sinoused[1] - sinoused[0]) // sinoused[2] BeamHardeningCoefficients = ( 0, 1, 0, 0, 0, .1) if BeamHardeningCoefficients is None else BeamHardeningCoefficients if cor is None: print("Detecting center of rotation", end="") if angularrange > 300: lastcor = int(np.floor(numangles / 2) - 1) else: lastcor = numangles - 1 #I don't want to see the warnings about the reader using a deprecated variable in dxchange with warnings.catch_warnings(): warnings.simplefilter("ignore") tomo, flat, dark, floc = dxchange.read_als_832h5( inputPath + filename, ind_tomo=(0, lastcor)) tomo = tomo.astype(np.float32) if useNormalize_nf: tomopy.normalize_nf(tomo, flat, dark, floc, out=tomo) else: tomopy.normalize(tomo, flat, dark, out=tomo) if corFunction == 'vo': # same reason for catching warnings as above with warnings.catch_warnings(): warnings.simplefilter("ignore") cor = tomopy.find_center_vo(tomo, ind=voInd, smin=voSMin, smax=voSMax, srad=voSRad, step=voStep, ratio=voRatio, drop=voDrop) elif corFunction == 'nm': cor = tomopy.find_center( tomo, tomopy.angles(numangles, angle_offset, angle_offset - angularrange), ind=nmInd, init=nmInit, tol=nmTol, mask=nmMask, ratio=nmRatio, sinogram_order=nmSinoOrder) elif corFunction == 'pc': cor = tomopy.find_center_pc(tomo[0], tomo[1], tol=0.25) else: raise ValueError("\'corFunction\' must be one of: [ pc, vo, nm ].") print(", {}".format(cor)) else: print("using user input center of {}".format(cor)) function_list = [] if doOutliers1D: function_list.append('remove_outlier1d') if doOutliers2D: function_list.append('remove_outlier2d') if useNormalize_nf: function_list.append('normalize_nf') else: function_list.append('normalize') function_list.append('minus_log') if doBeamHardening: function_list.append('beam_hardening') if doFWringremoval: function_list.append('remove_stripe_fw') if doTIringremoval: function_list.append('remove_stripe_ti') if doSFringremoval: function_list.append('remove_stripe_sf') if correcttilt: function_list.append('correcttilt') if use360to180: function_list.append('do_360_to_180') if doPhaseRetrieval: function_list.append('phase_retrieval') function_list.append('recon_mask') if doPolarRing: function_list.append('polar_ring') if castTo8bit: function_list.append('castTo8bit') if doBilateralFilter: function_list.append('bilateral_filter') function_list.append('write_output') # Figure out first direction to slice for func in function_list: if slice_dir[func] != 'both': axis = slice_dir[func] break done = False curfunc = 0 curtemp = 0 while True: # Loop over reading data in certain chunking direction if axis == 'proj': niter = numprojchunks else: niter = numsinochunks for y in range(niter): # Loop over chunks print("{} chunk {} of {}".format(axis, y + 1, niter)) if curfunc == 0: with warnings.catch_warnings(): warnings.simplefilter("ignore") if axis == 'proj': tomo, flat, dark, floc = dxchange.read_als_832h5( inputPath + filename, ind_tomo=range( y * num_proj_per_chunk + projused[0], np.minimum( (y + 1) * num_proj_per_chunk + projused[0], numangles)), sino=(sinoused[0], sinoused[1], sinoused[2])) else: tomo, flat, dark, floc = dxchange.read_als_832h5( inputPath + filename, ind_tomo=range(projused[0], projused[1], projused[2]), sino=(y * num_sino_per_chunk + sinoused[0], np.minimum((y + 1) * num_sino_per_chunk + sinoused[0], numslices), 1)) else: if axis == 'proj': start, end = y * num_proj_per_chunk, np.minimum( (y + 1) * num_proj_per_chunk, numprojused) tomo = dxchange.reader.read_hdf5( tempfilenames[curtemp], '/tmp/tmp', slc=((start, end, 1), (0, numslices, 1), (0, numrays, 1))) #read in intermediate file else: start, end = y * num_sino_per_chunk, np.minimum( (y + 1) * num_sino_per_chunk, numsinoused) tomo = dxchange.reader.read_hdf5(tempfilenames[curtemp], '/tmp/tmp', slc=((0, numangles, 1), (start, end, 1), (0, numrays, 1))) dofunc = curfunc keepvalues = None while True: # Loop over operations to do in current chunking direction func_name = function_list[dofunc] newaxis = slice_dir[func_name] if newaxis != 'both' and newaxis != axis: # We have to switch axis, so flush to disk if y == 0: try: os.remove(tempfilenames[1 - curtemp]) except OSError: pass appendaxis = 1 if axis == 'sino' else 0 dxchange.writer.write_hdf5( tomo, fname=tempfilenames[1 - curtemp], gname='tmp', dname='tmp', overwrite=False, appendaxis=appendaxis) #writing intermediate file... break print(func_name, end=" ") curtime = time.time() if func_name == 'remove_outlier1d': tomo = tomo.astype(np.float32, copy=False) remove_outlier1d(tomo, outlier_diff1D, size=outlier_size1D, out=tomo) if func_name == 'remove_outlier2d': tomo = tomo.astype(np.float32, copy=False) tomopy.remove_outlier(tomo, outlier_diff2D, size=outlier_size2D, axis=0, out=tomo) elif func_name == 'normalize_nf': tomo = tomo.astype(np.float32, copy=False) tomopy.normalize_nf( tomo, flat, dark, floc_independent, out=tomo ) #use floc_independent b/c when you read file in proj chunks, you don't get the correct floc returned right now to use here. elif func_name == 'normalize': tomo = tomo.astype(np.float32, copy=False) tomopy.normalize(tomo, flat, dark, out=tomo) elif func_name == 'minus_log': mx = np.float32(0.00000000000000000001) ne.evaluate('where(tomo>mx, tomo, mx)', out=tomo) tomopy.minus_log(tomo, out=tomo) elif func_name == 'beam_hardening': loc_dict = { 'a{}'.format(i): np.float32(val) for i, val in enumerate(BeamHardeningCoefficients) } tomo = ne.evaluate( 'a0 + a1*tomo + a2*tomo**2 + a3*tomo**3 + a4*tomo**4 + a5*tomo**5', local_dict=loc_dict, out=tomo) elif func_name == 'remove_stripe_fw': tomo = tomopy.remove_stripe_fw(tomo, sigma=ringSigma, level=ringLevel, pad=True, wname=ringWavelet) elif func_name == 'remove_stripe_ti': tomo = tomopy.remove_stripe_ti(tomo, nblock=ringNBlock, alpha=ringAlpha) elif func_name == 'remove_stripe_sf': tomo = tomopy.remove_stripe_sf(tomo, size=ringSize) elif func_name == 'correcttilt': if tiltcenter_slice is None: tiltcenter_slice = numslices / 2. if tiltcenter_det is None: tiltcenter_det = tomo.shape[2] / 2 new_center = tiltcenter_slice - 0.5 - sinoused[0] center_det = tiltcenter_det - 0.5 #add padding of 10 pixels, to be unpadded right after tilt correction. This makes the tilted image not have zeros at certain edges, which matters in cases where sample is bigger than the field of view. For the small amounts we are generally tilting the images, 10 pixels is sufficient. # tomo = tomopy.pad(tomo, 2, npad=10, mode='edge') # center_det = center_det + 10 cntr = (center_det, new_center) for b in range(tomo.shape[0]): tomo[b] = st.rotate( tomo[b], correcttilt, center=cntr, preserve_range=True, order=1, mode='edge', clip=True ) #center=None means image is rotated around its center; order=1 is default, order of spline interpolation # tomo = tomo[:, :, 10:-10] elif func_name == 'do_360_to_180': # Keep values around for processing the next chunk in the list keepvalues = [ angularrange, numangles, projused, num_proj_per_chunk, numprojchunks, numprojused, numrays, anglelist ] #why -.5 on one and not on the other? if tomo.shape[0] % 2 > 0: tomo = sino_360_to_180( tomo[0:-1, :, :], overlap=int( np.round((tomo.shape[2] - cor - .5)) * 2), rotation='right') angularrange = angularrange / 2 - angularrange / ( tomo.shape[0] - 1) else: tomo = sino_360_to_180( tomo[:, :, :], overlap=int(np.round((tomo.shape[2] - cor)) * 2), rotation='right') angularrange = angularrange / 2 numangles = int(numangles / 2) projused = (0, numangles - 1, 1) num_proj_per_chunk = np.minimum(chunk_proj, projused[1] - projused[0]) numprojchunks = (projused[1] - projused[0] - 1) // num_proj_per_chunk + 1 numprojused = (projused[1] - projused[0]) // projused[2] numrays = tomo.shape[2] anglelist = anglelist[:numangles] elif func_name == 'phase_retrieval': tomo = tomopy.retrieve_phase(tomo, pixel_size=pxsize, dist=propagation_dist, energy=kev, alpha=alphaReg, pad=True) elif func_name == 'recon_mask': tomo = tomopy.pad(tomo, 2, npad=npad, mode='edge') if projIgnoreList is not None: for badproj in projIgnoreList: tomo[badproj] = 0 rec = tomopy.recon( tomo, anglelist, center=cor + npad, algorithm='gridrec', filter_name='butterworth', filter_par=[butterworth_cutoff, butterworth_order]) rec = rec[:, npad:-npad, npad:-npad] rec /= pxsize # convert reconstructed voxel values from 1/pixel to 1/cm rec = tomopy.circ_mask(rec, 0) elif func_name == 'polar_ring': rec = np.ascontiguousarray(rec, dtype=np.float32) rec = tomopy.remove_ring(rec, theta_min=Rarc, rwidth=Rmaxwidth, thresh_max=Rtmax, thresh=Rthr, thresh_min=Rtmin, out=rec) elif func_name == 'castTo8bit': rec = convert8bit(rec, cast8bit_min, cast8bit_max) elif func_name == 'bilateral_filter': rec = pyF3D.run_BilateralFilter( rec, spatialRadius=bilateral_srad, rangeRadius=bilateral_rrad) elif func_name == 'write_output': dxchange.write_tiff_stack(rec, fname=filenametowrite, start=y * num_sino_per_chunk + sinoused[0]) print('(took {:.2f} seconds)'.format(time.time() - curtime)) dofunc += 1 if dofunc == len(function_list): break if y < niter - 1 and keepvalues: # Reset original values for next chunk angularrange, numangles, projused, num_proj_per_chunk, numprojchunks, numprojused, numrays, anglelist = keepvalues curtemp = 1 - curtemp curfunc = dofunc if curfunc == len(function_list): break axis = slice_dir[function_list[curfunc]] print("cleaning up temp files") for tmpfile in tempfilenames: try: os.remove(tmpfile) except OSError: pass print("End Time: " + time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())) print('It took {:.3f} s to process {}'.format(time.time() - start_time, inputPath + filename))
# Select the sinogram range to reconstruct. start = 290 end = 294 # Read the APS 5-BM raw data proj, flat, dark = dxchange.read_aps_5bm(fname, sino=(start, end)) # Set data collection angles as equally spaced between 0-180 degrees. theta = tomopy.angles(proj.shape[0]) # Flat-field correction of raw data. proj = tomopy.normalize(proj, flat, dark) # remove stripes proj = tomopy.remove_stripe_fw(proj,level=7,wname='sym16',sigma=1,pad=True) # Set rotation center. rot_center = proj.shape[2] / 2.0 print("Center of rotation: ", rot_center) proj = tomopy.minus_log(proj) # Reconstruct object using Gridrec algorithm. rec = tomopy.recon(proj, theta, center=rot_center, algorithm='gridrec') # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) # Write data as stack of TIFs. dxchange.write_tiff_stack(rec, fname='recon_dir/recon')
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 31 # Propagation distance of the wavefront in cm detector_pixel_size_x = 1.17e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) monochromator_energy = 65 # Energy of incident wave in keV # used pink beam alpha = 1e-5 * 2**4 # Phase retrieval coeff. zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white # Read APS 2-BM raw data. # DIMAX saves 3 files: proj, flat, dark # when loading the data set select the proj file (larger size) fname = os.path.splitext(h5fname)[0] fbase = fname.rsplit('_', 1)[0] fnum = fname.rsplit('_', 1)[1] fext = os.path.splitext(h5fname)[1] fnum_flat = str("%4.4d" % (int(fnum) + 1)) fnum_dark = str("%4.4d" % (int(fnum) + 2)) fnproj = fbase + '_' + fnum + fext fnflat = fbase + '_' + fnum_flat + fext fndark = fbase + '_' + fnum_dark + fext print('proj', fnproj) print('flat', fnflat) print('dark', fndark) # Read APS 2-BM DIMAX raw data. proj, dum, dum2, theta = dxchange.read_aps_32id(fnproj, sino=sino) dum3, flat, dum4, dum5 = dxchange.read_aps_32id(fnflat, sino=sino) #flat, dum3, dum4, dum5 = dxchange.read_aps_32id(fnflat, sino=sino) dum6, dum7, dark, dum8 = dxchange.read_aps_32id(fndark, sino=sino) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=1, pad=True) # zinger_removal proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. ##data = tomopy.normalize(proj, flat, dark, cutoff=0.8) data = tomopy.normalize(proj, flat, dark) # remove stripes #data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) #data = tomopy.remove_stripe_ti(data, alpha=1.5) data = tomopy.remove_stripe_sf(data, size=150) # phase retrieval data = tomopy.prep.phase.retrieve_phase(data, pixel_size=detector_pixel_size_x, dist=sample_detector_distance, energy=monochromator_energy, alpha=alpha, pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center / np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # padding N = data.shape[2] data_pad = np.zeros([data.shape[0], data.shape[1], 3 * N // 2], dtype="float32") data_pad[:, :, N // 4:5 * N // 4] = data data_pad[:, :, 0:N // 4] = np.tile( np.reshape(data[:, :, 0], [data.shape[0], data.shape[1], 1]), (1, 1, N // 4)) data_pad[:, :, 5 * N // 4:] = np.tile( np.reshape(data[:, :, -1], [data.shape[0], data.shape[1], 1]), (1, 1, N // 4)) data = data_pad rot_center = rot_center + N // 4 nframes = 1 nproj = 1500 theta = np.linspace(0, np.pi * nframes, nproj * nframes, endpoint=False) rec = np.zeros((nframes, data.shape[1], data.shape[2], data.shape[2]), dtype='float32') for time_frame in range(0, nframes): rec0 = tomopy.recon(data[time_frame * nproj:(time_frame + 1) * nproj], theta[time_frame * nproj:(time_frame + 1) * nproj], center=rot_center, algorithm='gridrec') # Mask each reconstructed slice with a circle. rec[time_frame] = tomopy.circ_mask(rec0, axis=0, ratio=0.95) rec = rec[:, :, N // 4:5 * N // 4, N // 4:5 * N // 4] print("Algorithm: ", algorithm) return rec
from skimage.io import imread from skimage import data_dir from skimage.transform import radon, rescale, iradon import tomopy from normalize import normalize_bo dataset = '/home/svvenkatakrishnan/data/20130807_234356_OIM121R_SAXS_5x.h5' algorithm = 'sirt' tomo, flats, darks, floc = tomopy.read_als_832h5(dataset, sino=(1000, 1003, 1)) print('Data read complete') print('Displaying sinogram') imgplot = plt.imshow(tomo[:, 0, :]) print('Generating angles') theta = tomopy.angles(tomo.shape[0]) print('Normalization') tomo = normalize_bo(tomo, flats, darks, 20) print('Ring removal') tomo = tomopy.remove_stripe_fw(tomo) print('Recon') rec = tomopy.recon(tomo, theta, center=1294, algorithm='osem', emission=False) print('Masking') rec = tomopy.circ_mask(rec, 0) tomopy.write_tiff_stack(rec, 'test.tiff')
def fast_tomo_recon(argv): """ Reconstruct subset slices (sinograms) equally spaced within tomographic dataset """ logger = logging.getLogger('fast_tomopy.fast_tomo_recon') # Parse arguments passed to function parser = argparse.ArgumentParser() parser.add_argument('-i', '--input', type=str, help='path to input raw ' 'dataset', required=True) parser.add_argument('-o', '--output-file', type=str, help='full path to h5 output ' 'file', default=os.path.join(os.getcwd(), "fast-tomopy.h5")) parser.add_argument('-sn', '--sino-num', type=int, help='Number of slices ' 'to reconstruct', default=5) parser.add_argument('-a', '--algorithm', type=str, help='Reconstruction' ' algorithm', default='gridrec', choices=[ 'art', 'bart', 'fbp', 'gridrec', 'mlem', 'ospml_hybrid', 'ospml_quad', 'pml_hybrid', 'pml_quad', 'sirt' ]) parser.add_argument('-c', '--center', type=float, help='Center of rotation', default=None) parser.add_argument('-fn', '--filter-name', type=str, help='Name of filter' ' used for reconstruction', choices=[ 'none', 'shepp', 'cosine', 'hann', 'hamming', 'ramlak', 'parzen', 'butterworth' ], default='butterworth') parser.add_argument('-rr', '--ring-remove', type=str, help='Ring removal ' 'method', choices=['Octopus', 'Tomopy-FW', 'Tomopy-T'], default='Tomopy-T') parser.add_argument('-lf', '--log-file', type=str, help='log file name', default='fast-tomopy.log') args = parser.parse_args() fh = logging.FileHandler(args.log_file) fh.setLevel(logging.INFO) fh.setFormatter(formatter) logger.addHandler(fh) if os.path.isdir(os.path.dirname(args.output_file)) is False: raise IOError(2, 'Directory of output file does not exist', args.output_file) # Read file metadata logger.info('Reading input file metadata') fdata, gdata = read_als_832h5_metadata(args.input) proj_total = int(gdata['nangles']) last = proj_total - 1 sino_total = int(gdata['nslices']) ray_total = int(gdata['nrays']) px_size = float(gdata['pxsize']) / 10 # cm # Set parameters for sinograms to read step = sino_total // (args.sino_num + 2) start = step end = step * (args.sino_num + 1) sino = (start, end, step) # Read full first and last projection to determine center of rotation if args.center is None: logger.info('Reading full first and last projection for COR') first_last, flats, darks, foobar = dx.read_als_832h5(args.input, ind_tomo=(0, last)) first_last = tomopy.normalize(first_last, flats, darks) args.center = tomopy.find_center_pc(first_last[0, :, :], first_last[1, :, :], tol=0.1) logger.info('Detected center: %f', args.center) # Read and normalize raw sinograms logger.info('Reading raw data') tomo, flats, darks, foobar = dx.read_als_832h5(args.input, sino=sino) logger.info('Normalizing raw data') tomo = tomopy.normalize(tomo, flats, darks) tomo = tomopy.minus_log(tomo) # Remove stripes from sinograms (remove rings) logger.info('Preprocessing normalized data') if args.ring_remove == 'Tomopy-FW': logger.info('Removing stripes from sinograms with %s', args.ring_remove) tomo = tomopy.remove_stripe_fw(tomo) elif args.ring_remove == 'Tomopy-T': logger.info('Removing stripes from sinograms with %s', args.ring_remove) tomo = tomopy.remove_stripe_ti(tomo) # Pad sinograms with edge values npad = int(np.ceil(ray_total * np.sqrt(2)) - ray_total) // 2 tomo = tomopy.pad(tomo, 2, npad=npad, mode='edge') args.center += npad # account for padding filter_name = np.array(args.filter_name, dtype=(str, 16)) theta = tomopy.angles(proj_total, 270, 90) logger.info('Reconstructing normalized data') # Reconstruct sinograms # rec = tomopy.minus_log(tomo, out=tomo) rec = tomopy.recon(tomo, theta, center=args.center, algorithm=args.algorithm, filter_name=filter_name) rec = tomopy.circ_mask(rec[:, npad:-npad, npad:-npad], 0) rec = rec / px_size # Remove rings from reconstruction if args.ring_remove == 'Octopus': logger.info('Removing rings from reconstructions with %s', args.ring_remove) thresh = float(gdata['ring_threshold']) thresh_max = float(gdata['upp_ring_value']) thresh_min = float(gdata['low_ring_value']) theta_min = int(gdata['max_arc_length']) rwidth = int(gdata['max_ring_size']) rec = tomopy.remove_rings(rec, center_x=args.center, thresh=thresh, thresh_max=thresh_max, thresh_min=thresh_min, theta_min=theta_min, rwidth=rwidth) # Write reconstruction data to new hdf5 file fdata['stage'] = 'fast-tomopy' fdata['stage_flow'] = '/raw/' + fdata['stage'] fdata['stage_version'] = 'fast-tomopy-0.1' # Generate a new uuid based on host ID and current time fdata['uuid'] = str(uuid.uuid1()) gdata['Reconstruction_Type'] = 'tomopy-gridrec' gdata['ring_removal_method'] = args.ring_remove gdata['rfilter'] = args.filter_name logger.info('Writing reconstructed data to h5 file') write_als_832h5(rec, args.input, fdata, gdata, args.output_file, step) return
def reconstruct(h5fname, sino, rot_center, args, blocked_views=None): # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Manage the missing angles: if blocked_views is not None: print("Blocked Views: ", blocked_views) proj = np.concatenate((proj[0:blocked_views[0], :, :], proj[blocked_views[1] + 1:-1, :, :]), axis=0) theta = np.concatenate( (theta[0:blocked_views[0]], theta[blocked_views[1] + 1:-1])) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=1, pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 algorithm = args.algorithm ncores = args.ncores nitr = args.num_iter # always add algorithm _kwargs = {"algorithm": algorithm} # assign number of cores _kwargs["ncore"] = ncores # use the accelerated version if algorithm in ["mlem", "sirt"]: _kwargs["accelerated"] = True # don't assign "num_iter" if gridrec or fbp if algorithm not in ["fbp", "gridrec"]: _kwargs["num_iter"] = nitr sname = os.path.join(args.output_dir, 'proj_{}'.format(args.algorithm)) print(proj.shape) tmp = np.zeros((proj.shape[0], proj.shape[2])) tmp[:, :] = proj[:, 0, :] output_image(tmp, sname + "." + args.format) # Reconstruct object. with timemory.util.auto_timer( "[tomopy.recon(algorithm='{}')]".format(algorithm)): print("Starting reconstruction with kwargs={}...".format(_kwargs)) rec = tomopy.recon(data, theta, **_kwargs) print("Completed reconstruction...") # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) obj = np.zeros(rec.shape, dtype=rec.dtype) label = "{} @ {}".format(algorithm.upper(), h5fname) quantify_difference(label, obj, rec) return rec
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 8 # Propagation distance of the wavefront in cm detector_pixel_size_x = 2.247e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) monochromator_energy = 24.9 # Energy of incident wave in keV alpha = 1e-02 # Phase retrieval coeff. zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # zinger_removal # proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) # flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. ##data = tomopy.normalize(proj, flat, dark, cutoff=0.8) data = tomopy.normalize(proj, flat, dark) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=1, pad=True) # data = tomopy.remove_stripe_ti(data, alpha=1.5) # data = tomopy.remove_stripe_sf(data, size=150) # phase retrieval #data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center / np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # Reconstruct object. if algorithm == 'sirtfbp': rec = rec_sirtfbp(data, theta, rot_center) elif algorithm == 'astrasirt': extra_options = {'MinConstraint': 0} options = { 'proj_type': 'cuda', 'method': 'SIRT_CUDA', 'num_iter': 200, 'extra_options': extra_options } rec = tomopy.recon(data, theta, center=rot_center, algorithm=tomopy.astra, options=options) else: rec = tomopy.recon(data, theta, center=rot_center, algorithm=algorithm, filter_name='parzen') print("Algorithm: ", algorithm) # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) return rec
def center(io_paras, data_paras, center_start, center_end, center_step, diag_cycle=0, mode='diag', normalize=True, stripe_removal=10, phase_retrieval=False): # Input and output datafile = io_paras.get('datafile') path2white = io_paras.get('path2white', datafile) path2dark = io_paras.get('path2dark', path2white) out_dir = io_paras.get('out_dir') diag_cent_dir = io_paras.get('diag_cent_dir', out_dir+"/center_diagnose/") recon_dir = io_paras.get('recon_dir', out_dir+"/recon/") out_prefix = io_paras.get('out_prefix', "recon_") # Parameters of dataset NumCycles = data_paras.get('NumCycles', 1) # Number of cycles used for recon ProjPerCycle = data_paras.get('ProjPerCycle') # Number of projections per cycle, N_theta cycle_offset = data_paras.get('cycle_offset', 0) # Offset in output cycle number proj_start = data_paras.get('proj_start', 0) # Starting projection of reconstruction proj_step = data_paras.get('proj_step') z_start = data_paras.get('z_start', 0) z_end = data_paras.get('z_end', z_start+1) z_step = data_paras.get('z_step') x_start = data_paras.get('x_start') x_end = data_paras.get('x_end', x_start+1) x_step = data_paras.get('x_step') white_start = data_paras.get('white_start') white_end = data_paras.get('white_end') dark_start = data_paras.get('dark_start') dark_end = data_paras.get('dark_end') # Set start and end of each subcycle projections_start = diag_cycle * ProjPerCycle + proj_start projections_end = projections_start + ProjPerCycle slice1 = slice(projections_start, projections_end, proj_step) slice2 = slice(z_start, z_end, z_step) slice3 = slice(x_start, x_end, x_step) slices = (slice1, slice2, slice3) white_slices = (slice(white_start, white_end), slice2, slice3) dark_slices = (slice(dark_start, dark_end), slice2, slice3) print("Running center diagnosis (projs %s to %s)" % (projections_start, projections_end)) # Read HDF5 file. print("Reading datafile %s..." % datafile, end="") sys.stdout.flush() data, white, dark = reader.read_aps_2bm(datafile, slices, white_slices, dark_slices, path2white=path2white, path2dark=path2dark) theta = gen_theta(data.shape[0]) print("Done!") print("Data shape = %s;\nwhite shape = %s;\ndark shape = %s." % (data.shape, white.shape, dark.shape)) ## Normalize dataset using data_white and data_dark if normalize: data = tomopy.normalize(data, white, dark, cutoff=None, ncore=_ncore, nchunk=None) ## Remove stripes caused by dead pixels in the detector if stripe_removal: data = tomopy.remove_stripe_fw(data, level=stripe_removal, wname='db5', sigma=2, pad=True, ncore=None, nchunk=None) # data = tomopy.remove_stripe_ti(data, nblock=0, alpha=1.5, # ncore=None, nchunk=None) # # Show preprocessed projection # plt.figure("%s-prep" % projections_start) # plt.imshow(d.data[0,:,:], cmap=cm.Greys_r) # plt.savefig(out_dir+"/preprocess/%s-prep.jpg" # % projections_start) # # plt.show() # continue ## Phase retrieval if phase_retrieval: data = tomopy.retrieve_phase(data, pixel_size=6.5e-5, dist=33, energy=30, alpha=1e-3, pad=True, ncore=_ncore, nchunk=None) ## Determine and set the center of rotation ### Using optimization method to automatically find the center # d.optimize_center() if 'opti' in mode: print("Optimizing center ...", end="") sys.stdout.flush() rot_center = tomopy.find_center(data, theta, ind=None, emission=True, init=None, tol=0.5, mask=True, ratio=1.) print("Done!") print("center = %s" % rot_center) ### Output the reconstruction results using a range of centers, ### and then manually find the optimal center. if 'diag' in mode: if not os.path.exists(diag_cent_dir): os.makedirs(diag_cent_dir) print("Testing centers ...", end="") sys.stdout.flush() tomopy.write_center(data, theta, dpath=diag_cent_dir, cen_range=[center_start, center_end, center_step], ind=None, emission=False, mask=False, ratio=1.) print("Done!")
def reconstruct(h5fname, sino, rot_center, args, blocked_views=None): # Read APS 32-BM raw data. proj, flat, dark, theta = dxchange.read_aps_32id(h5fname, sino=sino) # Manage the missing angles: if blocked_views is not None: print("Blocked Views: ", blocked_views) proj = np.concatenate((proj[0:blocked_views[0], :, :], proj[blocked_views[1]+1:-1, :, :]), axis=0) theta = np.concatenate((theta[0:blocked_views[0]], theta[blocked_views[1]+1: -1])) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data, level=7, wname='sym16', sigma=1, pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 algorithm = args.algorithm ncores = args.ncores nitr = args.num_iter # always add algorithm _kwargs = {"algorithm": algorithm} # assign number of cores _kwargs["ncore"] = ncores # use the accelerated version if algorithm in ["mlem", "sirt"]: _kwargs["accelerated"] = True # don't assign "num_iter" if gridrec or fbp if algorithm not in ["fbp", "gridrec"]: _kwargs["num_iter"] = nitr sname = os.path.join(args.output_dir, 'proj_{}'.format(args.algorithm)) print(proj.shape) tmp = np.zeros((proj.shape[0], proj.shape[2])) tmp[:,:] = proj[:,0,:] output_image(tmp, sname + "." + args.format) # Reconstruct object. with timemory.util.auto_timer( "[tomopy.recon(algorithm='{}')]".format(algorithm)): print("Starting reconstruction with kwargs={}...".format(_kwargs)) rec = tomopy.recon(data, theta, **_kwargs) print("Completed reconstruction...") # Mask each reconstructed slice with a circle. rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) obj = np.zeros(rec.shape, dtype=rec.dtype) label = "{} @ {}".format(algorithm.upper(), h5fname) quantify_difference(label, obj, rec) return rec
def cleaning( filename, bffilename=None, inputPath='/', #input path, location of the data set to reconstruct outputPath=None, # define an output path (default is inputPath), a sub-folder will be created based on file name outputFilename=None, #file name for output tif files (a number and .tiff will be added). default is based on input filename fulloutputPath=None, # definte the full output path, no automatic sub-folder will be created doFWringremoval=True, # Fourier-wavelet ring removal ringSigma=3, # damping parameter in Fourier space (Fourier-wavelet ring removal) ringLevel=8, # number of wavelet transform levels (Fourier-wavelet ring removal) ringWavelet='db5', # type of wavelet filter (Fourier-wavelet ring removal) ringNBlock=0, # used in Titarenko ring removal (doTIringremoval) ringAlpha=1.5, # used in Titarenko ring removal (doTIringremoval) ringSize=5, # used in smoothing filter ring removal (doSFringremoval) butterworth_cutoff=0.25, #0.1 would be very smooth, 0.4 would be very grainy (reconstruction) butterworth_order=2, # for reconstruction npad=None, # amount to pad data before reconstruction projused=None, # should be slicing in projection dimension (start,end,step) Be sure to add one to the end as stop in python means the last value is omitted sinoused=None, # should be sliceing in sinogram dimension (start,end,step). If first value is negative, it takes the number of slices from the second value in the middle of the stack. angle_offset=0, # this is the angle offset from our default (270) so that tomopy yields output in the same orientation as previous software (Octopus) anglelist=None, # if not set, will assume evenly spaced angles which will be calculated by the angular range and number of angles found in the file. if set to -1, will read individual angles from each image. alternatively, a list of angles can be passed. cor=None, # center of rotation (float). If not used then cor will be detected automatically corFunction='pc', # center of rotation function to use - can be 'pc', 'vo', or 'nm' voInd=None, # index of slice to use for cor search (vo) voSMin=-40, # min radius for searching in sinogram (vo) voSMax=40, # max radius for searching in sinogram (vo) voSRad=10, # search radius (vo) voStep=0.5, # search step (vo) voRatio=2.0, # ratio of field-of-view and object size (vo) voDrop=20, # drop lines around vertical center of mask (vo) nmInd=None, # index of slice to use for cor search (nm) nmInit=None, # initial guess for center (nm) nmTol=0.5, # desired sub-pixel accuracy (nm) nmMask=True, # if True, limits analysis to circular region (nm) nmRatio=1.0, # ratio of radius of circular mask to edge of reconstructed image (nm) nmSinoOrder=False, # if True, analyzes in sinogram space. If False, analyzes in radiograph space useNormalize_nf=False, # normalize based on background intensity (nf) bfexposureratio=1 #ratio of exposure time of bf to exposure time of sample ): start_time = time.time() print("Start {} at:".format(filename) + time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())) outputFilename = os.path.splitext( filename)[0] if outputFilename is None else outputFilename outputPath = inputPath + 'rec' + os.path.splitext( filename )[0] + '/' if outputPath is None else outputPath + 'rec' + os.path.splitext( filename)[0] + '/' fulloutputPath = outputPath if fulloutputPath is None else fulloutputPath tempfilenames = [fulloutputPath + 'tmp0.h5', fulloutputPath + 'tmp1.h5'] filenametowrite = fulloutputPath + outputFilename print(filenametowrite) print("cleaning up previous temp files", end="") for tmpfile in tempfilenames: try: os.remove(tmpfile) except OSError: pass print(", reading metadata") datafile = h5py.File(inputPath + filename, 'r') gdata = dict(dxchange.reader._find_dataset_group(datafile).attrs) numslices = int(gdata['nslices']) numangles = int(gdata['nangles']) print('There are ' + str(numslices) + ' sinograms and ' + str(numangles) + ' projections') angularrange = float(gdata['arange']) numrays = int(gdata['nrays']) npad = int(np.ceil(numrays * np.sqrt(2)) - numrays) // 2 if npad is None else npad if projused is not None and ( projused[1] > numangles - 1 or projused[0] < 0 ): #allows program to deal with out of range projection values if projused[1] > numangles: print( "End Projection value greater than number of angles. Value has been lowered to the number of angles " + str(numangles)) projused = (projused[0], numangles, projused[2]) if projused[0] < 0: print("Start Projection value less than zero. Value raised to 0") projused = (0, projused[1], projused[2]) if projused is None: projused = (0, numangles, 1) else: #if projused is different than default, need to chnage numangles and angularrange #dula attempting to do this with these two lines, we'll see if it works! 11/16/17 testrange = range(projused[0], projused[1], projused[2]) #+1 because we need to compensate for the range functions last value always being one less than the second arg angularrange = (angularrange / (numangles - 1)) * (projused[1] - projused[0]) # want angular range to stay constant if we keep the end values consistent numangles = len(testrange) # ndark = int(gdata['num_dark_fields']) # ind_dark = list(range(0, ndark)) # group_dark = [numangles - 1] inter_bright = int(gdata['i0cycle']) if inter_bright > 0: group_flat = list(range(0, numangles, inter_bright)) if group_flat[-1] != numangles - 1: group_flat.append(numangles - 1) elif inter_bright == 0: group_flat = [0, numangles - 1] else: group_flat = None # figure out the angle list (a list of angles, one per projection image) dtemp = datafile[list(datafile.keys())[0]] fltemp = list(dtemp.keys()) firstangle = float(dtemp[fltemp[0]].attrs.get('rot_angle', 0)) anglegap = angularrange / (numangles - 1) firstangle += anglegap * projused[0] #accounting for projused argument if anglelist is None: #the offset angle should offset from the angle of the first image, which is usually 0, but in the case of timbir data may not be. #we add the 270 to be inte same orientation as previous software used at bl832 angle_offset = 270 + angle_offset - firstangle anglelist = tomopy.angles(numangles, angle_offset, angle_offset - angularrange) elif anglelist == -1: anglelist = np.zeros(shape=numangles) for icount in range(0, numangles): anglelist[icount] = np.pi / 180 * (270 + angle_offset - float( dtemp[fltemp[icount]].attrs['rot_angle'])) #figure out how user can pass to do central x number of slices, or set of slices dispersed throughout (without knowing a priori the value of numslices) if sinoused is None: sinoused = (0, numslices, 1) elif sinoused[0] < 0: sinoused = ( int(np.floor(numslices / 2.0) - np.ceil(sinoused[1] / 2.0)), int(np.floor(numslices / 2.0) + np.floor(sinoused[1] / 2.0)), 1) if cor is None: print("Detecting center of rotation", end="") if angularrange > 300: lastcor = int(np.floor(numangles / 2) - 1) else: lastcor = numangles - 1 # I don't want to see the warnings about the reader using a deprecated variable in dxchange with warnings.catch_warnings(): warnings.simplefilter("ignore") tomo, flat, dark, floc = dxchange.read_als_832h5( inputPath + filename, ind_tomo=(0, lastcor)) if bffilename is not None: tomobf, flatbf, darkbf, flocbf = dxchange.read_als_832h5( inputPath + bffilename) flat = tomobf tomo = tomo.astype(np.float32) if useNormalize_nf: tomopy.normalize_nf(tomo, flat, dark, floc, out=tomo) if bfexposureratio != 1: tomo = tomo * bfexposureratio else: tomopy.normalize(tomo, flat, dark, out=tomo) if bfexposureratio != 1: tomo = tomo * bfexposureratio if corFunction == 'vo': # same reason for catching warnings as above with warnings.catch_warnings(): warnings.simplefilter("ignore") cor = tomopy.find_center_vo(tomo, ind=voInd, smin=voSMin, smax=voSMax, srad=voSRad, step=voStep, ratio=voRatio, drop=voDrop) elif corFunction == 'nm': cor = tomopy.find_center( tomo, tomopy.angles(numangles, angle_offset, angle_offset - angularrange), ind=nmInd, init=nmInit, tol=nmTol, mask=nmMask, ratio=nmRatio, sinogram_order=nmSinoOrder) elif corFunction == 'pc': cor = tomopy.find_center_pc(tomo[0], tomo[1], tol=0.25) else: raise ValueError("\'corFunction\' must be one of: [ pc, vo, nm ].") print(", {}".format(cor)) else: print("using user input center of {}".format(cor)) tomo, flat, dark, floc = dxchange.read_als_832h5( inputPath + filename, ind_tomo=range(projused[0], projused[1], projused[2]), sino=(sinoused[0], sinoused[1], sinoused[2])) tomo = tomo.astype(np.float32, copy=False) tomopy.normalize(tomo, flat, dark, out=tomo) mx = np.float32(0.01) ne.evaluate('where(tomo>mx, tomo, mx)', out=tomo) tomopy.minus_log(tomo, out=tomo) tomo = tomopy.remove_stripe_fw(tomo, sigma=ringSigma, level=ringLevel, pad=True, wname=ringWavelet) tomo = tomopy.pad(tomo, 2, npad=npad, mode='edge') tomo = np.swapaxes(tomo, 0, 1) theta = anglelist print('It took {:.3f} s to process {}'.format(time.time() - start_time, inputPath + filename)) return tomo, theta, cor
def reconstruct(filename,inputPath="", outputPath="", COR=COR, doOutliers=doOutliers, outlier_diff=outlier_diff, outlier_size=outlier_size, doFWringremoval=doFWringremoval, ringSigma=ringSigma,ringLevel=ringLevel, ringWavelet=ringWavelet,pad_sino=pad_sino, doPhaseRetrieval=doPhaseRetrieval, propagation_dist=propagation_dist, kev=kev,alphaReg=alphaReg, butterworthpars=butterworthpars, doPolarRing=doPolarRing,Rarc=Rarc, Rmaxwidth=Rmaxwidth, Rtmax=Rtmax, Rthr=Rthr, Rtmin=Rtmin, useAutoCOR=useAutoCOR, use360to180=use360to180, num_substacks=num_substacks,recon_slice=recon_slice): # Convert filename to list type if only one file name is given if type(filename) != list: filename=[filename] # If useAutoCor == true, a list of COR will be automatically calculated for all files # If a list of COR is given, only entries with boolean False will use automatic COR calculation if useAutoCOR==True or (len(COR) != len(filename)): logging.info('using auto COR for all input files') COR = [False]*len(filename) for x in range(len(filename)): logging.info('opening data set, checking metadata') fdata, gdata = read_als_832h5_metadata(inputPath[x]+filename[x]+'.h5') pxsize = float(gdata['pxsize'])/10.0 # convert from metadata (mm) to this script (cm) numslices = int(gdata['nslices']) # recon_slice == True, only center slice will be reconstructed # if integer is given, a specific if recon_slice != False: if (type(recon_slice) == int) and (recon_slice <= numslices): sinorange [recon_slice-1, recon_slice] else: sinorange = [numslices//2-1, numslices//2] else: sinorange = [0, numslices] # Calculate number of substacks (chunks) substacks = num_substacks #(sinorange[1]-sinorange[0]-1)//num_sino_per_substack+1 if (sinorange[1]-sinorange[0]) >= substacks: num_sino_per_substack = (sinorange[1]-sinorange[0])//num_substacks else: num_sino_per_substack = 1 firstcor, lastcor = 0, int(gdata['nangles'])-1 projs, flat, dark, floc = dxchange.read_als_832h5(inputPath[x]+filename[x]+'.h5', ind_tomo=(firstcor, lastcor)) projs = tomopy.normalize_nf(projs, flat, dark, floc) autocor = tomopy.find_center_pc(projs[0], projs[1], tol=0.25) if (type(COR[x]) == bool) or (COR[x]<0) or (COR[x]=='auto'): firstcor, lastcor = 0, int(gdata['nangles'])-1 projs, flat, dark, floc = dxchange.read_als_832h5(inputPath[x]+filename[x]+'.h5', ind_tomo=(firstcor, lastcor)) projs = tomopy.normalize_nf(projs, flat, dark, floc) cor = tomopy.find_center_pc(projs[0], projs[1], tol=0.25) else: cor = COR[x] logging.info('Dataset %s, has %d total slices, reconstructing slices %d through %d in %d substack(s), using COR: %f',filename[x], int(gdata['nslices']), sinorange[0], sinorange[1]-1, substacks, cor) for y in range(0, substacks): logging.info('Starting dataset %s (%d of %d), substack %d of %d',filename[x], x+1, len(filename), y+1, substacks) logging.info('Reading sinograms...') projs, flat, dark, floc = dxchange.read_als_832h5(inputPath[x]+filename[x]+'.h5', sino=(sinorange[0]+y*num_sino_per_substack, sinorange[0]+(y+1)*num_sino_per_substack, 1)) logging.info('Doing remove outliers, norm (nearest flats), and -log...') if doOutliers: projs = tomopy.remove_outlier(projs, outlier_diff, size=outlier_size, axis=0) flat = tomopy.remove_outlier(flat, outlier_diff, size=outlier_size, axis=0) tomo = tomopy.normalize_nf(projs, flat, dark, floc) tomo = tomopy.minus_log(tomo, out=tomo) # in place logarithm # Use padding to remove halo in reconstruction if present if pad_sino: npad = int(np.ceil(tomo.shape[2] * np.sqrt(2)) - tomo.shape[2])//2 tomo = tomopy.pad(tomo, 2, npad=npad, mode='edge') cor_rec = cor + npad # account for padding else: cor_rec = cor if doFWringremoval: logging.info('Doing ring (Fourier-wavelet) function...') tomo = tomopy.remove_stripe_fw(tomo, sigma=ringSigma, level=ringLevel, pad=True, wname=ringWavelet) if doPhaseRetrieval: logging.info('Doing Phase retrieval...') #tomo = tomopy.retrieve_phase(tomo, pixel_size=pxsize, dist=propagation_dist, energy=kev, alpha=alphaReg, pad=True) tomo = tomopy.retrieve_phase(tomo, pixel_size=pxsize, dist=propagation_dist, energy=kev, alpha=alphaReg, pad=True) logging.info('Doing recon (gridrec) function and scaling/masking, with cor %f...',cor_rec) rec = tomopy.recon(tomo, tomopy.angles(tomo.shape[0], 270, 90), center=cor_rec, algorithm='gridrec', filter_name='butterworth', filter_par=butterworthpars) #rec = tomopy.recon(tomo, tomopy.angles(tomo.shape[0], 180+angularrange/2, 180-angularrange/2), center=cor_rec, algorithm='gridrec', filter_name='butterworth', filter_par=butterworthpars) rec /= pxsize # intensity values in cm^-1 if pad_sino: rec = tomopy.circ_mask(rec[:, npad:-npad, npad:-npad], 0) else: rec = tomopy.circ_mask(rec, 0, ratio=1.0, val=0.0) if doPolarRing: logging.info('Doing ring (polar mean filter) function...') rec = tomopy.remove_ring(rec, theta_min=Rarc, rwidth=Rmaxwidth, thresh_max=Rtmax, thresh=Rthr, thresh_min=Rtmin) logging.info('Writing reconstruction slices to %s', filename[x]) #dxchange.write_tiff_stack(rec, fname=outputPath+'alpha'+str(alphaReg)+'/rec'+filename[x]+'/rec'+filename[x], start=sinorange[0]+y*num_sino_per_substack) dxchange.write_tiff_stack(rec, fname=outputPath + 'recon_'+filename[x]+'/recon_'+filename[x], start=sinorange[0]+y*num_sino_per_substack) logging.info('Reconstruction Complete: '+ filename[x])
# Xtomo object creation and pipeline of methods. ##d = tomopy.xtomo_dataset(log='debug') ##d.dataset(data, white, dark, theta) #if perform_norm: d.normalize() # flat & dark field correction if perform_norm: data = tomopy.normalize(data, white, dark) ##if drift_correct: d.correct_drift() if drift_correct: data = tomopy.normalize_bg(data) #d.median_filter(size=medfilt_size, axis=0) # Apply a median filter in the projection plane data = tomopy.median_filter(data, size=medfilt_size, axis=0) #if remove_stripe1: d.stripe_removal(level=stripe_lvl, sigma=sig, wname=Wname) if remove_stripe1: data = tomopy.remove_stripe_fw(data, level=stripe_lvl, wname=Wname, sigma=sig) # z = 3 # eng = 31 # pxl = 0.325e-4 # rat = 5e-03 # rat = 1e-03 #d.phase_retrieval(dist=z, energy=eng, pixel_size=pxl, alpha=rat,padding=True) #data = tomopy.retrieve_phase(data, dist=z, energy=eng, pixel_size=pxl, alpha=rat,pad=True) #if remove_stripe2: d.stripe_removal2() if remove_stripe2: data = tomopy.remove_stripe_ti(data) #d.downsample2d(level=level) # apply binning on the data data = tomopy.downsample(data, level=level) # apply binning on the data theta = tomopy.angles(data.shape[0])
def main(): args = parse_arguments() context = zmq.Context() # TQM setup if args.my_distributor_addr is not None: addr_split = re.split("://|:", args.my_distributor_addr) tmq.init_tmq() # Handshake w. remote processes print(addr_split) tmq.handshake(addr_split[1], int(addr_split[2]), args.num_sinograms, args.num_columns) else: print("No distributor..") # Subscriber setup print("Subscribing to: {}".format(args.data_source_addr)) subscriber_socket = context.socket(zmq.SUB) subscriber_socket.set_hwm(args.data_source_hwm) subscriber_socket.connect(args.data_source_addr) subscriber_socket.setsockopt(zmq.SUBSCRIBE, b'') # Local publisher socket if args.my_publisher_addr is not None: publisher_socket = context.socket(zmq.PUB) publisher_socket.set_hwm(200) # XXX publisher_socket.bind(args.my_publisher_addr) if args.data_source_synch_addr is not None: synchronize_subs(context, args.data_source_synch_addr) # Setup flatbuffer builder and serializer builder = flatbuffers.Builder(0) serializer = TraceSerializer.ImageSerializer(builder) # White/dark fields white_imgs = [] tot_white_imgs = 0 dark_imgs = [] tot_dark_imgs = 0 # Receive images total_received = 0 total_size = 0 seq = 0 time0 = time.time() while True: msg = subscriber_socket.recv() total_received += 1 total_size += len(msg) if msg == b"end_data": break # End of data acquisition # This is mostly for data rate tests if args.skip_serialize: print("Skipping rest. Received msg: {}".format(total_received)) continue # Deserialize msg to image read_image = serializer.deserialize(serialized_image=msg) serializer.info(read_image) # print image information # Local checks if args.check_seq: if seq != read_image.Seq(): print("Wrong sequence number: {} != {}".format( seq, read_image.Seq())) seq += 1 # Push image to workers (REQ/REP) my_image_np = read_image.TdataAsNumpy() if args.uint8_to_float32: my_image_np.dtype = np.uint8 sub = np.array(my_image_np, dtype="float32") elif args.uint16_to_float32: my_image_np.dtype = np.uint16 sub = np.array(my_image_np, dtype="float32") else: sub = my_image_np sub = sub.reshape((1, read_image.Dims().Y(), read_image.Dims().X())) # If incoming data is projection if read_image.Itype() is serializer.ITypes.Projection: rotation = read_image.Rotation() if args.degree_to_radian: rotation = rotation * math.pi / 180. # Tomopy operations expect 3D data, reshape incoming projections. if args.normalize: # flat/dark fields' corresponding rows if tot_white_imgs > 0 and tot_dark_imgs > 0: print( "normalizing: white_imgs.shape={}; dark_imgs.shape={}". format( np.array(white_imgs).shape, np.array(dark_imgs).shape)) sub = tp.normalize(sub, flat=white_imgs, dark=dark_imgs) if args.remove_stripes: print("removing stripes") sub = tp.remove_stripe_fw(sub, level=7, wname='sym16', sigma=1, pad=True) if args.mlog: print("applying -log") sub = -np.log(sub) if args.remove_invalids: print("removing invalids") sub = tp.remove_nan(sub, val=0.0) sub = tp.remove_neg(sub, val=0.00) sub[np.where(sub == np.inf)] = 0.00 # Publish to the world if (args.my_publisher_addr is not None) and (total_received % args.my_publisher_freq == 0): builder.Reset() serializer = TraceSerializer.ImageSerializer(builder) mub = np.reshape( sub, (read_image.Dims().Y(), read_image.Dims().X())) serialized_data = serializer.serialize( image=mub, uniqueId=0, rotation=0, itype=serializer.ITypes.Projection) print("Publishing:{}".format(read_image.UniqueId())) publisher_socket.send(serialized_data) # Send to workers if args.num_sinograms is not None: sub = sub[:, args.beg_sinogram:args.beg_sinogram + args.num_sinograms, :] ncols = sub.shape[2] sub = sub.reshape(sub.shape[0] * sub.shape[1] * sub.shape[2]) if args.my_distributor_addr is not None: tmq.push_image(sub, args.num_sinograms, ncols, rotation, read_image.UniqueId(), read_image.Center()) # If incoming data is white field if read_image.Itype() is serializer.ITypes.White: #print("White field data is received: {}".format(read_image.UniqueId())) white_imgs.extend(sub) tot_white_imgs += 1 # If incoming data is white-reset if read_image.Itype() is serializer.ITypes.WhiteReset: #print("White-reset data is received: {}".format(read_image.UniqueId())) white_imgs = [] white_imgs.extend(sub) tot_white_imgs += 1 # If incoming data is dark field if read_image.Itype() is serializer.ITypes.Dark: #print("Dark data is received: {}".format(read_image.UniqueId())) dark_imgs.extend(sub) tot_dark_imgs += 1 # If incoming data is dark-reset if read_image.Itype() is serializer.ITypes.DarkReset: #print("Dark-reset data is received: {}".format(read_image.UniqueId())) dark_imgs = [] dark_imgs.extend(sub) tot_dark_imgs += 1 time1 = time.time() # Profile information elapsed_time = time1 - time0 tot_MiBs = (total_size * 1.) / 2**20 print( "Received number of projections: {}; Total size (MiB): {:.2f}; Elapsed time (s): {:.2f}" .format(total_received, tot_MiBs, elapsed_time)) print("Rate (MiB/s): {:.2f}; (msg/s): {:.2f}".format( tot_MiBs / elapsed_time, total_received / elapsed_time)) # Finalize TMQ if not args.my_distributor_addr is not None: tmq.done_image() tmq.finalize_tmq()
logging.info('Doing ring (Fourier-wavelet) function') tend = 0 total_tomo = tomo.shape[0] num_flats = len(floc) for m, loc in enumerate(floc): logging.info('fing removal secstion %d of %d',m+1,num_flats) if m==0: tstart = 0 else: tstart = tend if m >= num_flats-1: tend = total_tomo else: tend = int(np.round((floc[m+1]-loc)/2)) + loc logging.info('tsart=%d, tend=%d',tstart, tend) tomo[tstart:tend,:,:] = tomopy.remove_stripe_fw(tomo[tstart:tend,:,:], sigma=ringSigma, level=ringLevel, pad=True, wname=ringWavelet) # sinofilenametowrite = odirectory+'/rec'+iname[x]+'/'+iname[x]+'sinoBefore3680-180_' # dxchange.write_tiff_stack(tomo, fname=sinofilenametowrite, start=sinorange[0]+y*num_sino_per_chunk,axis=1) if use360to180: #logging.info('Shape of projections matrix before 360 to 180: %d, %d, %d', tomo.shape[0],tomo.shape[1],tomo.shape[2]) logging.info('overlap for 360 to 180 = %f', tomo.shape[2]-cor) if tomo.shape[0]%2>0: angularrange = angularrange/2 - angularrange/(tomo.shape[0]-1) tomo = sino_360_to_180(tomo[0:-1,:,:], overlap=int(np.round((tomo.shape[2]-cor_rec-.5))*2), rotation='right') else: angularrange = angularrange/2 tomo = sino_360_to_180(tomo[:,:,:], overlap=int(np.round((tomo.shape[2]-cor_rec))*2), rotation='right')
def recon(io_paras, data_paras, rot_center=None, normalize=True, stripe_removal=10, phase_retrieval=False, opt_center=False, diag_center=False, output="tiff"): # Input and output datafile = io_paras.get('datafile') path2white = io_paras.get('path2white', datafile) path2dark = io_paras.get('path2dark', path2white) out_dir = io_paras.get('out_dir') diag_cent_dir = io_paras.get('diag_cent_dir', out_dir+"/center_diagnose/") recon_dir = io_paras.get('recon_dir', out_dir+"/recon/") out_prefix = io_paras.get('out_prefix', "recon_") # Parameters of dataset NumCycles = data_paras.get('NumCycles', 1) # Number of cycles used for recon ProjPerCycle = data_paras.get('ProjPerCycle') # Number of projections per cycle, N_theta cycle_offset = data_paras.get('cycle_offset', 0) # Offset in output cycle number proj_start = data_paras.get('proj_start', 0) # Starting projection of reconstruction proj_step = data_paras.get('proj_step') z_start = data_paras.get('z_start', 0) z_end = data_paras.get('z_end', z_start+1) z_step = data_paras.get('z_step') x_start = data_paras.get('x_start') x_end = data_paras.get('x_end', x_start+1) x_step = data_paras.get('x_step') white_start = data_paras.get('white_start') white_end = data_paras.get('white_end') dark_start = data_paras.get('dark_start') dark_end = data_paras.get('dark_end') rot_center_copy = rot_center for cycle in xrange(NumCycles): # Set start and end of each cycle projections_start = cycle * ProjPerCycle + proj_start projections_end = projections_start + ProjPerCycle slice1 = slice(projections_start, projections_end, proj_step) slice2 = slice(z_start, z_end, z_step) slice3 = slice(x_start, x_end, x_step) slices = (slice1, slice2, slice3) white_slices = (slice(white_start, white_end), slice2, slice3) dark_slices = (slice(dark_start, dark_end), slice2, slice3) print("Running cycle #%s (projs %s to %s)" % (cycle, projections_start, projections_end)) # Read HDF5 file. print("Reading datafile %s..." % datafile, end="") sys.stdout.flush() data, white, dark = reader.read_aps_2bm(datafile, slices, white_slices, dark_slices, path2white=path2white, path2dark=path2dark) theta = gen_theta(data.shape[0]) print("Done!") print("Data shape = %s;\nwhite shape = %s;\ndark shape = %s." % (data.shape, white.shape, dark.shape)) ## Normalize dataset using data_white and data_dark if normalize: print("Normalizing data ...") # white = white.mean(axis=0).reshape(-1, *data.shape[1:]) # dark = dark.mean(axis=0).reshape(-1, *data.shape[1:]) # data = (data - dark) / (white - dark) data = tomopy.normalize(data, white, dark, cutoff=None, ncore=_ncore, nchunk=None)[...] ## Remove stripes caused by dead pixels in the detector if stripe_removal: print("Removing stripes ...") data = tomopy.remove_stripe_fw(data, level=stripe_removal, wname='db5', sigma=2, pad=True, ncore=_ncore, nchunk=None) # data = tomopy.remove_stripe_ti(data, nblock=0, alpha=1.5, # ncore=None, nchunk=None) # # Show preprocessed projection # plt.figure("%s-prep" % projections_start) # plt.imshow(d.data[0,:,:], cmap=cm.Greys_r) # plt.savefig(out_dir+"/preprocess/%s-prep.jpg" # % projections_start) # # plt.show() # continue ## Phase retrieval if phase_retrieval: print("Retrieving phase ...") data = tomopy.retrieve_phase(data, pixel_size=1e-4, dist=50, energy=20, alpha=1e-3, pad=True, ncore=_ncore, nchunk=None) ## Determine and set the center of rotation if opt_center or (rot_center == None): ### Using optimization method to automatically find the center # d.optimize_center() print("Optimizing center ...", end="") sys.stdout.flush() rot_center = tomopy.find_center(data, theta, ind=None, emission=True, init=None, tol=0.5, mask=True, ratio=1.) print("Done!") print("center = %s" % rot_center) if diag_center: ### Output the reconstruction results using a range of centers, ### and then manually find the optimal center. # d.diagnose_center() if not os.path.exists(diag_cent_dir): os.makedirs(diag_cent_dir) print("Testing centers ...", end="") sys.stdout.flush() tomopy.write_center(data, theta, dpath=diag_cent_dir, cen_range=[center_start, center_end, center_step], ind=None, emission=False, mask=False, ratio=1.) print("Done!") ## Flip odd frames if (cycle % 2): data[...] = data[...,::-1] rot_center = data.shape[-1] - rot_center_copy else: rot_center = rot_center_copy ## Reconstruction using FBP print("Running gridrec ...", end="") sys.stdout.flush() recon = tomopy.recon(data, theta, center=rot_center, emission=False, algorithm='gridrec', # num_gridx=None, num_gridy=None, filter_name='shepp', ncore=_ncore, nchunk=_nchunk) print("Done!") ## Collect background # if cycle == 0: # bg = recon # elif cycle < 4: # bg += recon # else: # recon -= bg/4. # Write to stack of TIFFs. if not os.path.exists(recon_dir): os.makedirs(recon_dir) out_fname = recon_dir+"/"+out_prefix+"t_%d" % (cycle + cycle_offset) if "hdf" in output: hdf_fname = out_fname + ".hdf5" print("Writing reconstruction output file %s..." % hdf_fname, end="") sys.stdout.flush() tomopy.write_hdf5(recon, fname=hdf_fname, gname='exchange', overwrite=False) print("Done!") if "tif" in output: tiff_fname = out_fname + ".tiff" print("Writing reconstruction tiff files %s ..." % tiff_fname, end="") sys.stdout.flush() tomopy.write_tiff_stack(recon, fname=tiff_fname, axis=0, digit=5, start=0, overwrite=False) print("Done!") if "bin" in output: bin_fname = out_fname + ".bin" print("Writing reconstruction to binary files %s..." % bin_fname, end="") sys.stdout.flush() recon.tofile(bin_fname)
def reconstruct(h5fname, sino, rot_center, binning, algorithm='gridrec'): sample_detector_distance = 31 # Propagation distance of the wavefront in cm detector_pixel_size_x = 1.17e-4 # Detector pixel size in cm (5x: 1.17e-4, 2X: 2.93e-4) monochromator_energy = 65 # Energy of incident wave in keV # used pink beam alpha = 4*1e-4 # Phase retrieval coeff. zinger_level = 800 # Zinger level for projections zinger_level_w = 1000 # Zinger level for white # Read APS 2-BM raw data. # DIMAX saves 3 files: proj, flat, dark # when loading the data set select the proj file (larger size) fname = os.path.splitext(h5fname)[0] fbase = fname.rsplit('_', 1)[0] fnum = fname.rsplit('_', 1)[1] fext = os.path.splitext(h5fname)[1] fnum_flat = str("%4.4d" % (int(fnum)+1)) fnum_dark = str("%4.4d" % (int(fnum)+2)) fnproj = fbase + '_' + fnum + fext fnflat = fbase + '_' + fnum_flat + fext fndark = fbase + '_' + fnum_dark + fext print('proj', fnproj) print('flat', fnflat) print('dark', fndark) # Read APS 2-BM DIMAX raw data. proj, dum, dum2, theta = dxchange.read_aps_32id(fnproj, sino=sino) dum3, flat, dum4, dum5 = dxchange.read_aps_32id(fnflat, sino=sino) #flat, dum3, dum4, dum5 = dxchange.read_aps_32id(fnflat, sino=sino) dum6, dum7, dark, dum8 = dxchange.read_aps_32id(fndark, sino=sino) # Flat-field correction of raw data. data = tomopy.normalize(proj, flat, dark, cutoff=1.4) # remove stripes data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) # zinger_removal proj = tomopy.misc.corr.remove_outlier(proj, zinger_level, size=15, axis=0) flat = tomopy.misc.corr.remove_outlier(flat, zinger_level_w, size=15, axis=0) # Flat-field correction of raw data. ##data = tomopy.normalize(proj, flat, dark, cutoff=0.8) data = tomopy.normalize(proj, flat, dark) # remove stripes #data = tomopy.remove_stripe_fw(data,level=7,wname='sym16',sigma=1,pad=True) #data = tomopy.remove_stripe_ti(data, alpha=1.5) data = tomopy.remove_stripe_sf(data, size=150) # phase retrieval #data = tomopy.prep.phase.retrieve_phase(data,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) print("Raw data: ", h5fname) print("Center: ", rot_center) data = tomopy.minus_log(data) data = tomopy.remove_nan(data, val=0.0) data = tomopy.remove_neg(data, val=0.00) data[np.where(data == np.inf)] = 0.00 rot_center = rot_center/np.power(2, float(binning)) data = tomopy.downsample(data, level=binning) data = tomopy.downsample(data, level=binning, axis=1) # padding N = data.shape[2] data_pad = np.zeros([data.shape[0],data.shape[1],3*N//2],dtype = "float32") data_pad[:,:,N//4:5*N//4] = data data_pad[:,:,0:N//4] = np.tile(np.reshape(data[:,:,0],[data.shape[0],data.shape[1],1]),(1,1,N//4)) data_pad[:,:,5*N//4:] = np.tile(np.reshape(data[:,:,-1],[data.shape[0],data.shape[1],1]),(1,1,N//4)) data = data_pad rot_center = rot_center+N//4 nframes = 8 nproj = 1500 theta = np.linspace(0, np.pi*nframes, nproj*nframes, endpoint=False) rec = np.zeros( (nframes, data.shape[1], data.shape[2], data.shape[2]), dtype='float32') for time_frame in range(0, nframes): rec0 = tomopy.recon(data[time_frame*nproj:(time_frame+1)*nproj], theta[time_frame*nproj:( time_frame+1)*nproj], center=rot_center, algorithm='gridrec') # Mask each reconstructed slice with a circle. rec[time_frame] = tomopy.circ_mask(rec0, axis=0, ratio=0.95) rec = rec[:,:,N//4:5*N//4,N//4:5*N//4] print("Algorithm: ", algorithm) return rec
def fast_tomo_recon(argv): """ Reconstruct subset slices (sinograms) equally spaced within tomographic dataset """ logger = logging.getLogger("fast_tomopy.fast_tomo_recon") # Parse arguments passed to function parser = argparse.ArgumentParser() parser.add_argument("-i", "--input", type=str, help="path to input raw " "dataset", required=True) parser.add_argument( "-o", "--output-file", type=str, help="full path to h5 output " "file", default=os.path.join(os.getcwd(), "fast-tomopy.h5"), ) parser.add_argument("-sn", "--sino-num", type=int, help="Number of slices " "to reconstruct", default=5) parser.add_argument( "-a", "--algorithm", type=str, help="Reconstruction" " algorithm", default="gridrec", choices=[ "art", "bart", "fbp", "gridrec", "mlem", "ospml_hybrid", "ospml_quad", "pml_hybrid", "pml_quad", "sirt", ], ) parser.add_argument("-c", "--center", type=float, help="Center of rotation", default=None) parser.add_argument( "-fn", "--filter-name", type=str, help="Name of filter" " used for reconstruction", choices=["none", "shepp", "cosine", "hann", "hamming", "ramlak", "parzen", "butterworth"], default="butterworth", ) parser.add_argument( "-rr", "--ring-remove", type=str, help="Ring removal " "method", choices=["Octopus", "Tomopy-FW", "Tomopy-T"], default="Tomopy-T", ) parser.add_argument("-lf", "--log-file", type=str, help="log file name", default="fast-tomopy.log") args = parser.parse_args() fh = logging.FileHandler(args.log_file) fh.setLevel(logging.INFO) fh.setFormatter(formatter) logger.addHandler(fh) if os.path.isdir(os.path.dirname(args.output_file)) is False: raise IOError(2, "Directory of output file does not exist", args.output_file) # Read file metadata logger.info("Reading input file metadata") fdata, gdata = read_als_832h5_metadata(args.input) proj_total = int(gdata["nangles"]) last = proj_total - 1 sino_total = int(gdata["nslices"]) ray_total = int(gdata["nrays"]) px_size = float(gdata["pxsize"]) / 10 # cm # Set parameters for sinograms to read step = sino_total // (args.sino_num + 2) start = step end = step * (args.sino_num + 1) sino = (start, end, step) # Read full first and last projection to determine center of rotation if args.center is None: logger.info("Reading full first and last projection for COR") first_last, flats, darks, floc = tomopy.read_als_832h5(args.input, ind_tomo=(0, last)) first_last = tomopy.normalize(first_last, flats, darks) args.center = tomopy.find_center_pc(first_last[0, :, :], first_last[1, :, :], tol=0.1) logger.info("Detected center: %f", args.center) # Read and normalize raw sinograms logger.info("Reading raw data") tomo, flats, darks, floc = tomopy.read_als_832h5(args.input, sino=sino) logger.info("Normalizing raw data") tomo = tomopy.normalize_nf(tomo, flats, darks, floc) # Remove stripes from sinograms (remove rings) logger.info("Preprocessing normalized data") if args.ring_remove == "Tomopy-FW": logger.info("Removing stripes from sinograms with %s", args.ring_remove) tomo = tomopy.remove_stripe_fw(tomo) elif args.ring_remove == "Tomopy-T": logger.info("Removing stripes from sinograms with %s", args.ring_remove) tomo = tomopy.remove_stripe_ti(tomo) # Pad sinograms with edge values npad = int(np.ceil(ray_total * np.sqrt(2)) - ray_total) // 2 tomo = tomopy.pad(tomo, 2, npad=npad, mode="edge") args.center += npad # account for padding filter_name = np.array(args.filter_name, dtype=(str, 16)) theta = tomopy.angles(proj_total, 270, 90) logger.info("Reconstructing normalized data") # Reconstruct sinograms # rec = tomopy.minus_log(tomo, out=tomo) rec = tomopy.recon( tomo, theta, center=args.center, emission=False, algorithm=args.algorithm, filter_name=filter_name ) rec = tomopy.circ_mask(rec[:, npad:-npad, npad:-npad], 0) rec = rec / px_size # Remove rings from reconstruction if args.ring_remove == "Octopus": logger.info("Removing rings from reconstructions with %s", args.ring_remove) thresh = float(gdata["ring_threshold"]) thresh_max = float(gdata["upp_ring_value"]) thresh_min = float(gdata["low_ring_value"]) theta_min = int(gdata["max_arc_length"]) rwidth = int(gdata["max_ring_size"]) rec = tomopy.remove_rings( rec, center_x=args.center, thresh=thresh, thresh_max=thresh_max, thresh_min=thresh_min, theta_min=theta_min, rwidth=rwidth, ) # Write reconstruction data to new hdf5 file fdata["stage"] = "fast-tomopy" fdata["stage_flow"] = "/raw/" + fdata["stage"] fdata["stage_version"] = "fast-tomopy-0.1" # Generate a new uuid based on host ID and current time fdata["uuid"] = str(uuid.uuid1()) gdata["Reconstruction_Type"] = "tomopy-gridrec" gdata["ring_removal_method"] = args.ring_remove gdata["rfilter"] = args.filter_name logger.info("Writing reconstructed data to h5 file") write_als_832h5(rec, args.input, fdata, gdata, args.output_file, step) return
def main(): parser = argparse.ArgumentParser() inputs = bl832inputs_parser(parser) num_slice = inputs['z_numElts'] num_angles = inputs['num_views'] / inputs['view_subsmpl_fact'] oversamp_factor = 1.25 pad_size = np.int16(inputs['x_width'] * oversamp_factor) fbp_filter_param = inputs['fbp_filter_param'] nufft_scaling = (np.pi / pad_size)**2 algorithm = 'gridrec' tomo, flats, darks, floc = tomopy.read_als_832h5( inputs['input_hdf5'], ind_tomo=range(1, inputs['num_views'] + 1, inputs['view_subsmpl_fact']), sino=(inputs['z_start'], inputs['z_start'] + inputs['z_numElts'], 1)) print('Data read complete') print('Displaying sinogram') #imgplot = plt.imshow(tomo[:,0,:]) print('Generating angles') theta = tomopy.angles(num_angles) #Need to modify to return the raw counts for noise estimation print('Normalization') tomo, weight = normalize_bo(tomo, flats, darks, inputs['num_dark']) print('Ring removal') tomo = tomopy.remove_stripe_fw(tomo) # fig = plt.figure() # plt.imshow(tomo[:,1,:],cmap=plt.cm.Greys_r) # fig.suptitle('Sinogram') ################## GPU gridrec() ###################### input_params = {} input_params['gpu_device'] = inputs['gpu_device'] input_params['fbp_filter_param'] = inputs['fbp_filter_param'] input_params['oversamp_factor'] = oversamp_factor t = time.time() rec_nufft_final = gpuGridrec(tomo, theta, inputs['rot_center'], input_params) elapsed_time = time.time() - t print('Time for NUFFT Gridrec of %d slices : %f' % (num_slice, elapsed_time)) pg.image(rec_nufft_final) pg.QtGui.QApplication.exec_() # np.save('/home/svvenkatakrishnan/results/gridrec_notch1080_70slice',rec_nufft_final) ##################TomoPy Recon##################### # print('Recon - tomopy GridRec') # t=time.time() # rec_tomopy = tomopy.recon(tomo, theta, center=inputs['rot_center'],algorithm=algorithm)#emission=False) # elapsed_time = (time.time()-t) # print('Time for reconstucting using Tomopy GridRec of %d slices : %f' % (num_slice,elapsed_time)) # print('Recon - tomopy Astra') # t=time.time() # options = {'proj_type':'cuda', 'method':'FBP_CUDA'} # rec_astra = tomopy.recon(tomo, theta, center=inputs['rot_center'], algorithm=tomopy.astra, options=options) # elapsed_time = (time.time()-t) # print('Time for reconstucting using Tomopy Astra of %d slices : %f' % (num_slice,elapsed_time)) # fig = plt.figure() # plt.imshow(np.abs(np.flipud(rec_tomopy[0])),cmap=plt.cm.Greys_r) # plt.colorbar() # fig.suptitle('Tomopy Gridrec Reconstruction') # fig = plt.figure() # plt.imshow(rec_nufft[0].real,cmap=plt.cm.Greys_r) # plt.colorbar() # fig.suptitle('GPU NUFFT Reconstruction') print 'main: Done!'