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]
Пример #2
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)
Пример #3
0
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
Пример #4
0
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
Пример #5
0
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