def get_tilted_sinogram(fname, target_slice, tilt, preprocess_data=True): """ Get a sinogram that is tilted about the theta-axis from the specified dataset. The tilting axis is assumed to be along the center of the FOV width. :param fname: name of the dataset. :param target_slice: the slice number where the tilting axis lies. :param tilt: tilting angle in degree. Positive = anticlockwise; negative = clockwise. :return: tilted sinogram. """ shape = read_data_adaptive(fname, shape_only=True) fov2 = shape[2] / 2. tilt = np.deg2rad(tilt) range_l = target_slice + fov2 * np.tan(tilt) range_r = target_slice - fov2 * np.tan(tilt) if tilt > 0: range_l = int(np.ceil(range_l)) + 1 range_r = int(np.floor(range_r)) else: range_l = int(np.floor(range_l)) range_r = int(np.ceil(range_r)) + 1 dat, flt, drk, _ = read_data_adaptive(fname, sino=(min([range_l, range_r]), max([range_l, range_r]))) if preprocess_data: dat = tomopy.normalize(dat, flt, drk) dat = preprocess(dat) else: dat[np.isnan(dat)] = 0 tilted_block = rotate(dat, tilt, axes=(1, 2), reshape=True) mid_slice = int(dat.shape[1] / 2) return tilted_block[:, mid_slice:mid_slice + 1, :]
def load_sino(filename, sino_n, normalize=True, data_format='aps_32id'): internal_print('Loading {:s}, slice {:d}'.format(filename, sino_n)) sino_n = int(sino_n) sino, flt, drk, _ = read_data_adaptive(filename, sino=(sino_n, sino_n + 1), data_format=data_format) if not normalize: flt[:, :, :] = flt.max() drk[:, :, :] = 0 sino = tomopy.normalize(sino, flt, drk) # 1st slice of each tile of some samples contains mostly abnormally large values which should be removed. if sino.max() > 1e2: sino[np.abs(sino) > 1] = 1 return np.squeeze(sino)
def save_partial_frames(file_grid, save_folder, prefix, frame=0, data_format='aps_32id'): for (y, x), value in np.ndenumerate(file_grid): print(value) if (value != None): prj, flt, drk, _ = read_data_adaptive(value, proj=(frame, frame + 1), data_format=data_format) prj = tomopy.normalize(prj, flt, drk) prj = preprocess(prj) fname = prefix + 'Y' + str(y).zfill(2) + '_X' + str(x).zfill(2) dxchange.write_tiff(np.squeeze(prj), fname=os.path.join(save_folder, 'partial_frames', fname))
def save_partial_raw(file_list, save_folder, data_format='aps_32id'): for value in file_list: if (value != None): prj, flt, drk, _ = read_data_adaptive(value, proj=(0, 1), data_format=data_format) fname = value dxchange.write_tiff_stack(np.squeeze(flt), fname=os.path.join( save_folder, 'partial_flats', fname)) dxchange.write_tiff_stack(np.squeeze(drk), fname=os.path.join( save_folder, 'partial_darks', fname)) prj = prj.astype('float32') dxchange.write_tiff(np.squeeze(prj), fname=os.path.join(save_folder, 'partial_frames_raw', fname))
def recon_hdf5(src_fanme, dest_folder, sino_range, sino_step, shift_grid, center_vec=None, center_eq=None, dtype='float32', algorithm='gridrec', tolerance=1, chunk_size=20, save_sino=False, sino_blur=None, flattened_radius=120, mode='180', test_mode=False, phase_retrieval=None, ring_removal=True, crop=None, num_iter=None, pad_length=0, read_theta=True, **kwargs): """ center_eq: a and b parameters in fitted center position equation center = a*slice + b. """ if not os.path.exists(dest_folder): try: os.mkdir(dest_folder) except: pass sino_ini = int(sino_range[0]) sino_end = int(sino_range[1]) sino_ls_all = np.arange(sino_ini, sino_end, sino_step, dtype='int') alloc_set = allocate_mpi_subsets(sino_ls_all.size, size, task_list=sino_ls_all) sino_ls = alloc_set[rank] # prepare metadata f = h5py.File(src_fanme) dset = f['exchange/data'] full_shape = dset.shape if read_theta: _, _, _, theta = read_data_adaptive(src_fanme, proj=(0, 1)) else: theta = tomopy.angles(full_shape[0]) if center_eq is not None: a, b = center_eq center_ls = sino_ls_all * a + b center_ls = np.round(center_ls) for iblock in range(int(sino_ls.size / chunk_size) + 1): internal_print('Beginning block {:d}.'.format(iblock)) t0 = time.time() istart = iblock * chunk_size iend = np.min([(iblock + 1) * chunk_size, sino_ls.size]) sub_sino_ls = sino_ls[istart:iend - 1] center = np.take(center_ls, sub_sino_ls) data = np.zeros([dset.shape[0], len(sub_sino_ls), dset.shape[2]]) for ind, i in enumerate(sub_sino_ls): data[:, ind, :] = dset[:, i, :] data[np.isnan(data)] = 0 data = data.astype('float32') data = tomopy.remove_stripe_ti(data, alpha=4) if sino_blur is not None: for i in range(data.shape[1]): data[:, i, :] = gaussian_filter(data[:, i, :], sino_blur) if phase_retrieval: data = tomopy.retrieve_phase(data, kwargs['pixel_size'], kwargs['dist'], kwargs['energy'], kwargs['alpha']) if pad_length != 0: data = pad_sinogram(data, pad_length) data = tomopy.remove_stripe_ti(data, alpha=4) if ring_removal: rec0 = tomopy.recon(data, theta, center=center + pad_length, algorithm=algorithm, **kwargs) rec = tomopy.remove_ring(np.copy(rec0)) cent = int((rec.shape[1] - 1) / 2) xx, yy = np.meshgrid(np.arange(rec.shape[2]), np.arange(rec.shape[1])) mask0 = ((xx - cent)**2 + (yy - cent)**2 <= flattened_radius**2) mask = np.zeros(rec.shape, dtype='bool') for i in range(mask.shape[0]): mask[i, :, :] = mask0 rec[mask] = (rec[mask] + rec0[mask]) / 2 else: rec = tomopy.recon(data, theta, center=center + pad_length, algorithm=algorithm, **kwargs) if pad_length != 0: rec = rec[:, pad_length:pad_length + full_shape[2], pad_length:pad_length + full_shape[2]] rec = tomopy.remove_outlier(rec, tolerance) rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) if crop is not None: crop = np.asarray(crop) rec = rec[:, crop[0, 0]:crop[1, 0], crop[0, 1]:crop[1, 1]] for i in range(rec.shape[0]): slice = sub_sino_ls[i] dxchange.write_tiff( rec[i, :, :], fname=os.path.join( dest_folder, 'recon/recon_{:05d}.tiff').format(slice)) if save_sino: dxchange.write_tiff( data[:, i, :], fname=os.path.join( dest_folder, 'sino/recon_{:05d}_{:d}.tiff').format( slice, int(center[i]))) iblock += 1 internal_print('Block {:d} finished in {:.2f} s.'.format( iblock, time.time() - t0)) else: # divide chunks grid_bins = np.append(np.ceil(shift_grid[:, 0, 0]), full_shape[1]) chunks = [] center_ls = [] istart = 0 counter = 0 # irow should be 0 for slice 0 irow = np.searchsorted(grid_bins, sino_ls[0], side='right') - 1 for i in range(sino_ls.size): counter += 1 sino_next = i + 1 if i != sino_ls.size - 1 else i if counter >= chunk_size or sino_ls[sino_next] >= grid_bins[ irow + 1] or sino_next == i: iend = i + 1 chunks.append((istart, iend)) istart = iend center_ls.append(center_vec[irow]) if sino_ls[sino_next] >= grid_bins[irow + 1]: irow += 1 counter = 0 # reconstruct chunks iblock = 1 for (istart, iend), center in zip(chunks, center_ls): internal_print('Beginning block {:d}.'.format(iblock)) t0 = time.time() internal_print('Reading data...') sub_sino_ls = sino_ls[istart:iend] data = np.zeros([dset.shape[0], len(sub_sino_ls), dset.shape[2]]) for ind, i in enumerate(sub_sino_ls): data[:, ind, :] = dset[:, i, :] if mode == '360': overlap = 2 * (dset.shape[2] - center) data = tomosaic.sino_360_to_180(data, overlap=overlap, rotation='right') theta = tomopy.angles(data.shape[0]) data[np.isnan(data)] = 0 data = data.astype('float32') if sino_blur is not None: for i in range(data.shape[1]): data[:, i, :] = gaussian_filter(data[:, i, :], sino_blur) if phase_retrieval: data = tomopy.retrieve_phase(data, kwargs['pixel_size'], kwargs['dist'], kwargs['energy'], kwargs['alpha']) if pad_length != 0: data = pad_sinogram(data, pad_length) data = tomopy.remove_stripe_ti(data, alpha=4) if ring_removal: rec0 = tomopy.recon(data, theta, center=center + pad_length, algorithm=algorithm, **kwargs) rec = tomopy.remove_ring(np.copy(rec0)) cent = int((rec.shape[1] - 1) / 2) xx, yy = np.meshgrid(np.arange(rec.shape[2]), np.arange(rec.shape[1])) mask0 = ((xx - cent)**2 + (yy - cent)**2 <= flattened_radius**2) mask = np.zeros(rec.shape, dtype='bool') for i in range(mask.shape[0]): mask[i, :, :] = mask0 rec[mask] = (rec[mask] + rec0[mask]) / 2 else: rec = tomopy.recon(data, theta, center=center + pad_length, algorithm=algorithm, **kwargs) if pad_length != 0: rec = rec[:, pad_length:pad_length + full_shape[2], pad_length:pad_length + full_shape[2]] rec = tomopy.remove_outlier(rec, tolerance) rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) if crop is not None: crop = np.asarray(crop) rec = rec[:, crop[0, 0]:crop[1, 0], crop[0, 1]:crop[1, 1]] for i in range(rec.shape[0]): slice = sub_sino_ls[i] if test_mode: dxchange.write_tiff( rec[i, :, :], fname=os.path.join( dest_folder, 'recon/recon_{:05d}_{:d}.tiff').format( slice, center), dtype=dtype) else: dxchange.write_tiff( rec[i, :, :], fname=os.path.join( dest_folder, 'recon/recon_{:05d}.tiff').format(slice), dtype=dtype) if save_sino: dxchange.write_tiff( data[:, i, :], fname=os.path.join( dest_folder, 'sino/recon_{:05d}_{:d}.tiff').format( slice, center), dtype=dtype) internal_print('Block {:d} finished in {:.2f} s.'.format( iblock, time.time() - t0)) iblock += 1 return
def recon_single(fname, center, dest_folder, sino_range=None, chunk_size=50, read_theta=True, pad_length=0, phase_retrieval=False, ring_removal=True, algorithm='gridrec', flattened_radius=40, crop=None, remove_padding=True, **kwargs): prj_shape = read_data_adaptive(fname, shape_only=True) if read_theta: theta = read_data_adaptive(fname, proj=(0, 1), return_theta=True) else: theta = tomopy.angles(prj_shape[0]) if sino_range is None: sino_st = 0 sino_end = prj_shape[1] sino_step = 1 else: sino_st, sino_end = sino_range[:2] if len(sino_range) == 3: sino_step = sino_range[-1] else: sino_step = 1 chunks = np.arange(0, sino_end, chunk_size * sino_step, dtype='int') for chunk_st in chunks: t0 = time.time() chunk_end = min(chunk_st + chunk_size * sino_step, prj_shape[1]) data, flt, drk = read_data_adaptive(fname, sino=(chunk_st, chunk_end, sino_step), return_theta=False) data = tomopy.normalize(data, flt, drk) data = data.astype('float32') data = tomopy.remove_stripe_ti(data, alpha=4) if phase_retrieval: data = tomopy.retrieve_phase(data, kwargs['pixel_size'], kwargs['dist'], kwargs['energy'], kwargs['alpha']) if pad_length != 0: data = pad_sinogram(data, pad_length) if ring_removal: data = tomopy.remove_stripe_ti(data, alpha=4) rec0 = tomopy.recon(data, theta, center=center + pad_length, algorithm=algorithm, **kwargs) rec = tomopy.remove_ring(np.copy(rec0)) cent = int((rec.shape[1] - 1) / 2) xx, yy = np.meshgrid(np.arange(rec.shape[2]), np.arange(rec.shape[1])) mask0 = ((xx - cent)**2 + (yy - cent)**2 <= flattened_radius**2) mask = np.zeros(rec.shape, dtype='bool') for i in range(mask.shape[0]): mask[i, :, :] = mask0 rec[mask] = (rec[mask] + rec0[mask]) / 2 else: rec = tomopy.recon(data, theta, center=center + pad_length, algorithm=algorithm, **kwargs) if pad_length != 0 and remove_padding: rec = rec[:, pad_length:pad_length + prj_shape[2], pad_length:pad_length + prj_shape[2]] rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) if crop is not None: crop = np.asarray(crop) rec = rec[:, crop[0, 0]:crop[1, 0], crop[0, 1]:crop[1, 1]] for i in range(rec.shape[0]): slice = chunk_st + sino_step * i internal_print('Saving slice {}'.format(slice)) dxchange.write_tiff( rec[i, :, :], fname=os.path.join(dest_folder, 'recon_{:05d}.tiff').format(slice), dtype='float32') internal_print('Block finished in {:.2f} s.'.format(time.time() - t0))
def recon_block(grid, shift_grid, src_folder, dest_folder, slice_range, sino_step, center_vec, ds_level=0, blend_method='max', blend_options=None, tolerance=1, sinogram_order=False, algorithm='gridrec', init_recon=None, ncore=None, nchunk=None, dtype='float32', crop=None, save_sino=False, assert_width=None, sino_blur=None, color_correction=False, flattened_radius=120, normalize=True, test_mode=False, mode='180', phase_retrieval=None, data_format='aps_32id', read_theta=True, ring_removal=True, **kwargs): """ Reconstruct dsicrete HDF5 tiles, blending sinograms only. """ sino_ini = int(slice_range[0]) sino_end = int(slice_range[1]) mod_start_slice = 0 center_vec = np.asarray(center_vec) center_pos_cache = 0 sino_ls = np.arange(sino_ini, sino_end, sino_step, dtype='int') alloc_set = allocate_mpi_subsets(sino_ls.size, size, task_list=sino_ls) for i_slice in alloc_set[rank]: internal_print('############################################') internal_print('Reconstructing ' + str(i_slice)) row_sino, center_pos = create_row_sinogram( grid, shift_grid, src_folder, i_slice, center_vec, ds_level, blend_method, blend_options, assert_width, sino_blur, color_correction, normalize, mode, phase_retrieval, data_format) if row_sino is None: continue if read_theta: _, _, _, theta = read_data_adaptive(os.path.join( src_folder, grid[0, 0]), proj=(0, 1), return_theta=True) if ring_removal: rec0 = recon_slice(row_sino, theta, center_pos, sinogram_order=sinogram_order, algorithm=algorithm, init_recon=init_recon, ncore=ncore, nchunk=nchunk, **kwargs) rec = tomopy.remove_ring(np.copy(rec0)) cent = int((rec.shape[1] - 1) / 2) xx, yy = np.meshgrid(np.arange(rec.shape[2]), np.arange(rec.shape[1])) mask0 = ((xx - cent)**2 + (yy - cent)**2 <= flattened_radius**2) mask = np.zeros(rec.shape, dtype='bool') for i in range(mask.shape[0]): mask[i, :, :] = mask0 rec[mask] = (rec[mask] + rec0[mask]) / 2 else: rec = recon_slice(row_sino, theta, center_pos, sinogram_order=sinogram_order, algorithm=algorithm, init_recon=init_recon, ncore=ncore, nchunk=nchunk, **kwargs) #rec = tomopy.remove_outlier(rec, tolerance) rec = tomopy.circ_mask(rec, axis=0, ratio=0.95) internal_print('Center: {:d}'.format(center_pos)) rec = np.squeeze(rec) # correct recon position shifting due to center misalignment if center_pos_cache == 0: center_pos_cache = center_pos center_diff = center_pos - center_pos_cache if center_diff != 0: rec = np.roll(rec, -center_diff, axis=0) if not crop is None: crop = np.asarray(crop) rec = rec[crop[0, 0]:crop[1, 0], crop[0, 1]:crop[1, 1]] if test_mode: dxchange.write_tiff(rec, fname=os.path.join( dest_folder, 'recon/recon_{:05d}_{:04d}.tiff'.format( i_slice, center_pos)), dtype=dtype) else: dxchange.write_tiff(rec, fname=os.path.join( dest_folder, 'recon/recon_{:05d}.tiff'.format(i_slice)), dtype=dtype) if save_sino: dxchange.write_tiff(np.squeeze(row_sino), fname=os.path.join( dest_folder, 'sino/sino_{:05d}.tiff'.format(i_slice)), overwrite=True) return
def main(arg): parser = argparse.ArgumentParser() parser.add_argument("--src_folder", help="folder where the H5 files are located", default='data_raw_1x') parser.add_argument("--frame", help="frame to preview", default=None) parser.add_argument("--pano", help="Preview Panorama", default=None) args = parser.parse_args() src_folder = args.src_folder method = 'pyramid' margin = 50 pyramid_options = {'depth': 5, 'blur': 0.4} f_pattern = 1 prefix = '' file_list = tomosaic.get_files(src_folder, prefix, type='h5') print(file_list) file_grid = tomosaic.start_file_grid(file_list, pattern=f_pattern) file_grid = np.fliplr(file_grid) print(file_grid) data_format = 'aps_32id' try: shift_grid = tomosaic.util.file2grid("shifts.txt") shift_grid = tomosaic.absolute_shift_grid(shift_grid, file_grid) except: print('Refined shift is not provided. Using pre-set shift values. ') shift_grid = tomosaic.start_shift_grid(file_grid, x_shift, y_shift) if (args.frame != None): frame = int(args.frame) for f in file_list: dat, flt, drk, _ = read_data_adaptive(os.path.join(src_folder, f), proj=(frame, frame + 1), data_format=data_format) #dat = tomopy.normalize(dat, flt, drk) #dat = tomopy.minus_log(dat) f = os.path.splitext(os.path.basename(f))[0] dxchange.write_tiff(flt.mean(0), os.path.join('preview_flats', f), dtype='float32', overwrite=True) dxchange.write_tiff(drk.mean(0), os.path.join('preview_darks', f), dtype='float32', overwrite=True) dxchange.write_tiff(dat, os.path.join('preview_frames', f), dtype='float32', overwrite=True) if (args.pano != None): pano = int(args.pano) buff = build_panorama('data_raw_1x', file_grid, shift_grid.astype(int), frame=pano, data_format=data_format, method=method, blend_options=pyramid_options) dxchange.write_tiff(buff, 'preview_panos/{}_norm'.format(pano), dtype='float32', overwrite=True)
dat[np.where(np.isnan(dat) == True)] = 0 if blur is not None: dat = gaussian_filter(dat, blur) return dat shift_grid = tomosaic.start_shift_grid(file_grid, x_shift, y_shift).astype('int') shift_grid = tomosaic.util.file2grid("shifts.txt") shift_grid = (tomosaic.absolute_shift_grid(shift_grid, file_grid) / 4.) print(shift_grid) root = os.getcwd() os.chdir(src_folder) last_none = False buff = np.zeros([1, 1]) for (y, x), value in np.ndenumerate(file_grid): if value != None: prj, flt, drk, _ = read_data_adaptive(value, proj=(frame, frame + 1)) prj = tomopy.normalize(prj, flt, drk) prj = preprocess(np.copy(prj)) buff = blend(buff, np.squeeze(prj), shift_grid[y, x, :], method=method) print(y, x) os.chdir(root) dxchange.write_tiff(buff, 'panos/{}_norm'.format(frame), dtype='float32', overwrite=True)