def process(sino_idx, num_sinos, infile, outpath, preprocessing_required, corr_plan, norm_sx, norm_dx, flat_end, half_half, half_half_line, ext_fov, ext_fov_rot_right, ext_fov_overlap, ext_fov_normalize, ext_fov_average, ringrem, phaseretrieval_required, phrtmethod, phrt_param1, phrt_param2, energy, distance, pixsize, phrtpad, approx_win, angles, angles_projfrom, angles_projto, offset, logtransform, param1, circle, scale, pad, method, zerone_mode, dset_min, dset_max, decim_factor, downsc_factor, corr_offset, postprocess_required, convert_opt, crop_opt, nr_threads, off_from, off_to, logfilename, lock, slice_prefix): """To do... """ slice_nr = sino_idx # Perform reconstruction (on-the-fly preprocessing and phase retrieval, if required): if (phaseretrieval_required): # In this case a bunch of sinograms is loaded into memory: # # Load the temporary data structure reading the input TDF file. # To know the right dimension the first sinogram is pre-processed. # # Open the TDF file and get the dataset: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] # Downscaling and decimation factors considered when determining the approximation window: zrange = arange(sino_idx - approx_win * downsc_factor / 2, sino_idx + approx_win * downsc_factor / 2, downsc_factor) zrange = zrange[(zrange >= 0)] zrange = zrange[(zrange < num_sinos)] approx_win = zrange.shape[0] # Approximation window cannot be odd: if (approx_win % 2 == 1): approx_win = approx_win - 1 zrange = zrange[0:approx_win] # Read one sinogram to get the proper dimensions: test_im = tdf.read_sino(dset, zrange[0] * downsc_factor).astype(float32) # Apply projection removal (if required): test_im = test_im[angles_projfrom:angles_projto, :] # Apply decimation and downscaling (if required): test_im = test_im[::decim_factor, ::downsc_factor] # Perform the pre-processing of the first sinogram to get the right dimension: if (preprocessing_required): test_im = flat_fielding(test_im, zrange[0], corr_plan, flat_end, half_half, half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: test_im = extfov_correction(test_im, ext_fov_rot_right, ext_fov_overlap / downsc_factor, ext_fov_normalize, ext_fov_average).astype(float32) test_im = ring_correction(test_im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line / decim_factor, ext_fov).astype(float32) # Now we can allocate memory for the bunch of slices: tmp_im = empty((approx_win, test_im.shape[0], test_im.shape[1]), dtype=float32) tmp_im[0, :, :] = test_im # Reading all the the sinos from TDF file and close: for ct in range(1, approx_win): test_im = tdf.read_sino(dset, zrange[ct] * downsc_factor).astype(float32) # Apply projection removal (if required): test_im = test_im[angles_projfrom:angles_projto, :] # Apply decimation and downscaling (if required): test_im = test_im[::decim_factor, ::downsc_factor] # Perform the pre-processing for each sinogram of the bunch: if (preprocessing_required): test_im = flat_fielding(test_im, zrange[ct], corr_plan, flat_end, half_half, half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: test_im = extfov_correction( test_im, ext_fov_rot_right, ext_fov_overlap / downsc_factor, ext_fov_normalize, ext_fov_average).astype(float32) test_im = ring_correction(test_im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line / decim_factor, ext_fov).astype(float32) tmp_im[ct, :, :] = test_im f_in.close() # Now everything has to refer to a downscaled dataset: sino_idx = ((zrange == sino_idx).nonzero()) # # Perform phase retrieval: # # Prepare the plan: if (phrtmethod == 0): # Paganin's: phrtplan = tiehom_plan(tmp_im[:, 0, :], phrt_param1, phrt_param2, energy, distance, pixsize * downsc_factor, padding=phrtpad) else: phrtplan = phrt_plan(tmp_im[:, 0, :], energy, distance, pixsize * downsc_factor, phrt_param2, phrt_param1, phrtmethod, padding=phrtpad) # Process each projection (whose height depends on the size of the bunch): for ct in range(0, tmp_im.shape[1]): if (phrtmethod == 0): tmp_im[:, ct, :] = tiehom(tmp_im[:, ct, :], phrtplan).astype(float32) else: tmp_im[:, ct, :] = phrt(tmp_im[:, ct, :], phrtplan, phrtmethod).astype(float32) # Extract the requested sinogram: im = tmp_im[sino_idx[0], :, :].squeeze() else: # Read only one sinogram: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] im = tdf.read_sino(dset, sino_idx * downsc_factor).astype(float32) f_in.close() # Apply projection removal (if required): im = im[angles_projfrom:angles_projto, :] # Downscale and decimate the sinogram: im = im[::decim_factor, ::downsc_factor] #sino_idx = sino_idx/downsc_factor # Perform the preprocessing of the sinogram (if required): if (preprocessing_required): im = flat_fielding(im, sino_idx, corr_plan, flat_end, half_half, half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: im = extfov_correction(im, ext_fov_rot_right, ext_fov_overlap / downsc_factor, ext_fov_normalize, ext_fov_average) im = ring_correction(im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line / decim_factor, ext_fov) # Log infos: log = open(logfilename, "a") log.write( linesep + "\tPerforming reconstruction with multiple centers of rotation...") log.write(linesep + "\t--------------") log.close() # Split the computation into multiple processes: for num in range(nr_threads): start = ((off_to - off_from + 1) / nr_threads) * num + off_from if (num == nr_threads - 1): end = off_to else: end = ((off_to - off_from + 1) / nr_threads) * (num + 1) + off_from - 1 Process(target=reconstruct, args=(im, angles, angles_projfrom, angles_projto, offset / downsc_factor, logtransform, param1, circle, scale, pad, method, zerone_mode, dset_min, dset_max, corr_offset, postprocess_required, convert_opt, crop_opt, start, end, outpath, slice_nr, downsc_factor, logfilename, lock, slice_prefix)).start()
def main(argv): """To do... """ lock = Lock() skip_flat = True first_done = False pyfftw_cache_disable() pyfftw_cache_enable() pyfftw_set_keepalive_time(1800) # Get the from and to number of files to process: int_from = int(argv[0]) int_to = int(argv[1]) # Get full paths of input TDF and output TDF: infile = argv[2] outfile = argv[3] # Get the phase retrieval parameters: method = int(argv[4]) param1 = double(argv[5]) # e.g. regParam, or beta param2 = double(argv[6]) # e.g. thresh or delta energy = double(argv[7]) distance = double(argv[8]) pixsize = double(argv[9]) / 1000.0 # pixsixe from micron to mm: pad = True if argv[10] == "True" else False # Number of threads (actually processes) to use and logfile: nr_threads = int(argv[11]) logfilename = argv[12] # Log infos: log = open(logfilename,"w") log.write(linesep + "\tInput TDF file: %s" % (infile)) log.write(linesep + "\tOutput TDF file: %s" % (outfile)) log.write(linesep + "\t--------------") if (method == 0): log.write(linesep + "\tMethod: TIE-Hom (Paganin et al., 2002)") log.write(linesep + "\t--------------") log.write(linesep + "\tDelta/Beta: %0.1f" % ((param2/param1)) ) #else: # log.write(linesep + "\tMethod: Projected CTF (Moosmann et al., 2011)") # log.write(linesep + "\t--------------") # log.write(linesep + "\tDelta/Beta: %0.1f" % ((param2/param1)) ) log.write(linesep + "\tEnergy: %0.1f keV" % (energy)) log.write(linesep + "\tDistance: %0.1f mm" % (distance)) log.write(linesep + "\tPixel size: %0.3f micron" % (pixsize*1000)) log.write(linesep + "\t--------------") log.write(linesep + "\tBrowsing input files...") log.close() # Remove a previous copy of output: if exists(outfile): remove(outfile) # Open the HDF5 file: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] num_proj = tdf.get_nr_projs(dset) num_sinos = tdf.get_nr_sinos(dset) if (num_proj == 0): log = open(logfilename,"a") log.write(linesep + "\tNo projections found. Process will end.") log.close() exit() log = open(logfilename,"a") log.write(linesep + "\tInput files browsed correctly.") log.close() # Check extrema (int_to == -1 means all files): if ( (int_to >= num_proj) or (int_to == -1) ): int_to = num_proj - 1 if ( (int_from < 0) ): int_from = 0 # Prepare the plan: log = open(logfilename,"a") log.write(linesep + "\tPreparing the work plan...") log.close() im = tdf.read_tomo(dset,0).astype(float32) outshape = tdf.get_dset_shape(im.shape[1], im.shape[0], num_proj) f_out = getHDF5(outfile, 'w') f_out_dset = f_out.create_dataset('exchange/data', outshape, float32) f_out_dset.attrs['min'] = str(amin(im[:])) f_out_dset.attrs['max'] = str(amax(im[:])) f_out_dset.attrs['version'] = '1.0' f_out_dset.attrs['axes'] = "y:theta:x" f_in.close() f_out.close() if (method == 0): # Paganin's: plan = tiehom_plan (im, param1, param2, energy, distance, pixsize, pad) else: plan = phrt_plan (im, energy, distance, pixsize, param2, param1, method, pad) # Run several threads for independent computation without waiting for threads completion: for num in range(nr_threads): start = (num_proj / nr_threads)*num if (num == nr_threads - 1): end = num_proj - 1 else: end = (num_proj / nr_threads)*(num + 1) - 1 Process(target=_process, args=(lock, start, end, infile, outfile, outshape, float32, method, plan, logfilename)).start()
def main(argv): """To do... """ lock = Lock() skip_flat = True first_done = False pyfftw_cache_disable() pyfftw_cache_enable() pyfftw_set_keepalive_time(1800) # Get the from and to number of files to process: int_from = int(argv[0]) int_to = int(argv[1]) # Get full paths of input TDF and output TDF: infile = argv[2] outfile = argv[3] # Get the phase retrieval parameters: method = int(argv[4]) param1 = double(argv[5]) # e.g. regParam, or beta param2 = double(argv[6]) # e.g. thresh or delta energy = double(argv[7]) distance = double(argv[8]) pixsize = double(argv[9]) / 1000.0 # pixsixe from micron to mm: pad = True if argv[10] == "True" else False # Number of threads (actually processes) to use and logfile: nr_threads = int(argv[11]) logfilename = argv[12] # Log infos: log = open(logfilename, "w") log.write(linesep + "\tInput TDF file: %s" % (infile)) log.write(linesep + "\tOutput TDF file: %s" % (outfile)) log.write(linesep + "\t--------------") if (method == 0): log.write(linesep + "\tMethod: TIE-Hom (Paganin et al., 2002)") log.write(linesep + "\t--------------") log.write(linesep + "\tDelta/Beta: %0.1f" % ((param2 / param1))) elif (method == 1): log.write(linesep + "\tMethod: Generalized TIE-Hom (Paganin et al., 2020)") log.write(linesep + "\t--------------") log.write(linesep + "\tDelta/Beta: %0.1f" % ((param2 / param1))) else: log.write(linesep + "\tMethod: Projected CTF (Moosmann et al., 2011)") log.write(linesep + "\t--------------") log.write(linesep + "\tRegularization: %0.3f" % (param2)) log.write(linesep + "\tThreshold: %0.3f" % (param1)) log.write(linesep + "\tEnergy: %0.1f keV" % (energy)) log.write(linesep + "\tDistance: %0.1f mm" % (distance)) log.write(linesep + "\tPixel size: %0.3f micron" % (pixsize * 1000)) log.write(linesep + "\t--------------") log.write(linesep + "\tBrowsing input files...") log.close() # Remove a previous copy of output: if exists(outfile): remove(outfile) # Open the HDF5 file: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] num_proj = tdf.get_nr_projs(dset) num_sinos = tdf.get_nr_sinos(dset) if (num_proj == 0): log = open(logfilename, "a") log.write(linesep + "\tNo projections found. Process will end.") log.close() exit() log = open(logfilename, "a") log.write(linesep + "\tInput files browsed correctly.") log.close() # Check extrema (int_to == -1 means all files): if ((int_to >= num_proj) or (int_to == -1)): int_to = num_proj - 1 if ((int_from < 0)): int_from = 0 # Prepare the plan: log = open(logfilename, "a") log.write(linesep + "\tPreparing the work plan...") log.close() im = tdf.read_tomo(dset, 0).astype(float32) outshape = tdf.get_dset_shape(im.shape[1], im.shape[0], num_proj) f_out = getHDF5(outfile, 'w') f_out_dset = f_out.create_dataset('exchange/data', outshape, float32) f_out_dset.attrs['min'] = str(amin(im[:])) f_out_dset.attrs['max'] = str(amax(im[:])) f_out_dset.attrs['version'] = '1.0' f_out_dset.attrs['axes'] = "y:theta:x" f_in.close() f_out.close() if (method == 0): # Paganin 2020: plan = tiehom_plan(im, param1, param2, energy, distance, pixsize, pad) elif (method == 1): # Paganin 2020: plan = tiehom_plan2020(im, param1, param2, energy, distance, pixsize, pad) else: plan = phrt_plan(im, energy, distance, pixsize, param2, param1, method, pad) # Run several threads for independent computation without waiting for threads completion: for num in range(nr_threads): start = (num_proj / nr_threads) * num if (num == nr_threads - 1): end = num_proj - 1 else: end = (num_proj / nr_threads) * (num + 1) - 1 Process(target=_process, args=(lock, start, end, infile, outfile, outshape, float32, method, plan, logfilename)).start()
def process(sino_idx, num_sinos, infile, outfile, preprocessing_required, corr_plan, skipflat, norm_sx, norm_dx, flat_end, half_half, half_half_line, ext_fov, ext_fov_rot_right, ext_fov_overlap, ext_fov_normalize, ext_fov_average, ringrem, phaseretrieval_required, phrtmethod, phrt_param1, phrt_param2, energy, distance, pixsize, phrtpad, approx_win, angles, angles_projfrom, angles_projto, offset, logtransform, recpar, circle, scale, pad, method, rolling, roll_shift, zerone_mode, dset_min, dset_max, decim_factor, downsc_factor, corr_offset, postprocess_required, polarfilt_opt, convert_opt, crop_opt, dynamic_ff, EFF, filtEFF, im_dark, nr_threads, logfilename, tmppath): """To do... """ # Perform reconstruction (on-the-fly preprocessing and phase retrieval, if # required): if (phaseretrieval_required): # In this case a bunch of sinograms is loaded into memory: # # Load the temporary data structure reading the input TDF file. # To know the right dimension the first sinogram is pre-processed. # # Open the TDF file and get the dataset: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] # Downscaling and decimation factors considered when determining the # approximation window: zrange = arange(sino_idx - approx_win * downsc_factor / 2, sino_idx + approx_win * downsc_factor / 2, downsc_factor) zrange = zrange[(zrange >= 0)] zrange = zrange[(zrange < num_sinos)] approx_win = zrange.shape[0] # Approximation window cannot be odd: if (approx_win % 2 == 1): approx_win = approx_win - 1 zrange = zrange[0:approx_win] # Read one sinogram to get the proper dimensions: test_im = tdf.read_sino(dset, zrange[0]*downsc_factor).astype(float32) # Apply projection removal (if required): test_im = test_im[angles_projfrom:angles_projto, :] # Apply decimation and downscaling (if required): test_im = test_im[::decim_factor, ::downsc_factor] # Perform the pre-processing of the first sinogram to get the right # dimension: if (preprocessing_required): if not skipflat: if dynamic_ff: # Dynamic flat fielding with downsampling = 2: #test_im = dynamic_flat_fielding(test_im, zrange[0] / downsc_factor, EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) test_im = dynamic_flat_fielding(test_im, zrange[0] , EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) else: #test_im = flat_fielding(test_im, zrange[0] / downsc_factor, corr_plan, flat_end, half_half, # half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) test_im = flat_fielding(test_im, zrange[0], corr_plan, flat_end, half_half, half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: test_im = extfov_correction(test_im, ext_fov_rot_right, ext_fov_overlap / downsc_factor, ext_fov_normalize, ext_fov_average).astype(float32) if not skipflat and not dynamic_ff: test_im = ring_correction(test_im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line / decim_factor, ext_fov).astype(float32) else: test_im = ring_correction(test_im, ringrem, False, False, half_half, half_half_line / decim_factor, ext_fov).astype(float32) # Now we can allocate memory for the bunch of slices: tmp_im = empty((approx_win, test_im.shape[0], test_im.shape[1]), dtype=float32) tmp_im[0,:,:] = test_im # Reading all the the sinos from TDF file and close: for ct in range(1, approx_win): # Read the sinogram: test_im = tdf.read_sino(dset, zrange[ct]*downsc_factor).astype(float32) # Apply projection removal (if required): test_im = test_im[angles_projfrom:angles_projto, :] # Apply decimation and downscaling (if required): test_im = test_im[::decim_factor, ::downsc_factor] # Perform the pre-processing for each sinogram of the bunch: if (preprocessing_required): if not skipflat: if dynamic_ff: # Dynamic flat fielding with downsampling = 2: #test_im = dynamic_flat_fielding(test_im, zrange[ct] / downsc_factor, EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) test_im = dynamic_flat_fielding(test_im, zrange[ct], EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) else: #test_im = flat_fielding(test_im, zrange[ct] / downsc_factor, corr_plan, flat_end, half_half, # half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) test_im = flat_fielding(test_im, zrange[ct], corr_plan, flat_end, half_half, half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: test_im = extfov_correction(test_im, ext_fov_rot_right, ext_fov_overlap / downsc_factor, ext_fov_normalize, ext_fov_average).astype(float32) if not skipflat and not dynamic_ff: test_im = ring_correction(test_im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line / decim_factor, ext_fov).astype(float32) else: test_im = ring_correction(test_im, ringrem, False, False, half_half, half_half_line / decim_factor, ext_fov).astype(float32) tmp_im[ct,:,:] = test_im f_in.close() # Now everything has to refer to a downscaled dataset: sino_idx = ((zrange == sino_idx).nonzero()) # # Perform phase retrieval: # # Prepare the plan: if (phrtmethod == 0): # Paganin's: phrtplan = tiehom_plan(tmp_im[:,0,:], phrt_param1, phrt_param2, energy, distance, pixsize * downsc_factor, phrtpad) else: phrtplan = phrt_plan(tmp_im[:,0,:], energy, distance, pixsize * downsc_factor, phrt_param2, phrt_param1, phrtmethod, phrtpad) #phrtplan = prepare_plan (tmp_im[:,0,:], beta, delta, energy, distance, #pixsize*downsc_factor, padding=phrtpad) # Process each projection (whose height depends on the size of the bunch): for ct in range(0, tmp_im.shape[1]): #tmp_im[:,ct,:] = phase_retrieval(tmp_im[:,ct,:], phrtplan).astype(float32) if (phrtmethod == 0): tmp_im[:,ct,:] = tiehom(tmp_im[:,ct,:], phrtplan).astype(float32) else: tmp_im[:,ct,:] = phrt(tmp_im[:,ct,:], phrtplan, phrtmethod).astype(float32) # Extract the requested sinogram: im = tmp_im[sino_idx[0],:,:].squeeze() else: # Read only one sinogram: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] im = tdf.read_sino(dset,sino_idx * downsc_factor).astype(float32) f_in.close() # Apply projection removal (if required): im = im[angles_projfrom:angles_projto, :] # Apply decimation and downscaling (if required): im = im[::decim_factor,::downsc_factor] #sino_idx = sino_idx / downsc_factor # Downscaling for the index already applied # Perform the preprocessing of the sinogram (if required): if (preprocessing_required): if not skipflat: if dynamic_ff: # Dynamic flat fielding with downsampling = 2: im = dynamic_flat_fielding(im, sino_idx, EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) else: im = flat_fielding(im, sino_idx, corr_plan, flat_end, half_half, half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: im = extfov_correction(im, ext_fov_rot_right, ext_fov_overlap / downsc_factor, ext_fov_normalize, ext_fov_average) if not skipflat and not dynamic_ff: im = ring_correction(im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line / decim_factor, ext_fov) else: im = ring_correction(im, ringrem, False, False, half_half, half_half_line / decim_factor, ext_fov) # Additional ring removal before reconstruction: #im = boinhaibel(im, '11;') #im = munchetal(im, '5;1.8') #im = rivers(im, '13;') #im = raven(im, '11;0.8') #im = oimoen(im, '51;51') # Actual reconstruction: im = reconstruct(im, angles, offset / downsc_factor, logtransform, recpar, circle, scale, pad, method, zerone_mode, dset_min, dset_max, corr_offset, rolling, roll_shift, tmppath).astype(float32) # Apply post-processing (if required): if postprocess_required: im = polarfilter(im, polarfilt_opt) im = croprescale(im, convert_opt, crop_opt) else: # Create the circle mask for fancy output: if (circle == True): siz = im.shape[1] if siz % 2: rang = arange(-siz / 2 + 1, siz / 2 + 1) else: rang = arange(-siz / 2,siz / 2) x,y = meshgrid(rang,rang) z = x ** 2 + y ** 2 a = (z < (siz / 2 - int(round(abs(offset) / downsc_factor))) ** 2) im = im * a # Write down reconstructed preview file (file name modified with metadata): im = im.astype(float32) outfile = outfile + '_' + str(im.shape[1]) + 'x' + str(im.shape[0]) + '_' + str(amin(im)) + '$' + str(amax(im)) im.tofile(outfile)
def process(sino_idx, num_sinos, infile, outpath, preprocessing_required, corr_plan, norm_sx, norm_dx, flat_end, half_half, half_half_line, ext_fov, ext_fov_rot_right, ext_fov_overlap, ext_fov_normalize, ext_fov_average, ringrem, phaseretrieval_required, phrtmethod, phrt_param1, phrt_param2, energy, distance, pixsize, phrtpad, approx_win, angles, offset, logtransform, param1, circle, scale, pad, method, zerone_mode, dset_min, dset_max, decim_factor, downsc_factor, corr_offset, postprocess_required, convert_opt, crop_opt, nr_threads, angles_from, angles_to, logfilename, lock, slice_prefix): """To do... """ slice_nr = sino_idx # Perform reconstruction (on-the-fly preprocessing and phase retrieval, if required): if (phaseretrieval_required): # In this case a bunch of sinograms is loaded into memory: # # Load the temporary data structure reading the input TDF file. # To know the right dimension the first sinogram is pre-processed. # # Open the TDF file and get the dataset: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] # Downscaling and decimation factors considered when determining the approximation window: zrange = arange(sino_idx - approx_win*downsc_factor/2, sino_idx + approx_win*downsc_factor/2, downsc_factor) zrange = zrange[ (zrange >= 0) ] zrange = zrange[ (zrange < num_sinos) ] approx_win = zrange.shape[0] # Approximation window cannot be odd: if (approx_win % 2 == 1): approx_win = approx_win-1 zrange = zrange[0:approx_win] # Read one sinogram to get the proper dimensions: test_im = tdf.read_sino(dset, zrange[0]*downsc_factor).astype(float32) # Apply decimation and downscaling (if required): test_im = test_im[::decim_factor, ::downsc_factor] # Perform the pre-processing of the first sinogram to get the right dimension: if (preprocessing_required): test_im = flat_fielding (test_im, zrange[0], corr_plan, flat_end, half_half, half_half_line/decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: test_im = extfov_correction (test_im, ext_fov_rot_right, ext_fov_overlap/downsc_factor, ext_fov_normalize, ext_fov_average).astype(float32) test_im = ring_correction (test_im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line/decim_factor, ext_fov).astype(float32) # Now we can allocate memory for the bunch of slices: tmp_im = empty((approx_win, test_im.shape[0], test_im.shape[1]), dtype=float32) tmp_im[0,:,:] = test_im # Reading all the the sinos from TDF file and close: for ct in range(1, approx_win): test_im = tdf.read_sino(dset, zrange[ct]*downsc_factor).astype(float32) test_im = test_im[::decim_factor, ::downsc_factor] # Perform the pre-processing for each sinogram of the bunch: if (preprocessing_required): test_im = flat_fielding (test_im, zrange[ct], corr_plan, flat_end, half_half, half_half_line/decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: test_im = extfov_correction (test_im, ext_fov_rot_right, ext_fov_overlap/downsc_factor, ext_fov_normalize, ext_fov_average).astype(float32) test_im = ring_correction (test_im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line/decim_factor, ext_fov).astype(float32) tmp_im[ct,:,:] = test_im f_in.close() # Now everything has to refer to a downscaled dataset: sino_idx = ((zrange == sino_idx).nonzero()) # # Perform phase retrieval: # # Prepare the plan: if (phrtmethod == 0): # Paganin's: phrtplan = tiehom_plan (tmp_im[:,0,:], phrt_param1, phrt_param2, energy, distance, pixsize*downsc_factor, padding=phrtpad) else: phrtplan = phrt_plan (tmp_im[:,0,:], energy, distance, pixsize*downsc_factor, phrt_param2, phrt_param1, phrtmethod, padding=phrtpad) # Process each projection (whose height depends on the size of the bunch): for ct in range(0, tmp_im.shape[1]): if (phrtmethod == 0): tmp_im[:,ct,:] = tiehom(tmp_im[:,ct,:], phrtplan).astype(float32) else: tmp_im[:,ct,:] = phrt(tmp_im[:,ct,:], phrtplan, phrtmethod).astype(float32) # Extract the requested sinogram: im = tmp_im[sino_idx[0],:,:].squeeze() else: # Read only one sinogram: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] im = tdf.read_sino(dset,sino_idx * downsc_factor).astype(float32) f_in.close() # Downscale and decimate the sinogram: im = im[::decim_factor,::downsc_factor] #sino_idx = sino_idx/downsc_factor # Perform the preprocessing of the sinogram (if required): if (preprocessing_required): im = flat_fielding (im, sino_idx, corr_plan, flat_end, half_half, half_half_line/decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: test_im = extfov_correction (test_im, ext_fov_rot_right, ext_fov_overlap/downsc_factor, ext_fov_normalize, ext_fov_average).astype(float32) im = ring_correction (im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line/decim_factor, ext_fov) # Log infos: log = open(logfilename,"a") log.write(linesep + "\tPerforming reconstruction with multiple centers of rotation...") log.write(linesep + "\t--------------") log.close() # Split the computation into multiple processes: for num in range(nr_threads): start = ( (angles_to - angles_from + 1) / nr_threads)*num + angles_from if (num == nr_threads - 1): end = angles_to else: end = ( (angles_to - angles_from + 1) / nr_threads)*(num + 1) + angles_from - 1 Process(target=reconstruct, args=(im, angles, offset/downsc_factor, logtransform, param1, circle, scale, pad, method, zerone_mode, dset_min, dset_max, corr_offset, postprocess_required, convert_opt, crop_opt, start, end, outpath, slice_nr, downsc_factor, decim_factor, logfilename, lock, slice_prefix)).start()
def main(argv): """To do... """ lock = Lock() skip_flat = True first_done = False pyfftw_cache_disable() pyfftw_cache_enable() pyfftw_set_keepalive_time(1800) # Get the from and to number of files to process: idx = int(argv[0]) # Get full paths of input TDF and output TDF: infile = argv[1] outfile = argv[2] # Get the phase retrieval parameters: method = int(argv[3]) param1 = double(argv[4]) # param1( e.g. regParam, or beta) param2 = double(argv[5]) # param2( e.g. thresh or delta) energy = double(argv[6]) distance = double(argv[7]) pixsize = double(argv[8]) / 1000.0 # pixsixe from micron to mm: pad = True if argv[9] == "True" else False # Tmp path and log file: tmppath = argv[10] if not tmppath.endswith(sep): tmppath += sep logfilename = argv[11] # Open the HDF5 file and check it contains flat files: skipflat = False f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] if not "/flat" in f_in: skipflat = True else: dset = f_in['exchange/data'] if not "/exchange/data_white" in f_in: skipflat = True num_proj = tdf.get_nr_projs(dset) num_sinos = tdf.get_nr_sinos(dset) # Check if the HDF5 makes sense: if (num_proj == 0): log = open(logfilename, "a") log.write(linesep + "\tNo projections found. Process will end.") log.close() exit() # Get flats and darks from cache or from file: if not skipflat: try: corrplan = cache2plan(infile, tmppath) except Exception as e: #print "Error(s) when reading from cache" corrplan = extract_flatdark(f_in, True, logfilename) remove(logfilename) plan2cache(corrplan, infile, tmppath) # Read projection: im = tdf.read_tomo(dset, idx).astype(float32) f_in.close() # Apply simple flat fielding (if applicable): if not skipflat: if (isinstance(corrplan['im_flat_after'], ndarray) and isinstance(corrplan['im_flat'], ndarray) and isinstance(corrplan['im_dark'], ndarray) and isinstance(corrplan['im_dark_after'], ndarray)): if (idx < num_proj / 2): im = (im - corrplan['im_dark']) / ( abs(corrplan['im_flat'] - corrplan['im_dark']) + finfo(float32).eps) else: im = (im - corrplan['im_dark_after']) / ( abs(corrplan['im_flat_after'] - corrplan['im_dark_after']) + finfo(float32).eps) # Prepare plan: im = im.astype(float32) if (method == 0): # Paganin 2002: plan = tiehom_plan(im, param1, param2, energy, distance, pixsize, pad) im = tiehom(im, plan).astype(float32) elif (method == 1): # Paganin 2020: plan = tiehom_plan2020(im, param1, param2, energy, distance, pixsize, pad) im = tiehom2020(im, plan).astype(float32) else: plan = phrt_plan(im, energy, distance, pixsize, param2, param1, method, pad) im = phrt(im, plan, method).astype(float32) # Write down reconstructed preview file (file name modified with metadata): im = im.astype(float32) outfile = outfile + '_' + str(im.shape[1]) + 'x' + str( im.shape[0]) + '_' + str(nanmin(im)) + '$' + str(nanmax(im)) im.tofile(outfile)
def process(sino_idx, num_sinos, infile, outfile, preprocessing_required, corr_plan, skipflat, norm_sx, norm_dx, flat_end, half_half, half_half_line, ext_fov, ext_fov_rot_right, ext_fov_overlap, ext_fov_normalize, ext_fov_average, ringrem, phaseretrieval_required, phrtmethod, phrt_param1, phrt_param2, energy, distance, pixsize, phrtpad, approx_win, angles, angles_projfrom, angles_projto, offset, logtransform, recpar, circle, scale, pad, method, rolling, roll_shift, zerone_mode, dset_min, dset_max, decim_factor, downsc_factor, corr_offset, postprocess_required, polarfilt_opt, convert_opt, crop_opt, dynamic_ff, EFF, filtEFF, im_dark, nr_threads, logfilename, tmppath): """To do... """ # Perform reconstruction (on-the-fly preprocessing and phase retrieval, if # required): if (phaseretrieval_required): # In this case a bunch of sinograms is loaded into memory: # # Load the temporary data structure reading the input TDF file. # To know the right dimension the first sinogram is pre-processed. # # Open the TDF file and get the dataset: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] # Downscaling and decimation factors considered when determining the # approximation window: zrange = arange(sino_idx - approx_win * downsc_factor / 2, sino_idx + approx_win * downsc_factor / 2, downsc_factor) zrange = zrange[(zrange >= 0)] zrange = zrange[(zrange < num_sinos)] approx_win = zrange.shape[0] # Approximation window cannot be odd: if (approx_win % 2 == 1): approx_win = approx_win - 1 zrange = zrange[0:approx_win] # Read one sinogram to get the proper dimensions: test_im = tdf.read_sino(dset, zrange[0] * downsc_factor).astype(float32) # Apply projection removal (if required): test_im = test_im[angles_projfrom:angles_projto, :] # Apply decimation and downscaling (if required): test_im = test_im[::decim_factor, ::downsc_factor] # Perform the pre-processing of the first sinogram to get the right # dimension: if (preprocessing_required): if not skipflat: if dynamic_ff: # Dynamic flat fielding with downsampling = 2: #test_im = dynamic_flat_fielding(test_im, zrange[0] / downsc_factor, EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) test_im = dynamic_flat_fielding(test_im, zrange[0], EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) else: #test_im = flat_fielding(test_im, zrange[0] / downsc_factor, corr_plan, flat_end, half_half, # half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) test_im = flat_fielding(test_im, zrange[0], corr_plan, flat_end, half_half, half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: test_im = extfov_correction(test_im, ext_fov_rot_right, ext_fov_overlap / downsc_factor, ext_fov_normalize, ext_fov_average).astype(float32) if not skipflat and not dynamic_ff: test_im = ring_correction(test_im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line / decim_factor, ext_fov).astype(float32) else: test_im = ring_correction(test_im, ringrem, False, False, half_half, half_half_line / decim_factor, ext_fov).astype(float32) # Now we can allocate memory for the bunch of slices: tmp_im = empty((approx_win, test_im.shape[0], test_im.shape[1]), dtype=float32) tmp_im[0, :, :] = test_im # Reading all the the sinos from TDF file and close: for ct in range(1, approx_win): # Read the sinogram: test_im = tdf.read_sino(dset, zrange[ct] * downsc_factor).astype(float32) # Apply projection removal (if required): test_im = test_im[angles_projfrom:angles_projto, :] # Apply decimation and downscaling (if required): test_im = test_im[::decim_factor, ::downsc_factor] # Perform the pre-processing for each sinogram of the bunch: if (preprocessing_required): if not skipflat: if dynamic_ff: # Dynamic flat fielding with downsampling = 2: #test_im = dynamic_flat_fielding(test_im, zrange[ct] / downsc_factor, EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) test_im = dynamic_flat_fielding( test_im, zrange[ct], EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) else: #test_im = flat_fielding(test_im, zrange[ct] / downsc_factor, corr_plan, flat_end, half_half, # half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) test_im = flat_fielding(test_im, zrange[ct], corr_plan, flat_end, half_half, half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: test_im = extfov_correction( test_im, ext_fov_rot_right, ext_fov_overlap / downsc_factor, ext_fov_normalize, ext_fov_average).astype(float32) if not skipflat and not dynamic_ff: test_im = ring_correction(test_im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line / decim_factor, ext_fov).astype(float32) else: test_im = ring_correction(test_im, ringrem, False, False, half_half, half_half_line / decim_factor, ext_fov).astype(float32) tmp_im[ct, :, :] = test_im f_in.close() # Now everything has to refer to a downscaled dataset: sino_idx = ((zrange == sino_idx).nonzero()) # # Perform phase retrieval: # # Prepare the plan: if (phrtmethod == 0): # Paganin 2002: phrtplan = tiehom_plan(tmp_im[:, 0, :], phrt_param1, phrt_param2, energy, distance, pixsize * downsc_factor, phrtpad) elif (phrtmethod == 1): # Paganin 2020: phrtplan = tiehom_plan2020(tmp_im[:, 0, :], phrt_param1, phrt_param2, energy, distance, pixsize * downsc_factor, phrtpad) else: phrtplan = phrt_plan(tmp_im[:, 0, :], energy, distance, pixsize * downsc_factor, phrt_param2, phrt_param1, phrtmethod, phrtpad) #phrtplan = prepare_plan (tmp_im[:,0,:], beta, delta, energy, distance, #pixsize*downsc_factor, padding=phrtpad) # Process each projection (whose height depends on the size of the bunch): for ct in range(0, tmp_im.shape[1]): #tmp_im[:,ct,:] = phase_retrieval(tmp_im[:,ct,:], phrtplan).astype(float32) if (phrtmethod == 0): tmp_im[:, ct, :] = tiehom(tmp_im[:, ct, :], phrtplan).astype(float32) elif (phrtmethod == 1): tmp_im[:, ct, :] = tiehom2020(tmp_im[:, ct, :], phrtplan).astype(float32) else: tmp_im[:, ct, :] = phrt(tmp_im[:, ct, :], phrtplan, phrtmethod).astype(float32) # Extract the requested sinogram: im = tmp_im[sino_idx[0], :, :].squeeze() else: # Read only one sinogram: f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] else: dset = f_in['exchange/data'] im = tdf.read_sino(dset, sino_idx * downsc_factor).astype(float32) f_in.close() # Apply projection removal (if required): im = im[angles_projfrom:angles_projto, :] # Apply decimation and downscaling (if required): im = im[::decim_factor, ::downsc_factor] #sino_idx = sino_idx / downsc_factor # Downscaling for the index already applied # Perform the preprocessing of the sinogram (if required): if (preprocessing_required): if not skipflat: if dynamic_ff: # Dynamic flat fielding with downsampling = 2: im = dynamic_flat_fielding(im, sino_idx, EFF, filtEFF, 2, im_dark, norm_sx, norm_dx) else: im = flat_fielding(im, sino_idx, corr_plan, flat_end, half_half, half_half_line / decim_factor, norm_sx, norm_dx).astype(float32) if ext_fov: im = extfov_correction(im, ext_fov_rot_right, ext_fov_overlap / downsc_factor, ext_fov_normalize, ext_fov_average) if not skipflat and not dynamic_ff: im = ring_correction(im, ringrem, flat_end, corr_plan['skip_flat_after'], half_half, half_half_line / decim_factor, ext_fov) else: im = ring_correction(im, ringrem, False, False, half_half, half_half_line / decim_factor, ext_fov) # Additional ring removal before reconstruction: #im = boinhaibel(im, '11;') #im = munchetal(im, '5;1.8') #im = rivers(im, '13;') #im = raven(im, '11;0.8') #im = oimoen(im, '51;51') # Actual reconstruction: im = reconstruct(im, angles, offset / downsc_factor, logtransform, recpar, circle, scale, pad, method, zerone_mode, dset_min, dset_max, corr_offset, rolling, roll_shift, tmppath).astype(float32) # Apply post-processing (if required): if postprocess_required: im = polarfilter(im, polarfilt_opt) im = croprescale(im, convert_opt, crop_opt) else: # Create the circle mask for fancy output: if (circle == True): siz = im.shape[1] if siz % 2: rang = arange(-siz / 2 + 1, siz / 2 + 1) else: rang = arange(-siz / 2, siz / 2) x, y = meshgrid(rang, rang) z = x**2 + y**2 a = (z < (siz / 2 - int(round(abs(offset) / downsc_factor)))**2) im = im * a # Write down reconstructed preview file (file name modified with metadata): im = im.astype(float32) outfile = outfile + '_' + str(im.shape[1]) + 'x' + str( im.shape[0]) + '_' + str(amin(im)) + '$' + str(amax(im)) im.tofile(outfile)
def main(argv): """To do... """ lock = Lock() skip_flat = True first_done = False pyfftw_cache_disable() pyfftw_cache_enable() pyfftw_set_keepalive_time(1800) # Get the from and to number of files to process: idx = int(argv[0]) # Get full paths of input TDF and output TDF: infile = argv[1] outfile = argv[2] # Get the phase retrieval parameters: method = int(argv[3]) param1 = double(argv[4]) # param1( e.g. regParam, or beta) param2 = double(argv[5]) # param2( e.g. thresh or delta) energy = double(argv[6]) distance = double(argv[7]) pixsize = double(argv[8]) / 1000.0 # pixsixe from micron to mm: pad = True if argv[9] == "True" else False # Tmp path and log file: tmppath = argv[10] if not tmppath.endswith(sep): tmppath += sep logfilename = argv[11] # Open the HDF5 file and check it contains flat files: skipflat = False f_in = getHDF5(infile, 'r') if "/tomo" in f_in: dset = f_in['tomo'] if not "/flat" in f_in: skipflat = True else: dset = f_in['exchange/data'] if not "/exchange/data_white" in f_in: skipflat = True num_proj = tdf.get_nr_projs(dset) num_sinos = tdf.get_nr_sinos(dset) # Check if the HDF5 makes sense: if (num_proj == 0): log = open(logfilename,"a") log.write(linesep + "\tNo projections found. Process will end.") log.close() exit() # Get flats and darks from cache or from file: if not skipflat: try: corrplan = cache2plan(infile, tmppath) except Exception as e: #print "Error(s) when reading from cache" corrplan = extract_flatdark(f_in, True, logfilename) remove(logfilename) plan2cache(corrplan, infile, tmppath) # Read projection: im = tdf.read_tomo(dset,idx).astype(float32) f_in.close() # Apply simple flat fielding (if applicable): if not skipflat: if (isinstance(corrplan['im_flat_after'], ndarray) and isinstance(corrplan['im_flat'], ndarray) and isinstance(corrplan['im_dark'], ndarray) and isinstance(corrplan['im_dark_after'], ndarray)) : if (idx < num_proj/2): im = (im - corrplan['im_dark']) / (abs(corrplan['im_flat'] - corrplan['im_dark']) + finfo(float32).eps) else: im = (im - corrplan['im_dark_after']) / (abs(corrplan['im_flat_after'] - corrplan['im_dark_after']) + finfo(float32).eps) # Prepare plan: im = im.astype(float32) if (method == 0): # Paganin's: plan = tiehom_plan (im, param1, param2, energy, distance, pixsize, pad) im = tiehom(im, plan).astype(float32) else: plan = phrt_plan (im, energy, distance, pixsize, param2, param1, method, pad) im = phrt(im, plan, method).astype(float32) # Write down reconstructed preview file (file name modified with metadata): im = im.astype(float32) outfile = outfile + '_' + str(im.shape[1]) + 'x' + str(im.shape[0]) + '_' + str( nanmin(im)) + '$' + str( nanmax(im) ) im.tofile(outfile)