def estimate_center_by_correlation(params): """Use correlation to estimate center of rotation for tomography.""" def flat_correct(flat, radio): nonzero = np.where(radio != 0) result = np.zeros_like(radio) result[nonzero] = flat[nonzero] / radio[nonzero] # log(1) = 0 result[result <= 0] = 1 return np.log(result) first = read_image(get_filenames(params.projections)[0]).astype(np.float) last_index = params.start + params.number if params.number else -1 last = read_image(get_filenames(params.projections)[last_index]).astype(np.float) if params.darks and params.flats: dark = read_image(get_filenames(params.darks)[0]).astype(np.float) flat = read_image(get_filenames(params.flats)[0]) - dark first = flat_correct(flat, first - dark) last = flat_correct(flat, last - dark) height = params.height if params.height else -1 y_region = slice(params.y, min(params.y + height, first.shape[0]), params.y_step) first = first[y_region, :] last = last[y_region, :] return compute_rotation_axis(first, last)
def find_axis_corr(self, ctset, vcrop, y, height, multipage): indir = self.make_inpaths(ctset[0], ctset[1]) """Use correlation to estimate center of rotation for tomography.""" from scipy.signal import fftconvolve def flat_correct(flat, radio): nonzero = np.where(radio != 0) result = np.zeros_like(radio) result[nonzero] = flat[nonzero] / radio[nonzero] # log(1) = 0 result[result <= 0] = 1 return np.log(result) if multipage: with tifffile.TiffFile(get_filenames(indir[2])[0]) as tif: first = tif.pages[0].asarray().astype(np.float) with tifffile.TiffFile(get_filenames(indir[2])[-1]) as tif: last = tif.pages[-1].asarray().astype(np.float) with tifffile.TiffFile(get_filenames(indir[0])[-1]) as tif: dark = tif.pages[-1].asarray().astype(np.float) with tifffile.TiffFile(get_filenames(indir[1])[0]) as tif: flat1 = tif.pages[-1].asarray().astype(np.float) - dark else: first = read_image(get_filenames(indir[2])[0]).astype(np.float) last = read_image(get_filenames(indir[2])[-1]).astype(np.float) dark = read_image(get_filenames(indir[0])[-1]).astype(np.float) flat1 = read_image(get_filenames(indir[1])[-1]) - dark first = flat_correct(flat1, first - dark) if ctset[1] == 4: if multipage: with tifffile.TiffFile(get_filenames(indir[3])[0]) as tif: flat2 = tif.pages[-1].asarray().astype(np.float) - dark else: flat2 = read_image(get_filenames(indir[3])[-1]) - dark last = flat_correct(flat2, last - dark) else: last = flat_correct(flat1, last - dark) if vcrop: y_region = slice(y, min(y + height, first.shape[0]), 1) first = first[y_region, :] last = last[y_region, :] width = first.shape[1] first = first - first.mean() last = last - last.mean() conv = fftconvolve(first, last[::-1, :], mode='same') center = np.unravel_index(conv.argmax(), conv.shape)[1] return (width / 2.0 + center) / 2.0
def find_axis_std(self, ctset, tmpdir, ax_range, p_width, search_row, nviews): indir = self.make_inpaths(ctset[0], ctset[1]) print indir[2] image = read_image(get_filenames(indir[2])[0]) cmd = 'tofu lamino --absorptivity --fix-nan-and-inf --overall-angle 180'\ ' --lamino-angle 90 --height 2' cmd += ' --darks {} --flats {} --projections {}'.\ format(indir[0], indir[1], enquote(indir[2])) cmd += ' --number {}'.format(nviews) cmd += ' --angle {:0.5f}'.format(np.radians(180.0 / float(nviews))) if ctset[1] == 4: cmd += ' --flats2 {}'.format(indir[3]) out_pattern = os.path.join(tmpdir, "axis-search/sli") cmd += ' --output {}'.format(enquote(out_pattern)) cmd += ' --x-region={},{},{}'.format(-p_width / 2, p_width / 2, 1) cmd += ' --y-region={},{},{}'.format(-p_width / 2, p_width / 2, 1) cmd += ' --y {} --height 2'.format(search_row) cmd += ' --z-parameter x-center' cmd += ' --region={}'.format(enquote(ax_range)) cmd += ' --z 0' res = [float(num) for num in ax_range.split(',')] cmd += ' --axis {},{}'.format((res[0] + res[1]) / 2., 1.0) #middle of ax search range? cmd += " --output-bytes-per-file 0" # cmd += ' --delete-slice-dir' print cmd os.system(cmd) points, maximum = evaluate_images_simp(out_pattern + '*.tif', "msag") return res[0] + res[2] * maximum
def estimate_center_by_reconstruction(params): if params.projections is not None: raise RuntimeError("Cannot estimate axis from projections") sinos = sorted(glob.glob(os.path.join(params.sinograms, '*.tif'))) if not sinos: raise RuntimeError("No sinograms found in {}".format(params.sinograms)) # Use a sinogram that probably has some interesting data filename = sinos[len(sinos) / 2] sinogram = read_image(filename) initial_width = sinogram.shape[1] m0 = np.mean(np.sum(sinogram, axis=1)) center = initial_width / 2.0 width = initial_width / 2.0 new_center = center tmp_dir = tempfile.mkdtemp() tmp_output = os.path.join(tmp_dir, 'slice-0.tif') params.sinograms = filename params.output = os.path.join(tmp_dir, 'slice-%i.tif') def heaviside(A): return (A >= 0.0) * 1.0 def get_score(guess, m0): # Run reconstruction with new guess params.axis = guess tomo(params) # Analyse reconstructed slice result = read_image(tmp_output) Q_IA = float(np.sum(np.abs(result)) / m0) Q_IN = float(-np.sum(result * heaviside(-result)) / m0) LOG.info("Q_IA={}, Q_IN={}".format(Q_IA, Q_IN)) return Q_IA def best_center(center, width): trials = [center + (width / 4.0) * x for x in range(-2, 3)] scores = [(guess, get_score(guess, m0)) for guess in trials] LOG.info(scores) best = sorted(scores, cmp=lambda x, y: cmp(x[1], y[1])) return best[0][0] for i in range(params.num_iterations): LOG.info("Estimate iteration: {}".format(i)) new_center = best_center(new_center, width) LOG.info("Currently best center: {}".format(new_center)) width /= 2.0 try: os.remove(tmp_output) os.removedirs(tmp_dir) except OSError: LOG.info("Could not remove {} or {}".format(tmp_output, tmp_dir)) return new_center
def get_dims(pth, args): #must be changed if multipage tiff input!!! # get number of projections and projections dimensions if not args.bigtif_inp: tomos = get_filenames(pth) image = read_image(tomos[0]) return len(tomos), image.shape else: return args.nviews, [args.H, args.W]
def get_score(guess, m0): # Run reconstruction with new guess params.axis = guess tomo(params) # Analyse reconstructed slice result = read_image(tmp_output) Q_IA = float(np.sum(np.abs(result)) / m0) Q_IN = float(-np.sum(result * heaviside(-result)) / m0) LOG.info("Q_IA={}, Q_IN={}".format(Q_IA, Q_IN)) return Q_IA
def bad_vert_ROI(multipage, path2proj, y, height): if multipage: with tifffile.TiffFile(get_filenames(path2proj)[0]) as tif: proj = tif.pages[0].asarray().astype(np.float) else: proj = read_image(get_filenames(path2proj)[0]).astype(np.float) y_region = slice(y, min(y + height, proj.shape[0]), 1) proj = proj[y_region, :] if proj.shape[0] == 0: return True else: return False
def get_sinogram_reader(params): reader = get_file_reader(params) setup_read_task(reader, params.sinograms, params) image = read_image(get_first_filename(params.sinograms)) if len(image.shape) > 2: # this is a probably a multi TIFF/raw width, height = image.shape[2], image.shape[1] else: # this is a directory of sinograms width, height = image.shape[1], image.shape[0] return reader, width, height
def make_copy_of_flat(flatdir, flat_copy_name, dryrun): first_flat_file = get_first_filename(flatdir) try: shape = get_image_shape(first_flat_file) except: raise ValueError('Failed to determine size and number of flats in {}'.format(flatdir)) cmd = "" if len(shape) == 2: last_flat_file = get_filenames(flatdir)[-1] cmd = "cp {} {}".format(last_flat_file, flat_copy_name) else: flat = read_image(get_filenames(flatdir)[-1])[-1] if dryrun: cmd = "echo Will save a copy of flat into \"{}\"".format(flat_copy_name) else: tifffile.imsave(flat_copy_name, flat) return cmd
def evaluate(image, metrics_1d=None, metrics_2d=None, global_min=None, global_max=None, metrics_1d_kwargs=None, blur_fwhm=None): """Evaluate *metrics_1d* which work on a flattened image and *metrics_2d* in an *image* which can either be a file path or an imageIf the metrics are None all the default ones are used. *global_min* and *global_max* are the mean extrema of the whole sequence used to cut off outlier values. Extrema are used only by 1d metrics. *metrics_1d_kwargs* are additional keyword arguments passed to the functions, they are specified in dictioinary {func_name: kwargs}. """ if metrics_1d is None: metrics_1d = METRICS_1D if metrics_2d is None: metrics_2d = METRICS_2D results = {} if type(image) == str: image = read_image(image) if blur_fwhm: from scipy.ndimage import gaussian_filter image = gaussian_filter(image, blur_fwhm / (2 * np.sqrt(2 * np.log(2)))) if global_min is None or global_max is None: flattened = image.flatten() else: # Use global cutoff flattened = image[np.where((image >= global_min) & (image <= global_max))] if metrics_1d is not None: for metric in metrics_1d: kwargs = {} if metrics_1d_kwargs and metric in metrics_1d_kwargs: kwargs = metrics_1d_kwargs[metric] results[metric] = metrics_1d[metric](flattened, **kwargs) if metrics_2d is not None: for metric in metrics_2d: results[metric] = metrics_2d[metric](image) return results