def calculate_two_image_frc(image1, image2, args, z_correction=1): """ A simple utility to calculate a regular FRC with a two image input :param image: the image as an Image object :param args: the parameters for the FRC calculation. See *miplib.ui.frc_options* for details :return: returns the FRC result as a FourierCorrelationData object """ assert isinstance(image1, Image) assert isinstance(image2, Image) assert image1.shape == image2.shape frc_data = FourierCorrelationDataCollection() spacing = image1.spacing if not args.disable_hamming: image1 = Image(windowing.apply_hamming_window(image1), spacing) image2 = Image(windowing.apply_hamming_window(image2), spacing) # Run FRC iterator = iterators.FourierRingIterator(image1.shape, args.d_bin) frc_task = FRC(image1, image2, iterator) frc_data[0] = frc_task.execute() # Analyze results analyzer = fsc_analysis.FourierCorrelationAnalysis(frc_data, image1.spacing[0], args) return analyzer.execute(z_correction=z_correction)[0]
def calculate_two_image_sectioned_fsc(image1, image2, args, z_correction=1): assert isinstance(image1, Image) assert isinstance(image2, Image) image1 = Image(windowing.apply_hamming_window(image1), image1.spacing) image2 = Image(windowing.apply_hamming_window(image2), image2.spacing) iterator = iterators.AxialExcludeHollowConicalFourierShellIterator( image1.shape, args.d_bin, args.d_angle, args.d_extract_angle) fsc_task = DirectionalFSC(image1, image2, iterator) data = fsc_task.execute() analyzer = fsc_analysis.FourierCorrelationAnalysis(data, image1.spacing[0], args) return analyzer.execute(z_correction=z_correction)
def fft(array, interpolation=1.0, window='tukey', *kwargs): """ A n-dimensional Forward Discrete Fourier transform with some extra bells and whistles added on top of the standard Numpy method. :param array: the image to be transformed :type array: np.ndarray :param interpolation: Add "interpolation" to the FFT by zero-padding prior to transform. This is expressed as a multiple of the image size. :type interpolation: float :param window: a window function to apply. 'tukey' or 'hamming' :type window: str or None :return: the complex Fourier transform of the input array """ # Apply a Window if requested if window is None: pass elif window == 'tukey': array = windowing.apply_tukey_window(array, *kwargs) elif window == 'hamming': array = windowing.apply_hamming_window(array) # Add extra padding if interpolation > 1.0: new_shape = tuple(int(interpolation * i) for i in array.shape) array = ndarray.expand_to_shape(array, new_shape) # Transform forward array = np.fft.fftshift(np.fft.fftn(array)) return array
def calculate_one_image_sectioned_fsc(image, args, z_correction=1): """ A function to calculate one-image sectioned FSC. I assume here that prior to calling the function, the image is going to be in a correct shape, resampled to isotropic spacing and zero padded. If the image dimensions are wrong (not a cube) the function will return an error. :param image: a 3D image, with isotropic spacing and cubic shape :type image: Image :param options: options for the FSC calculation :type options: argparse options :param z_correction: correction, for anisotropic sampling. It is the ratio of axial vs. lateral spacing, defaults to 1 :type z_correction: float, optional :return: the resolution measurement results organized by rotation angle :rtype: FourierCorrelationDataCollection object """ assert isinstance(image, Image) assert all(s == image.shape[0] for s in image.shape) image1, image2 = imops.checkerboard_split(image) image1 = Image(windowing.apply_hamming_window(image1), image1.spacing) image2 = Image(windowing.apply_hamming_window(image2), image2.spacing) iterator = iterators.AxialExcludeHollowConicalFourierShellIterator( image1.shape, args.d_bin, args.d_angle, args.d_extract_angle) fsc_task = DirectionalFSC(image1, image2, iterator) data = fsc_task.execute() analyzer = fsc_analysis.FourierCorrelationAnalysis(data, image1.spacing[0], args) result = analyzer.execute(z_correction=z_correction) def func(x, a, b, c, d): return a * np.exp(c * (x - b)) + d params = [0.95988146, 0.97979108, 13.90441896, 0.55146136] for angle, dataset in result: point = dataset.resolution["resolution-point"][1] cut_off_correction = func(point, *params) dataset.resolution["spacing"] /= cut_off_correction dataset.resolution["resolution"] /= cut_off_correction return result
def find_image_shifts_frequency_domain(data, photosensor=0): """ Register all image in an ISM ArrayDetectorDAta dataset, with a single step frequency domain phase correlation based method. This might be slightly faster than the iterative method above (depending on the sampling strategy in the latter mainly), but usually does not work quite as well. :param data: ArrayDetectorData object with all the individual images :param photosensor: The photosensor number (from 0 upwards) that is to be processed :return: a three element tuple: x offset, y offset, transforms. The x and y offsets are expressed in physical units (um). The transforms are sitk.TranslationTransform objects that can be used to resample the images into a common coordinate system. """ assert isinstance(data, ArrayDetectorData) assert photosensor < data.ngates spacing = data[0, 0].spacing fixed_image = Image( apply_hamming_window(data[photosensor, int(floor(data.ndetectors / 2))]), spacing) x = [] y = [] transforms = [] for idx in range(data.ndetectors): moving_image = Image(apply_hamming_window(data[photosensor, idx]), spacing) y_new, x_new = registration.phase_correlation_registration( fixed_image, moving_image, verbose=True, resample=False) tfm = sitk.TranslationTransform(2) tfm.SetParameters((x_new, y_new)) x.append(x_new) y.append(y_new) transforms.append(tfm) return x, y, transforms
def calculate_single_image_frc(image, args, average=True, trim=True, z_correction=1): """ A simple utility to calculate a regular FRC with a single image input :param image: the image as an Image object :param args: the parameters for the FRC calculation. See *miplib.ui.frc_options* for details :return: returns the FRC result as a FourierCorrelationData object """ assert isinstance(image, Image) frc_data = FourierCorrelationDataCollection() # Hamming Windowing if not args.disable_hamming: spacing = image.spacing image = Image(windowing.apply_hamming_window(image), spacing) # Split and make sure that the images are the same siz image1, image2 = imops.checkerboard_split(image) #image1, image2 = imops.reverse_checkerboard_split(image) image1, image2 = imops.zero_pad_to_matching_shape(image1, image2) # Run FRC iterator = iterators.FourierRingIterator(image1.shape, args.d_bin) frc_task = FRC(image1, image2, iterator) frc_data[0] = frc_task.execute() if average: # Split and make sure that the images are the same size image1, image2 = imops.reverse_checkerboard_split(image) image1, image2 = imops.zero_pad_to_matching_shape(image1, image2) iterator = iterators.FourierRingIterator(image1.shape, args.d_bin) frc_task = FRC(image1, image2, iterator) frc_data[0].correlation["correlation"] *= 0.5 frc_data[0].correlation["correlation"] += 0.5 * frc_task.execute( ).correlation["correlation"] freqs = frc_data[0].correlation["frequency"].copy() def func(x, a, b, c, d): return a * np.exp(c * (x - b)) + d params = [0.95988146, 0.97979108, 13.90441896, 0.55146136] # Analyze results analyzer = fsc_analysis.FourierCorrelationAnalysis(frc_data, image1.spacing[0], args) result = analyzer.execute(z_correction=z_correction)[0] point = result.resolution["resolution-point"][1] log_correction = func(point, *params) result.resolution["spacing"] /= log_correction result.resolution["resolution"] /= log_correction return result
def calculate_single_image_sectioned_frc(image, args, rotation=45, orthogonal=True, trim=True): """ A function utility to calculate a single image FRC on a Fourier ring section. The section is defined by the section size d_angle (in args) and the section rotation. :param image: the image as an Image object :param args: the parameters for the FRC calculation. See *miplib.ui.frc_options* for details :param rotation: defines the orientation of the fourier ring section :param orthogonal: if True, FRC is calculated from two sections, oriented at rotation and rotation + 90 degrees :return: returns the FRC result as a FourierCorrelationData object """ assert isinstance(image, Image) frc_data = FourierCorrelationDataCollection() # Hamming Windowing if not args.disable_hamming: spacing = image.spacing image = Image(windowing.apply_hamming_window(image), spacing) # Run FRC def frc_helper(image1, image2, args, rotation): iterator = iterators.SectionedFourierRingIterator( image1.shape, args.d_bin, args.d_angle) iterator.angle = rotation frc_task = FRC(image1, image2, iterator) return frc_task.execute() image1, image2 = imops.checkerboard_split(image) image1, image2 = imops.zero_pad_to_matching_shape(image1, image2) image1_r, image2_r = imops.reverse_checkerboard_split(image) image1_r, image2_r = imops.zero_pad_to_matching_shape(image1_r, image2_r) pair_1 = frc_helper(image1, image2, args, rotation) pair_2 = frc_helper(image1_r, image2_r, args, rotation) pair_1.correlation["correlation"] * 0.5 pair_1.correlation[ "correlation"] += 0.5 * pair_2.correlation["correlation"] if orthogonal: pair_1_o = frc_helper(image1, image2, args, rotation + 90) pair_2_o = frc_helper(image1_r, image2_r, args, rotation + 90) pair_1_o.correlation["correlation"] * 0.5 pair_1_o.correlation[ "correlation"] += 0.5 * pair_2_o.correlation["correlation"] pair_1.correlation[ "correlation"] += 0.5 * pair_1_o.correlation["correlation"] frc_data[0] = pair_1 freqs = frc_data[0].correlation["frequency"].copy() def func(x, a, b, c, d): return a * np.exp(c * (x - b)) + d params = [0.95988146, 0.97979108, 13.90441896, 0.55146136] # Analyze results analyzer = fsc_analysis.FourierCorrelationAnalysis(frc_data, image1.spacing[0], args) result = analyzer.execute()[0] point = result.resolution["resolution-point"][1] log_correction = func(point, *params) result.resolution["spacing"] /= log_correction result.resolution["resolution"] /= log_correction return result