def srxfftomo_findcenter(corrected_proj_tiff=None, proj=None, save_find_center=True, autocheck=False, check_cen_range_step=[390, 410, 1], auto_selecslice=True, cen_slice=400, outpath=None, samplename=None, starting_angle=0, last_angle=180): ''' input needs to be either 1) corrected_proj_tiff, provided as a file path and name, e.g. '/home/xf05id1/localdata/TomoCommissioning/testsample_01/testsample_01_corrected.tiff' it is a stack of tiff generated by srxfftomo_correction, where background and stage round out have been corrected 2) projection numpy array, returned from srxfftomo_correction The 'proj' array assignment has priority. If it is None, proj was be read from corrected_proj_tiff input example: check_cen_range_step = [390, 410, 1] cen_slice = 400 return: proj (numpy array, float), with negative natural log has been taken ''' if proj is None: print('proj is not asigned, load corrected projection from:', corrected_proj_tiff) proj = tifffile.imread(corrected_proj_tiff) else: print('proj array is not None, use it as is') if save_find_center is True: center_check_path = outpath + '/' + samplename + '/center_check/' print('saving find center value into ' + center_check_path) theta = tomopy.angles(proj.shape[0], ang1=starting_angle, ang2=last_angle) if autocheck is True: check_cen_range_step = [ int(proj.shape[2] / 2) - 50, int(proj.shape[2]) / 2 + 50, 5 ] if auto_selecslice is True: cen_slice = int(proj.shape[1] / 2) tomopy.write_center(proj, theta, center_check_path, cen_range=check_cen_range_step, ind=cen_slice, mask=True) return proj
def reconstruct( self, ct_series, workdir=None, outdir=None, rot_center=None, explore_rot_center=True): workdir = workdir or self.workdir; outdir = outdir or self.outdir theta = self.theta # preprocess angles, sinograms = i3.build_sinograms( ct_series, workdir=os.path.join(workdir, 'sinogram'), parallel = self.parallel_preprocessing, parallel_nodes = self.parallel_nodes) # take the middle part to calculate the center of rotation NSINO = len(sinograms) sino = [s.data for s in sinograms[NSINO//3: NSINO*2//3]] # sino = [s.data for s in sinograms] sino= np.array(sino) proj = np.swapaxes(sino, 0, 1) import tomopy X = proj.shape[-1] DEVIATION = 40 # max deviation of rot center from center of image if explore_rot_center: print("* Exploring rotation center using tomopy...") tomopy.write_center( proj.copy(), theta, cen_range=[X//2-DEVIATION, X//2+DEVIATION, 1.], dpath=os.path.join(workdir, 'tomopy-findcenter'), emission=False) if rot_center is None: print("* Computing rotation center using 180deg pairs...") from .tilt import find_rot_center rot_center = find_rot_center.find( ct_series, workdir=os.path.join(workdir, 'find-rot-center')) print('* Rotation center: %s' % rot_center) open(os.path.join(workdir, 'rot_center'), 'wt').write(str(rot_center)) # reconstruct if self.vertical_range: sinograms = sinograms[self.vertical_range] recon = i3.reconstruct( angles, sinograms, workdir=outdir, center=rot_center, nodes=self.parallel_nodes) return
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 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!")
print proj.shape theta = np.arange(0.0, 181.9 + step, step) print(theta) theta *= np.pi / 180. # calculate rotation center print "* finding center ..." rot_center = tomopy.find_center(proj, theta, emission=False, init=1024, tol=0.5) print " done." print("Center of rotation: ", rot_center) # checking print proj.shape tomopy.write_center(proj.copy(), theta, dpath='center', emission=False) # rot_center = tomopy.find_center_vo(proj.copy()) # print("Center of rotation: ", rot_center) # plot data # print "* normalizing bg ..." # proj = tomopy.normalize_bg(data) # print " done." # plot an image fig, ax = plt.subplots() im = plt.imshow(data[0], cmap='gray') #, vmin=0.2, vmax=1.2 fig.colorbar(im) # plot a projection fig, ax = plt.subplots() im = plt.imshow(proj[:, 1000, :], cmap='gray') fig.colorbar(im)
# Select sinogram range to reconstruct. sino = None start = 1000 end = 1001 sino = (start, end) # Read APS 2-BM raw data. if (int(key) > 6): proj, flat, dark, theta = read_aps_2bm_custom(fname, sino=sino) else: proj, flat, dark, theta = dxchange.read_aps_2bm(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) print(h5name, rot_center) data = tomopy.minus_log(data) # find center fname = top + 'try_center/' + prefix + h5name + '/recon' center_shift_w = 10 cen_range = (rot_center-center_shift_w, rot_center+center_shift_w, 0.5) tomopy.write_center(data, theta, fname, cen_range)
print "* normalizing ..." proj = tomopy.normalize(data, ob_data, df_data) print " done." # checking print proj.shape theta = np.arange(0.0, 181.9+step, step) print(theta) theta *= np.pi/180. # calculate rotation center print "* finding center ..." rot_center = tomopy.find_center(proj, theta, emission=False, init=1024, tol=0.5) print " done." print("Center of rotation: ", rot_center) # checking print proj.shape tomopy.write_center(proj.copy(), theta, dpath='center', emission=False) # rot_center = tomopy.find_center_vo(proj.copy()) # print("Center of rotation: ", rot_center) # plot data # print "* normalizing bg ..." # proj = tomopy.normalize_bg(data) # print " done." # plot an image fig, ax = plt.subplots() im = plt.imshow(data[0], cmap='gray') #, vmin=0.2, vmax=1.2 fig.colorbar(im) # plot a projection fig, ax = plt.subplots() im = plt.imshow(proj[:, 1000, :], cmap='gray') fig.colorbar(im)
proj = tomopy.minus_log(proj) logger.info('logarithmized proj') ################################ # Rotation center rcen = False auto_rcen = True manual_rcen = False if manual_rcen: # find rotation center manually by varying the rcen and writing back to file. Exits script when done. rcen_range = [754, 764, 0.1] tomopy.write_center(proj, theta, dpath=recodir + 'tmp/center', cen_range=rcen_range) logger.info( 'Reconstructed with varying rotation center from %g to %g in %g steps.' % (rcen_range[0], rcen_range[1], rcen_range[2])) raise SystemExit(0) if auto_rcen: rcen_tol = 0.08 logger.info('determine rotation center with tolerance: %g' % rcen_tol) rcen = tomopy.find_center(proj, theta, tol=rcen_tol) logger.info('found rotation center at %g px' % rcen) if rcen - proj.shape[2] > 20: logger.warning( 'rotation center more than 20px from projection center.')
# phase retrieval #data = tomopy.prep.phase.retrieve_phase(prj,pixel_size=detector_pixel_size_x,dist=sample_detector_distance,energy=monochromator_energy,alpha=alpha,pad=True) prj = tomopy.median_filter(prj,size=medfilt_size) print('\n** Median filter done!') if debug: print('## Debug: after nedian filter:') print('\n** Min and max val in prj before recon: %0.5f, %0.3f' % (np.min(prj), np.max(prj))) if level>0: prj = tomopy.downsample(prj, level=level) print('\n** Down sampling done!\n') if debug: print('## Debug: after down sampling:') print('\n** Min and max val in prj before recon: %0.5f, %0.3f' % (np.min(prj), np.max(prj))) if auto_center == False: tomopy.write_center(prj,theta,dpath=output_path,cen_range=[Center_st/pow(2,level),Center_end/pow(2,level),((Center_end - Center_st)/float(N_recon))/pow(2,level)]) else: rot_axis = tomopy.find_center_vo(prj) rot_axis = rot_axis * pow(2,level) print('*** Rotation center: %0.2f' % rot_axis) rec = tomopy.recon(prj, theta, center=rot_axis/pow(2,level), algorithm='gridrec', filter_name='parzen') rec=np.squeeze(rec) plt.figure() plt.imshow(rec, cmap='gray', aspect="auto", interpolation='none') plt.colorbar(), plt.title('Rotation center: %0.2f' % rot_axis), plt.show()
def do_work(out_path, scan_id, center_offset, mpi_projs, flats, darks, mpi_thetas): logger.info("Flat Field Correction") mpi_projs = normalize_mpi(mpi_projs, flats, darks) #utils_mpi.write_stack_mpi(out_path/"flat", mpi_projs) del flats del darks logger.info("Outlier Removal") # TODO: base parameters on clean simulation data! - might need fill projs = mpi_projs.scatter(0) # TODO: put back in, I think it is causing issues right now... tomopy.remove_outlier(projs, 0.1, 5, ncore=ncore, out=projs) #tomopy.remove_outlier_cuda(projs, 0.1, 5, ncore, out=projs) np.clip(projs, 1E-6, 1 - 1E-6, projs) # TODO: distortion correction factor? # TODO: ring removal? # # flat field change correction # remove_low_frequency_mpi(mpi_projs) # utils_mpi.write_stack_mpi(out_path/"low_frequency_removed", mpi_projs) # bulk Si intensity correction # removes constant absorption contribution from bulk Si, and mounting material # TODO: base parameters on clean simulation data! - will need fill # TODO: alternatively, refine result after good recon - with theta offset target_transmission = 0.80 logger.info(f"Setting target transmission to {target_transmission}") set_target_transmission_mpi(mpi_projs, mpi_thetas, target_transmission) projs = mpi_projs.scatter(0) np.clip(projs, 1E-6, 1 - 1E-6, projs) utils_mpi.write_stack_mpi(out_path / "constant_transmission", mpi_projs) # center finding - manual for now? if center_offset is None: logger.info("Finding center") # algorithm = "SART" # pixel_size = 2 * 0.000016 #16nm bin 1 # options = {"PixelWidth": pixel_size, # "PixelHeight": pixel_size, # "windowFOV": False, # "archDir": out_path, # "_mpi_rank": mpi_rank, # } # alg_params = {"N_iter": 1, # "N_subsets": 20, # "nonnegativityConstraint": True, # "useFBPasSeedImage": False, # # "Preconditioner": "RAMP", # # "beta": 2e-7, # # "p": 1, # # "delta": 1/20, # delta sets edge strength (difference between regions divide by ten) # # "inverseVarianceExponent": 1.0, # set to 1 to include noise model # # "other": 3, #convergence of low frequencies # } # # load data into LTT, then find the center before recon # ltt_tomopy.initialize_recon(sinos, thetas, xcenter, True, algorithm, options, ncore=ncore) # center = align_tomo.find_center_ltt(lambda c: ltt_tomopy.preview(center=c, algorithm=algorithm, sinogram_order=True, close=False, options=options, alg_params=alg_params, ncore=ncore), xcenter, 0.1, ratio=0.8) # ltt_tomopy.recon_close() logger.info("Padding sinos for center finding") mpi_sinos = utils_mpi.create_sinos_mpi(mpi_projs, ncore) sinos = mpi_sinos.scatter(0) sinos = pad_sinos(sinos) mpi_sinos = MpiArray(sinos) gthetas = mpi_thetas.allgather() xcenter = sinos.shape[2] // 2 cen_range = (xcenter - 20, xcenter + 20, 0.5) if mpi_rank == mpi_size // 2: tomopy.write_center(sinos, gthetas, out_path / ("center"), cen_range, sinogram_order=True) del mpi_sinos, sinos import sys comm.Barrier() sys.exit() # center_offset = mpi_projs.shape[2]//2-center # mpi_projs.comm.Barrier() #for printing # print(f"{mpi_projs.mpi_rank}: center={center} offset={center_offset}") #center = xcenter + center_offset # Shift correction? # use MPI and binning for speed # use LTT for all recon # define recon extent with extra X and less Z # Quick recon - LTT with SART or other? (can't use FBP) algorithm = "gridrec" options = { "filter_name": "parzen", } logger.info(f"Finding layer alignment within volume using {algorithm}") mpi_rec = tomopy_recon_mpi(mpi_projs, mpi_thetas, center_offset, algorithm, ncore=ncore, **options) utils_mpi.write_stack_mpi(out_path / ("quick_" + algorithm), mpi_rec) theta_deg, start_z1, end_z1 = align_layers.find_angle_mpi(mpi_rec, 0) logger.info(f"Theta offset angle {theta_deg:0.2} deg") # find phi angle (axis 2) phi_deg, start_z2, end_z2 = align_layers.find_angle_mpi(mpi_rec, 2) logger.info(f"Phi offset angle {phi_deg:0.2} deg") start_z = min(start_z1, start_z2) end_z = max(end_z1, end_z2) # add buffer for start and end start_z = max(start_z - 20, 0) end_z = min(end_z + 20, mpi_rec.shape[1] - 1) #FIXME: override start and end start_z = 0 end_z = mpi_rec.shape[1] - 1 logger.info(f"Layer extent: {start_z} - {end_z}") # change theta with correction for next reconstruction thetas = mpi_thetas.scatter(0) thetas += np.deg2rad(theta_deg) # modify projections to remove phi angle # TODO: combine with stage shift code projs = mpi_projs.scatter(0) align_layers.apply_phi_correction(projs, thetas, phi_deg, projs) # Quick aligned recon algorithm = "gridrec" options = { "filter_name": "parzen", } logger.info("Quick Tomopy Recon") mpi_rec = tomopy_recon_mpi(mpi_projs, mpi_thetas, center_offset, algorithm, ncore=ncore, **options) rec = mpi_rec.scatter(0) rec = rec[:, start_z:end_z, :] mpi_rec = MpiArray(rec) utils_mpi.write_stack_mpi(out_path / algorithm, mpi_rec) del mpi_rec, rec # Aligned recon # iterative recon with extra recon space in X and a restricted Z axis algorithm = "SART" #"RDLS"#"DFM"#"ASD-POCS"#"SART"#"FBP" logger.info(f"Reconstructing aligned layers using {algorithm}") mpi_sinos = utils_mpi.create_sinos_mpi(mpi_projs, ncore) #utils_mpi.write_stack_mpi(out_path/"sinos", mpi_sinos) sinos = mpi_sinos.scatter(0) # add padding to recon - fixes cupping effect xrecpadding = sinos.shape[2] // 2 pixel_size = 2 * 0.000016 # 16nm bin 1 options = { "PixelWidth": pixel_size, "PixelHeight": pixel_size, "ryoffset": start_z, "ryelements": end_z - start_z, "windowFOV": False, "rxelements": sinos.shape[2] + 2 * xrecpadding, "rxoffset": -xrecpadding, "_mpi_rank": mpi_rank, } alg_params = { "N_iter": 50, "nonnegativityConstraint": False, "useFBPasSeedImage": False, #"Preconditioner": "RAMP", #"descentType": "CG",#"GD", #"beta": 2e-7, #"p": 1, #"delta": 20/20, # delta sets edge strength (difference between regions divide by ten) #"inverseVarianceExponent": 1.0, # set to 1 to include noise model #"other": 3, #convergence of low frequencies } #TODO: add support to add overlap in future with updates between iterations (see xray_trust6.py) gthetas = mpi_thetas.allgather() #global thetas center = sinos.shape[2] // 2 + center_offset if gthetas[1] < gthetas[0]: # decreasing angle, LTT doesn't support, switch data around # TODO: load in reversed order? gthetas = gthetas[::-1] sinos[:] = sinos[:, ::-1, :] rec = ltt_tomopy.recon(sinos, gthetas, center, True, algorithm, alg_params, options, ncore=ncore) rec = rec[:, :, xrecpadding:xrecpadding + sinos.shape[2]] mpi_rec = MpiArray(rec, distribution=mpi_sinos.distribution) utils_mpi.write_stack_mpi(out_path / algorithm, mpi_rec) # Neural network processing? # Extract layers # Use template if available logger.info("Extracting Layers") mpi_layers = align_layers.extract_layers_mpi(mpi_rec) align_layers.write_layers_to_file_mpi(mpi_layers, "layers") logger.info(f"Finished {scan_id}")
# Read APS 2-BM raw data. if (int(key) > 6): proj, flat, dark, theta = read_aps_2bm_custom(fname, sino=sino) else: proj, flat, dark, theta = dxchange.read_aps_2bm(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) print(h5name, rot_center) data = tomopy.minus_log(data) # find center fname = top + 'try_center/' + prefix + h5name + '/recon' center_shift_w = 10 cen_range = (rot_center - center_shift_w, rot_center + center_shift_w, 0.5) tomopy.write_center(data, theta, fname, cen_range)
def recon3(io_paras, data_paras, rot_center=None, normalize=True, stripe_removal=10, stripe_sigma=2, phase_retrieval=False, opt_center=False, diag_center=False, output="tiff", z_recon_size=None): # 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') # TIMBIR parameters NumSubCycles = data_paras.get('NumSubCycles', 1) # Number of subcycles in one cycle, K SlewSpeed = data_paras.get('SlewSpeed', 0) # In deg/s MinAcqTime = data_paras.get('MinAcqTime', 0) # In s TotalNumCycles = data_paras.get( 'TotalNumCycles', 1) # Total number of cycles in the full scan data ProjPerRecon = data_paras.get( 'ProjPerRecon', ProjPerCycle) # Number of projections per reconstruction # Calculate thetas for interlaced scan theta = gen_theta_timbir(NumSubCycles, ProjPerCycle, SlewSpeed, MinAcqTime, TotalNumCycles) if ProjPerRecon is None: ProjPerCycle = theta.size // TotalNumCycles else: ProjPerCycle = ProjPerRecon print("Will use %s projections per reconstruction." % ProjPerCycle) # Distribute z slices to processes if z_step is None: z_step = 1 z_pool = get_pool(z_start, z_end, z_step, z_chunk_size=z_recon_size, fmt='slice') slice3 = slice(x_start, x_end, x_step) 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) # Setup continuous output if "cont" in output: if not os.path.exists(recon_dir): os.makedirs(recon_dir) cont_fname = recon_dir+"/"+out_prefix+"t_%d_z_%d_%d.bin" \ % (cycle + cycle_offset, z_start, z_end) cont_file = file(cont_fname, 'wb') # Distribute z slices to processes for i in range(_rank, len(z_pool), _nprocs): slice2 = z_pool[i] 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, z = %s - %s) on process %s of %s" % (cycle, projections_start, projections_end, slice2.start, slice2.stop, _rank, _nprocs)) # 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) # data += 1 # theta = gen_theta(data.shape[0]) print("Done!") print("Data shape = %s;\nwhite shape = %s;\ndark shape = %s." % (data.shape, white.shape, dark.shape)) # data = tomopy.focus_region(data, dia=1560, xcoord=1150, ycoord=1080, # center=rot_center, pad=False, corr=True) # rot_center = None # 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=_nchunk)[...] ## 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=stripe_sigma, pad=True, ncore=_ncore, nchunk=_nchunk) # 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=1.1e-4, dist=6, energy=25.7, alpha=1e-2, pad=True, ncore=_ncore, nchunk=_nchunk) ## 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[slice1], 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_z_" % ( cycle + cycle_offset) if "hdf" in output: hdf_fname = out_fname + "%d_%d.hdf5" % (slice2.start, slice2.stop) 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: if "stack" in output: # single stacked file for multiple z tiff_fname = out_fname + "%d_%d.tiff" % (slice2.start, slice2.stop) print("Writing reconstruction tiff files %s ..." % tiff_fname, end="") sys.stdout.flush() tomopy.write_tiff(recon, fname=tiff_fname, overwrite=False) print("Done!") else: # separate files for different z for iz, z in enumerate( range(slice2.start, slice2.stop, slice2.step)): tiff_fname = out_fname + "%d.tiff" % z print("Writing reconstruction tiff files %s ..." % tiff_fname, end="") sys.stdout.flush() tomopy.write_tiff(recon[iz], fname=tiff_fname, overwrite=False) print("Done!") if "bin" in output: bin_fname = out_fname + "%d_%d.bin" % (slice2.start, slice2.stop) print("Writing reconstruction to binary files %s..." % bin_fname, end="") sys.stdout.flush() recon.tofile(bin_fname) if "cont" in output: print("Writing reconstruction to binary files %s..." % cont_fname, end="") sys.stdout.flush() recon.tofile(cont_file) print("Done!") if "cont" in output: cont_file.close() if _usempi: comm.Barrier() if _rank == 0: print("All done!")
# # recon apply_shifts(projs, shifts, out=projs) shifted_projs = projs #change name after shifts del projs write_stack("shifted_projs", shifted_projs) sinos = tomopy.init_tomo(shifted_projs, sinogram_order=False, sharedmem=False) tomopy.minus_log(sinos, out=sinos) # logger.info("Finding center of rotation") xcenter = sinos.shape[2] // 2 center = xcenter if center_offset is not None: center = xcenter + center_offset else: tomopy.write_center(sinos, thetas, "xcenter", (xcenter - 50, xcenter + 50, 1), sinogram_order=True) #center = tomopy.find_center(sinos, thetas, tol=0.1, mask=True, ratio=0.8, sinogram_order=True, algorithm="sirt", num_iter=10) #tomopy.write_center(sinos, thetas, "center", (center - 20, center + 20, 0.5), sinogram_order=True, algorithm="sirt", num_iter=10) logger.info(f"center: {center:0.2f}") # for flat samples, align recon to surface if align_flat_sample: # Theta angle correction, do another recon to get better data afterwards! alg = "FBP" logger.info(f"Correcting theta using recon with {alg}") options = {"PixelWidth": pixel_size, "PixelHeight": pixel_size, "loggingLevel": "logDEBUG", } alg_params = {"extrapolate": True,
def calib(cal_indir, cal_infn, center_check_path=None, use_cal_indir_as_center_check_path=True, hist_threshold=1.5, max_threshold=10): ''' max_threshold: larger then this value, set img(x,y) = 0.001 to avoid numerical errors ''' plt.ion() #cal_indir = '/nfs/xf05id1/data/beamlineData/fullfield_comissioning/pintest_run1_361proj/' #cal_indir = '/home/xf05id1/localdata/TomoCommissioning/pintest_run1_361proj/' #cal_infn = 'pintest_run1_361proj_norm.tif' #cal_infn = 'pintest_run3_1441proj_norm.tif' cal_infile = cal_indir + cal_infn img = imread(cal_infile) img = (-1) * np.log(img) # #plt.figure() #plt.plot(cen[:,1]) sino = img[:, 400, :] #plt.plot(range(sino.shape[1]), sino[0, :]) plt.figure() plt.imshow(sino) plt.show() img = tomopy.misc.corr.remove_nan(img, val=0.001) img[img > max_threshold] = 0.001 #plot histogram hist, bin_edges = np.histogram(img, bins=120, range=(-2.0, 4.0)) bin_centers = 0.5 * (bin_edges[:-1] + bin_edges[1:]) plt.figure() plt.plot(bin_centers, hist) #segment the image by threshold = hist_threshold binary_img = img > hist_threshold plt.figure() plt.imshow(img[0, :, :]) plt.figure() plt.imshow(binary_img[0, :, :]) cen = np.array([ ndimage.measurements.center_of_mass(binary_img[i, :, :]) for i in range(binary_img.shape[0]) ]) if use_cal_indir_as_center_check_path is True: center_check_path = cal_indir if center_check_path is not None: print('shifting images....') img_shift_xonlyseg = np.array([ shift(img[i, :, :], [0, cen[:, 1].mean() - cen[i, 1]]) for i in range(img.shape[0]) ]) sino_shift_xonlyseg = img_shift_xonlyseg[:, 400, :] plt.figure() plt.imshow(sino_shift_xonlyseg) plt.show() theta = tomopy.angles(binary_img.shape[0]) tomopy.write_center(img_shift_xonlyseg, theta, center_check_path, cen_range=[390, 410, 1], ind=400, mask=True) f = open('cen_seg_x.txt', 'w') for i in cen: f.write(str(i[1]) + '\n') f.close() return img, cen, img_shift_xonlyseg
def reconstruct( self, ct_series, workdir=None, outdir=None, rot_center=None, explore_rot_center=True, outfilename_template=None, remove_rings_at_sinograms=False, mirror=True, **kwds): workdir = workdir or self.workdir; outdir = outdir or self.outdir theta = self.theta # preprocess angles, sinograms = i3.build_sinograms( ct_series, workdir=os.path.join(workdir, 'sinogram'), parallel = self.parallel_preprocessing, parallel_nodes = self.parallel_nodes) # take the middle part to calculate the center of rotation NSINO = len(sinograms) sino = [s.data for s in sinograms[NSINO//3: NSINO*2//3]] # sino = [s.data for s in sinograms] sino= np.array(sino) proj = np.swapaxes(sino, 0, 1) import tomopy X = proj.shape[-1] DEVIATION = 40 # max deviation of rot center from center of image if explore_rot_center: print("* Exploring rotation center using tomopy...") dpath=os.path.join(workdir, 'tomopy-findcenter') if not os.path.exists(dpath): # skip if already done tomopy.write_center( proj.copy(), theta, cen_range=[X//2-DEVIATION, X//2+DEVIATION, 1.], dpath=dpath, emission=False) if rot_center is None: print("* Computing rotation center using 180deg pairs...") from .tilt import find_rot_center rot_center = find_rot_center.find( ct_series, workdir=os.path.join(workdir, 'find-rot-center')) print('* Rotation center: %s' % rot_center) self.rot_center = rot_center open(os.path.join(workdir, 'rot_center'), 'wt').write(str(rot_center)) # reconstruct if self.vertical_range: sinograms = sinograms[self.vertical_range] self.r.sinograms = sinograms # sometimes the rotation angles and the stacking sequence coulb be not in the right convention if mirror: angles = -np.array(angles) # reconstruct using original sinograms recon = i3.reconstruct( angles, sinograms, workdir=outdir, filename_template=outfilename_template, center=rot_center, nodes=self.parallel_nodes, **kwds) self.r.reconstructed = recon # reconstruct using rar filtered sinograms if remove_rings_at_sinograms: if remove_rings_at_sinograms is True: remove_rings_at_sinograms = {} self.r.rar_sino = sinograms = i3.ring_artifact_removal_Ketcham( sinograms, workdir=os.path.join(workdir, 'rar_sinograms'), parallel = self.parallel_preprocessing, **remove_rings_at_sinograms) recon = i3.reconstruct( angles, sinograms, workdir=os.path.join(outdir, 'rar_sinograms'), filename_template=outfilename_template, center=rot_center, nodes=self.parallel_nodes, **kwds) self.r.reconstructed_using_rar_sinograms = recon return recon