def _find_rotation_axis(params): log.info(" *** calculating automatic center") data_size = file_io.get_dx_dims(params) ssino = int(data_size[1] * params.nsino) # Select sinogram range to reconstruct sino_start = ssino sino_end = sino_start + pow(2, int(params.binning)) sino = (int(sino_start), int(sino_end)) # Read APS 32-BM raw data proj, flat, dark, theta, params_rotation_axis_ignored = file_io.read_tomo( sino, params) # apply all preprocessing functions data = prep.all(proj, flat, dark, params, sino) # find rotation center log.info(" *** find_center vo") rot_center = tomopy.find_center_vo(data) log.info(" *** automatic center: %f" % rot_center) return rot_center * np.power(2, float(params.binning))
def _find_rotation_axis(params): log.info(" *** calculating automatic center") data_size = file_io.get_dx_dims(params) ssino = int(data_size[1] * params.nsino) params = file_io.read_pixel_size(params) params = file_io.read_filter_materials(params) params = file_io.read_scintillator(params) params = file_io.read_bright_ratio(params) # Select sinogram range to reconstruct sino_start = ssino sino_end = sino_start + pow(2, int(params.binning)) sino = (int(sino_start), int(sino_end)) # Read APS 32-BM raw data proj, flat, dark, theta, params_rotation_axis_ignored = file_io.read_tomo(sino, params, True) # apply all preprocessing functions data = prep.all(proj, flat, dark, params, sino) # if flip and stitch, just use the overlapped part of the dataset if params.file_type == 'flip_and_stich': params = _find_rotation_axis_flip_stitch(data, params) else: # find rotation center log.info(" *** find_center vo") # if we start at 0 and end at 180, remove last angle if np.isclose(theta[-1] - theta[0], np.pi, 1e-4): data = data[:-1,...] params.rotation_axis = tomopy.find_center_vo(data) * np.power(2, float(params.binning)) params.rotation_axis_flip = -1 log.info(" *** automatic center: %f" % params.rotation_axis) return params
def rec(params): data_shape = file_io.get_dx_dims(params) if params.rotation_axis < 0: params.rotation_axis = data_shape[2] / 2 # Select sinogram range to reconstruct if (params.reconstruction_type == "full"): nSino_per_chunk = params.nsino_per_chunk chunks = int(np.ceil(data_shape[1] / nSino_per_chunk)) sino_start = 0 sino_end = chunks * nSino_per_chunk else: # "slice" and "try" nSino_per_chunk = pow(2, int(params.binning)) chunks = 1 ssino = int(data_shape[1] * params.nsino) sino_start = ssino sino_end = sino_start + pow(2, int(params.binning)) log.info("reconstructing [%d] slices from slice [%d] to [%d] in [%d] chunks of [%d] slices each" % \ ((sino_end - sino_start)/pow(2, int(params.binning)), sino_start/pow(2, int(params.binning)), sino_end/pow(2, int(params.binning)), \ chunks, nSino_per_chunk/pow(2, int(params.binning)))) strt = 0 for iChunk in range(0, chunks): log.info('chunk # %i/%i' % (iChunk, chunks)) sino_chunk_start = np.int(sino_start + nSino_per_chunk * iChunk) sino_chunk_end = np.int(sino_start + nSino_per_chunk * (iChunk + 1)) log.info(' *** [%i, %i]' % (sino_chunk_start / pow(2, int(params.binning)), sino_chunk_end / pow(2, int(params.binning)))) if sino_chunk_end > sino_end: break sino = (int(sino_chunk_start), int(sino_chunk_end)) # Read APS 32-BM raw data. proj, flat, dark, theta, rotation_axis = file_io.read_tomo( sino, params) # apply all preprocessing functions data = prep.all(proj, flat, dark, params) # Reconstruct if (params.reconstruction_type == "try"): # try passes an array of rotation centers and this is only supported by gridrec reconstruction_algorithm_org = params.reconstruction_algorithm params.reconstruction_algorithm = 'gridrec' center_search_width = params.center_search_width / np.power( 2, float(params.binning)) center_range = (rotation_axis - center_search_width, rotation_axis + center_search_width, 0.5) stack = np.empty( (len(np.arange(*center_range)), data_shape[0], int(data_shape[2] / np.power(2, float(params.binning))))) index = 0 for axis in np.arange(*center_range): stack[index] = data[:, 0, :] index = index + 1 log.warning( ' reconstruct slice [%d] with rotation axis range [%.2f - %.2f] in [%.2f] pixel steps' % (ssino, center_range[0], center_range[1], center_range[2])) rotation_axis = np.arange(*center_range) rec = padded_rec(stack, theta, rotation_axis, params) # Save images to a temporary folder. fname = os.path.dirname( params.hdf_file ) + '_rec' + os.sep + 'try_center' + os.sep + file_io.path_base_name( params.hdf_file) + os.sep + 'recon_' index = 0 for axis in np.arange(*center_range): rfname = fname + str('{0:.2f}'.format( axis * np.power(2, float(params.binning))) + '.tiff') dxchange.write_tiff(rec[index], fname=rfname, overwrite=True) index = index + 1 # restore original method params.reconstruction_algorithm = reconstruction_algorithm_org else: # "slice" and "full" rec = padded_rec(data, theta, rotation_axis, params) # handling of the last chunk if (params.reconstruction_type == "full"): if (iChunk == chunks - 1): log.info("handling of the last chunk") log.info(" *** chunk # %d" % (chunks)) log.info(" *** last rec size %d" % ((data_shape[1] - (chunks - 1) * nSino_per_chunk) / pow(2, int(params.binning)))) rec = rec[0:data_shape[1] - (chunks - 1) * nSino_per_chunk, :, :] # Save images if (params.reconstruction_type == "full"): tail = os.sep + os.path.splitext( os.path.basename(params.hdf_file))[0] + '_rec' + os.sep fname = os.path.dirname( params.hdf_file) + '_rec' + tail + 'recon' dxchange.write_tiff_stack(rec, fname=fname, start=strt) strt += int( (sino[1] - sino[0]) / np.power(2, float(params.binning))) if (params.reconstruction_type == "slice"): fname = os.path.dirname( params.hdf_file ) + os.sep + 'slice_rec/recon_' + os.path.splitext( os.path.basename(params.hdf_file))[0] dxchange.write_tiff_stack(rec, fname=fname, overwrite=False) log.info(" *** reconstructions: %s" % fname)
def rec(params): data_shape = file_io.get_dx_dims(params) #Read parameters from DXchange file if requested params = file_io.auto_read_dxchange(params) if params.rotation_axis <= 0: params.rotation_axis = data_shape[2] / 2 log.warning( ' *** *** No rotation center given: assuming the middle of the projections at %f' % float(params.rotation_axis)) # Select sinogram range to reconstruct if (params.reconstruction_type == "full"): if params.start_row: sino_start = params.start_row else: sino_start = 0 if params.end_row < 0: sino_end = data_shape[1] else: sino_end = params.end_row #If params.nsino_per_chunk < 1, use # of processor cores if params.nsino_per_chunk < 1: params.nsino_per_chunk = cpu_count() nSino_per_chunk = params.nsino_per_chunk chunks = int(np.ceil((sino_end - sino_start) / nSino_per_chunk)) else: # "slice" and "try" nSino_per_chunk = pow(2, int(params.binning)) chunks = 1 ssino = int(data_shape[1] * params.nsino) sino_start = ssino sino_end = sino_start + pow(2, int(params.binning)) log.info("reconstructing [%d] slices from slice [%d] to [%d] in [%d] chunks of [%d] slices each" % \ ((sino_end - sino_start)/pow(2, int(params.binning)), sino_start/pow(2, int(params.binning)), sino_end/pow(2, int(params.binning)), \ chunks, nSino_per_chunk/pow(2, int(params.binning)))) strt = sino_start for iChunk in range(0, chunks): log.info('chunk # %i/%i' % (iChunk + 1, chunks)) sino_chunk_start = np.int(sino_start + nSino_per_chunk * iChunk) sino_chunk_end = np.int(sino_start + nSino_per_chunk * (iChunk + 1)) if sino_chunk_end > sino_end: log.warning( ' *** asking to go to row {0:d}, but our end row is {1:d}'. format(sino_chunk_end, sino_end)) sino_chunk_end = sino_end log.info(' *** [%i, %i]' % (sino_chunk_start / pow(2, int(params.binning)), sino_chunk_end / pow(2, int(params.binning)))) sino = (int(sino_chunk_start), int(sino_chunk_end)) # Read APS 32-BM raw data. proj, flat, dark, theta, rotation_axis = file_io.read_tomo( sino, params) # What if sino overruns the size of data? if sino[1] - sino[0] > proj.shape[1]: log.warning(" *** Chunk size > remaining data size.") sino = (sino[0], sino[0] + proj.shape[1]) # apply all preprocessing functions data = prep.all(proj, flat, dark, params, sino) # Reconstruct if (params.reconstruction_type == "try"): # try passes an array of rotation centers and this is only supported by gridrec reconstruction_algorithm_org = params.reconstruction_algorithm params.reconstruction_algorithm = 'gridrec' center_search_width = params.center_search_width / np.power( 2, float(params.binning)) center_range = (rotation_axis - center_search_width, rotation_axis + center_search_width, 0.5) stack = np.empty( (len(np.arange(*center_range)), data_shape[0], int(data_shape[2] / np.power(2, float(params.binning))))) index = 0 for axis in np.arange(*center_range): stack[index] = data[:, 0, :] index = index + 1 log.warning( ' reconstruct slice [%d] with rotation axis range [%.2f - %.2f] in [%.2f] pixel steps' % (ssino, center_range[0], center_range[1], center_range[2])) rotation_axis = np.arange(*center_range) rec = padded_rec(stack, theta, rotation_axis, params) # Save images to a temporary folder. fname = os.path.dirname( params.file_name ) + '_rec' + os.sep + 'try_center' + os.sep + file_io.path_base_name( params.file_name) + os.sep + 'recon_' index = 0 for axis in np.arange(*center_range): rfname = fname + str('{0:.2f}'.format( axis * np.power(2, float(params.binning))) + '.tiff') dxchange.write_tiff(rec[index], fname=rfname, overwrite=True) index = index + 1 # restore original method params.reconstruction_algorithm = reconstruction_algorithm_org else: # "slice" and "full" rec = padded_rec(data, theta, rotation_axis, params) # Save images if (params.reconstruction_type == "full"): tail = os.sep + os.path.splitext( os.path.basename(params.file_name))[0] + '_rec' + os.sep fname = os.path.dirname( params.file_name) + '_rec' + tail + 'recon' write_thread = threading.Thread( target=dxchange.write_tiff_stack, args=(rec, ), kwargs={ 'fname': fname, 'start': strt, 'overwrite': True }) write_thread.start() #dxchange.write_tiff_stack(rec, fname=fname, start=strt) strt += int( (sino[1] - sino[0]) / np.power(2, float(params.binning))) if (params.reconstruction_type == "slice"): fname = Path.joinpath( Path(os.path.dirname(params.file_name) + '_rec'), 'slice_rec', 'recon_' + Path(params.file_name).stem) # fname = Path.joinpath(Path(params.file_name).parent, 'slice_rec','recon_'+str(Path(params.file_name).stem)) dxchange.write_tiff_stack(rec, fname=str(fname), overwrite=False) log.info(" *** reconstructions: %s" % fname)
def rec(params): data_shape = file_io.get_dx_dims(params) # Read parameters from YAML file params = config.yaml_args(params, params.parameter_file, str(params.file_name)) # Read parameters from DXchange file if requested params = file_io.auto_read_dxchange(params) if params.rotation_axis <= 0: params.rotation_axis = data_shape[2]/2 log.warning(' *** *** No rotation center given: assuming the middle of the projections at %f' % float(params.rotation_axis)) # Select sinogram range to reconstruct if (params.reconstruction_type == "full"): if params.start_row: sino_start = params.start_row else: sino_start = 0 if params.end_row < 0: sino_end = data_shape[1] else: sino_end = params.end_row # If params.nsino_per_chunk < 1, use # of processor cores if params.nsino_per_chunk < 1: params.nsino_per_chunk = cpu_count() nSino_per_chunk = params.nsino_per_chunk * pow(2, int(params.binning)) chunks = int(np.ceil((sino_end - sino_start)/nSino_per_chunk)) elif (params.reconstruction_type == 'try'): _try_rec(params) return else: # "slice" nSino_per_chunk = pow(2, int(params.binning)) chunks = 1 ssino = int(data_shape[1] * params.nsino) sino_start = ssino sino_end = sino_start + pow(2, int(params.binning)) log.info(" *** reconstructing [%d] slices from slice [%d] to [%d] in [%d] chunks of [%d] slices each" % ( (sino_end - sino_start) / pow(2, int(params.binning)), sino_start/pow(2, int(params.binning)), sino_end/pow(2, int(params.binning)), chunks, nSino_per_chunk/pow(2, int(params.binning)))) strt = sino_start write_threads = [] if chunks == 0: log.warning(" *** 0 chunks selected for reconstruction, " "check your *start_row*, " "*end_row*, and *nsino_per_chunk*.") for iChunk in range(0, chunks): log.info('chunk # %i/%i' % (iChunk + 1, chunks)) sino = _compute_sino(iChunk, sino_start, sino_end, nSino_per_chunk, chunks, params) # Read APS 32-BM raw data. proj, flat, dark, theta, rotation_axis = file_io.read_tomo(sino, params) # What if sino overruns the size of data? if sino[1] - sino[0] > proj.shape[1]: log.warning(" *** Chunk size > remaining data size.") sino = [sino[0], sino[0] + proj.shape[1]] # Apply all preprocessing functions data = prep.all(proj, flat, dark, params, sino) del(proj, flat, dark) # unpad after phase retrieval if params.retrieve_phase_method == "paganin": params.phase_pad //= pow(2, int(params.binning)) sino -= params.phase_pad data = data[:,-params.phase_pad[0]:data.shape[1]-params.phase_pad[1]] log.info(' *** unpadding after phase retrieval gives slices [%i,%i] ' % (sino[0],sino[1])) # Reconstruct: this is for "slice" and "full" methods rotation_axis_rec = rotation_axis if (params.file_type == 'double_fov'): if(rotation_axis<data.shape[-1]//2): #if rotation center is on the left side of the ROI data = data[:,:,::-1] rotation_axis_rec = data.shape[-1]-rotation_axis # double FOV by adding zeros data = double_fov(data,rotation_axis_rec) #Perform actual reconstruction rec = padded_rec(data, theta, rotation_axis_rec, params) # Save images recon_base_dir = reconstruction_folder(params) fpath = Path(params.file_name).resolve() if params.reconstruction_type == "full": recon_dir = recon_base_dir / "{}_rec".format(fpath.stem) if params.output_format == 'tiff_stack': fname = recon_dir / 'recon' log.debug("Full tiff dir: %s", fname) write_thread = threading.Thread(target=dxchange.write_tiff_stack, args = (rec,), kwargs = {'fname': str(fname), 'start': strt, 'overwrite': True}) elif params.output_format == "hdf5": # HDF5 output fname = "{}.hdf".format(recon_dir) # file_io.write_hdf5(rec, fname=str(fname), dest_idx=slice(strt, strt+rec.shape[0]), # maxsize=(sino_end, *rec.shape[1:]), overwrite=(iChunk==0)) ds_end = int(np.ceil(sino_end / pow(2, int(params.binning)))) write_thread = threading.Thread(target=file_io.write_hdf5, args = (rec,), kwargs = {'fname': str(fname), 'dest_idx': slice(strt, strt+rec.shape[0]), 'maxsize': (ds_end, *rec.shape[1:]), 'overwrite': iChunk==0}) else: log.error(" *** Unknown output_format '%s'", params.output_format) fname = "<Not saved (bad output-format)>" write_thread = None # Save the data to disk if write_thread is not None: write_thread.start() write_threads.append(write_thread) # Increment counter for which chunks to save strt += (sino[1] - sino[0]) elif params.reconstruction_type == "slice": # Construct the path for where to save the tiffs fname = recon_base_dir / 'slice_rec' / 'recon_{}'.format(fpath.stem) dxchange.write_tiff(rec, fname=str(fname), overwrite=False) else: raise ValueError("Unknown value for *reconstruction type*: {}. " "Valid options are {}" "".format(params.reconstruction_type, config.SECTIONS['reconstruction']['reconstruction-type']['choices'])) log.info(" *** reconstructions: %s" % fname) # Wait until the all threads are done writing data for thread in write_threads: thread.join()
def _try_rec(params): log.info(" *** *** starting 'try' reconstruction") data_shape = file_io.get_dx_dims(params) # Select sinogram range to reconstruct nSino_per_chunk = pow(2, int(params.binning)) sino_start = int(data_shape[1] * params.nsino) sino_end = sino_start + pow(2, int(params.binning)) if sino_end > data_shape[1]: log.warning(' *** *** *** binning would request row past end of data. Truncating.') sino_start = data_shape[1] - pow(2, int(params.binning)) sino_end = data_shape[1] log.info("reconstructing a slice binned from raw data rows [%d] to [%d]" % \ (sino_start, sino_end)) log.info(' *** binned rows [%i, %i]' % (sino_start/pow(2, int(params.binning)), sino_end/pow(2, int(params.binning)))) sino = (int(sino_start), int(sino_end)) # Set up the centers of rotation we will use # Read APS 32-BM raw data. proj, flat, dark, theta, rotation_axis = file_io.read_tomo(sino, params, True) # Apply all preprocessing functions data = prep.all(proj, flat, dark, params, sino) rec = [] center_range = [] # try passes an array of rotation centers and this is only supported by gridrec # reconstruction_algorithm_org = params.reconstruction_algorithm # params.reconstruction_algorithm = 'gridrec' if (params.file_type == 'standard' or params.file_type == 'double_fov'): center_search_width = params.center_search_width/np.power(2, float(params.binning)) center_range = np.arange(rotation_axis-center_search_width, rotation_axis+center_search_width, 0.5) # stack = np.empty((len(center_range), data_shape[0], int(data_shape[2]))) if (params.blocked_views): # blocked_views = params.blocked_views_end - params.blocked_views_start # stack = np.empty((len(center_range), data_shape[0]-blocked_views, int(data_shape[2]))) st = params.blocked_views_start end = params.blocked_views_end #log.warning('%f %f',st,end) ids = np.where(((theta-st)%np.pi<0) + ((theta-st)%np.pi>end-st))[0] stack = np.empty((len(center_range), len(ids), int(data_shape[2]))) else: stack = np.empty((len(center_range), data.shape[0], int(data.shape[2]))) for i, axis in enumerate(center_range): stack[i] = data[:, 0, :] log.warning(' reconstruct slice [%d] with rotation axis range [%.2f - %.2f] in [%.2f] pixel steps' % (sino_start, center_range[0], center_range[-1], center_range[1] - center_range[0])) center_range_rec = center_range if (params.file_type == 'double_fov'): if(rotation_axis<stack.shape[-1]//2): #if rotation center is on the left side of the ROI stack = stack[:,:,::-1] center_range_rec = stack.shape[-1]-center_range # double FOV by adding zeros stack = double_fov_try(stack,center_range_rec) if params.reconstruction_algorithm == 'gridrec': rec = padded_rec(stack, theta, center_range_rec, params) else: log.warning(" *** Doing try_center with '%s' instead of 'gridrec' is slow.", params.reconstruction_algorithm) rec = [] for center in center_range_rec: rec.append(padded_rec(data[:, 0:1, :], theta, center, params)) rec = np.asarray(rec) else: rotation_axis = params.rotation_axis_flip // pow(2,int(params.binning)) center_search_width = params.center_search_width/np.power(2, float(params.binning)) center_range = np.arange(rotation_axis-center_search_width, rotation_axis+center_search_width, 0.5) stitched_data = [] rot_centers = np.zeros_like(center_range) #Loop through the assumed rotation centers for i, rot_center in enumerate(center_range): params.rotation_axis_flip = rot_center stitched_data.append(file_io.flip_and_stitch(params, data, np.ones_like(data[0,...]), np.zeros_like(data[0,...]))[0]) rot_centers[i] = params.rotation_axis total_cols = np.min([i.shape[2] for i in stitched_data]) theta180 = theta[:len(theta)//2] # take first half stack = np.empty((len(center_range), theta180.shape[0], total_cols)) for i in range(center_range.shape[0]): stack[i] = stitched_data[i][:theta180.shape[0],0,:total_cols] del(stitched_data) rec = padded_rec(stack, theta180, rot_centers, params) # Save images to a temporary folder. fpath = Path(params.file_name).resolve() rec_dir = reconstruction_folder(params) / 'try_center' / fpath.stem for i,axis in enumerate(center_range): this_center = axis * np.power(2, float(params.binning)) rfname = rec_dir / "recon_{:.2f}.tiff".format(this_center) dxchange.write_tiff(rec[i], fname=str(rfname), overwrite=True)