示例#1
0
    def _findCarrier(self, band0, band1, mask):
        band = band0 * band1
        ixf = abs(fft.fftshift(fft.fft2(fft.fftshift(band))))

        if self.debug:
            plt.figure()
            plt.title('Find carrier')
            plt.imshow((ixf - gaussian_filter(ixf, 20)) * mask)

        pyc0, pxc0 = self._findPeak((ixf - gaussian_filter(ixf, 20)) * mask)
        ixfz, Kx, Ky = self._zoomf(band, self.N, self._kx[pyc0, pxc0],
                                   self._ky[pyc0, pxc0], 50, self._dk * self.N)
        pyc, pxc = self._findPeak(abs(ixfz))

        if self.debug:
            plt.figure()
            plt.title('Zoon Find carrier')
            plt.imshow(abs(ixfz))

        kx = Kx[pxc]
        ky = Ky[pyc]

        otf_exclude_min_radius = 0.5
        otf_exclude_max_radius = 1.5

        kr = sqrt(self._kx**2 + self._ky**2)

        m = (kr < 2)
        otf = fft.fftshift(self._tfm(kr, m) + (1 - m))

        otf_mask = (kr > otf_exclude_min_radius) & (kr <
                                                    otf_exclude_max_radius)
        otf_mask_for_band_common_freq = fft.fftshift(
            otf_mask & scipy.ndimage.shift(otf_mask, (pyc0 -
                                                      (self.N // 2 + 1), pxc0 -
                                                      (self.N // 2 + 1)),
                                           order=0))
        band0_common = fft.ifft2(
            fft.fft2(band0) / otf * otf_mask_for_band_common_freq)

        xx = np.arange(-self.N / 2 * self._dx,
                       self.N / 2 * self._dx,
                       self._dx,
                       dtype=np.single)
        phase_shift_to_xpeak = exp(-1j * kx * xx * 2 * pi * self.NA /
                                   self.wavelength)
        phase_shift_to_ypeak = exp(-1j * ky * xx * 2 * pi * self.NA /
                                   self.wavelength)

        band1_common = fft.ifft2(
            fft.fft2(band1) / otf * otf_mask_for_band_common_freq) * np.outer(
                phase_shift_to_ypeak, phase_shift_to_xpeak)

        scaling = 1 / np.sum(band0_common * np.conjugate(band0_common))

        cross_corr_result = np.sum(band0_common * band1_common) * scaling

        ampl = np.abs(cross_corr_result) * 2
        phase = np.angle(cross_corr_result)
        return kx, ky, phase, ampl
示例#2
0
def fast_cfft2(x, axes=(-1, -2)):
    if len(x.shape) == 2:
        return fftshift(np.transpose(fft2(np.transpose(ifftshift(x)))))
    elif len(x.shape) == 3:
        y = ifftshift(x, axes=axes)
        y = fft2(y, axes=axes)
        y = fftshift(y, axes=axes)
        return y
    else:
        raise ValueError("x must be 2D or 3D")
示例#3
0
    def _refineCarrier(self, band0, band1, kx_in, ky_in):
        pxc0 = np.int(np.round(kx_in / self._dk) + self.N / 2)
        pyc0 = np.int(np.round(ky_in / self._dk) + self.N / 2)

        otf_exclude_min_radius = self.eta / 2
        otf_exclude_max_radius = 1.5

        m = (self._kr < 2)
        otf = fft.fftshift(self._tfm(self._kr, m) + (1 - m) * 0.0001)

        otf_mask = (self._kr > otf_exclude_min_radius) & (
            self._kr < otf_exclude_max_radius)
        otf_mask_for_band_common_freq = fft.fftshift(
            otf_mask & scipy.ndimage.shift(otf_mask, (pyc0 -
                                                      (self.N // 2), pxc0 -
                                                      (self.N // 2)),
                                           order=0))
        band0_common = fft.ifft2(
            fft.fft2(band0) / otf * otf_mask_for_band_common_freq)

        band1_common = fft.ifft2(
            fft.fft2(band1) / otf * otf_mask_for_band_common_freq)

        band = band0_common * band1_common

        mag = 25 * self.N / 256
        ixfz, Kx, Ky = self._zoomf(band, self.N, np.single(self._k[pxc0]),
                                   np.single(self._k[pyc0]), mag,
                                   self._dk * self.N)
        pyc, pxc = self._findPeak(abs(ixfz))

        if self.debug:
            plt.figure()
            plt.title('Zoom Find carrier')
            plt.imshow(abs(ixfz))

        kx = Kx[pxc]
        ky = Ky[pyc]

        xx = np.arange(-self.N / 2 * self._dx,
                       self.N / 2 * self._dx,
                       self._dx,
                       dtype=np.double)
        phase_shift_to_xpeak = exp(-1j * kx * xx * 2 * pi * self.NA /
                                   self.wavelength)
        phase_shift_to_ypeak = exp(-1j * ky * xx * 2 * pi * self.NA /
                                   self.wavelength)

        scaling = 1 / np.sum(band0_common * np.conjugate(band0_common))
        cross_corr_result = np.sum(band0_common * band1_common * np.outer(
            phase_shift_to_ypeak, phase_shift_to_xpeak)) * scaling

        ampl = np.abs(cross_corr_result) * 2
        phase = np.angle(cross_corr_result)
        return kx, ky, phase, ampl
 def reconstruct_fftw(self, img):
     imf = fft.fft2(img) * self._prefilter
     self._carray[:, 0:self.N // 2, 0:self.N // 2] = imf[:, 0:self.N // 2, 0:self.N // 2]
     self._carray[:, 0:self.N // 2, 3 * self.N // 2:2 * self.N] = imf[:, 0:self.N // 2, self.N // 2:self.N]
     self._carray[:, 3 * self.N // 2:2 * self.N, 0:self.N // 2] = imf[:, self.N // 2:self.N, 0:self.N // 2]
     self._carray[:, 3 * self.N // 2:2 * self.N, 3 * self.N // 2:2 * self.N] = imf[:, self.N // 2:self.N,
                                                                               self.N // 2:self.N]
     img2 = np.sum(np.real(fft.ifft2(self._carray)).real * self._reconfactor, 0)
     self._imgstore = img
     self._bigimgstore = fft.ifft2(fft.fft2(img2) * self._postfilter).real
     return self._bigimgstore
示例#5
0
def solve_spectral(Winit, expU, expT):
    B = fft2(Winit, axes=(0,1)) # (x,y,px,py) -> (λx,λy,px,py)
    B *= expT
    B = ifft2(B, axes=(0,1)) # (λx,λy,px,py) -> (x,y,px,py)
    B = fft2(B, axes=(2,3)) # (x,y,px,py) -> (x,y,θx,θy)
    B *= expU
    B = ifft2(B, axes=(2,3)) # (x,y,θx,θy) -> (x,y,px,py)
    B = fft2(B, axes=(0,1)) # (x,y,px,py) -> (λx,λy,px,py)
    B *= expT
    B = ifft2(B, axes=(0,1)) # (λx,λy,px,py) -> (x,y,px,py)
    return real(B) # to avoid python warning
示例#6
0
def translation(im0, im1):
    """Return translation vector to register images."""
    shape = im0.shape
    f0 = fft2(im0)
    f1 = fft2(im1)
    ir = abs(ifft2((f0 * f1.conjugate()) / (abs(f0) * abs(f1))))
    t0, t1 = np.unravel_index(np.argmax(ir), shape)
    if t0 > shape[0] // 2:
        t0 -= shape[0]
    if t1 > shape[1] // 2:
        t1 -= shape[1]
    return [t0, t1]
示例#7
0
def fast_cfft2(x):
    if len(x.shape) == 2:
        return fftshift(np.transpose(fft2(np.transpose(ifftshift(x)))))
    elif len(x.shape) == 3:
        y = ifftshift(x, (1, 2))
        y = np.transpose(y, (0, 2, 1))
        y = fft2(y)
        y = np.transpose(y, (0, 2, 1))
        y = fftshift(y, (1, 2))
        return y
    else:
        raise ValueError("x must be 2D or 3D")
示例#8
0
文件: util.py 项目: mdw771/beyond_dof
def fourier_ring_correlation(obj,
                             ref,
                             step_size=1,
                             save_path='frc',
                             save_mask=False):

    if not os.path.exists(save_path):
        os.makedirs(save_path)

    radius_max = int(min(obj.shape) / 2)
    f_obj = np_fftshift(fft2(obj))
    f_ref = np_fftshift(fft2(ref))
    f_prod = f_obj * np.conjugate(f_ref)
    f_obj_2 = np.real(f_obj * np.conjugate(f_obj))
    f_ref_2 = np.real(f_ref * np.conjugate(f_ref))
    radius_ls = np.arange(1, radius_max, step_size)
    fsc_ls = []
    np.save(os.path.join(save_path, 'radii.npy'), radius_ls)

    for rad in radius_ls:
        print(rad)
        if os.path.exists(
                os.path.join(save_path,
                             'mask_rad_{:04d}.tiff'.format(int(rad)))):
            mask = dxchange.read_tiff(
                os.path.join(save_path,
                             'mask_rad_{:04d}.tiff'.format(int(rad))))
        else:
            mask = generate_ring(obj.shape, rad, anti_aliasing=2)
            if save_mask:
                dxchange.write_tiff(
                    mask,
                    os.path.join(save_path,
                                 'mask_rad_{:04d}.tiff'.format(int(rad))),
                    dtype='float32',
                    overwrite=True)
        fsc = abs(np.sum(f_prod * mask))
        fsc /= np.sqrt(np.sum(f_obj_2 * mask) * np.sum(f_ref_2 * mask))
        fsc_ls.append(fsc)
        np.save(os.path.join(save_path, 'fsc.npy'), fsc_ls)

    matplotlib.rcParams['pdf.fonttype'] = 'truetype'
    fontProperties = {
        'family': 'serif',
        'serif': ['Times New Roman'],
        'weight': 'normal',
        'size': 12
    }
    plt.rc('font', **fontProperties)
    plt.plot(radius_ls.astype(float) / radius_ls[-1], fsc_ls)
    plt.xlabel('Spatial frequency (1 / Nyquist)')
    plt.ylabel('FRC')
    plt.savefig(os.path.join(save_path, 'frc.pdf'), format='pdf')
示例#9
0
def translation(im0, im1):
    """Return translation vector to register images."""
    shape = im0.shape
    f0 = fft2(im0)
    f1 = fft2(im1)
    ir = abs(ifft2((f0 * f1.conjugate()) / (abs(f0) * abs(f1))))
    t0, t1 = np.unravel_index(np.argmax(ir), shape)
    if t0 > shape[0] // 2:
        t0 -= shape[0]
    if t1 > shape[1] // 2:
        t1 -= shape[1]
    return [t0, t1]
 def reconstructframe_fftw(self, img, i):
     diff = img - self._imgstore[i, :, :]
     imf = fft.fft2(diff) * self._prefilter
     self._carray[0, 0:self.N // 2, 0:self.N // 2] = imf[0:self.N // 2, 0:self.N // 2]
     self._carray[0, 0:self.N // 2, 3 * self.N // 2:2 * self.N] = imf[0:self.N // 2, self.N // 2:self.N]
     self._carray[0, 3 * self.N // 2:2 * self.N, 0:self.N // 2] = imf[self.N // 2:self.N, 0:self.N // 2]
     self._carray[0, 3 * self.N // 2:2 * self.N, 3 * self.N // 2:2 * self.N] = imf[self.N // 2:self.N,
                                                                               self.N // 2:self.N]
     img2 = fft.ifft2(self._carray[0, :, :]).real * self._reconfactor[i, :, :]
     self._imgstore[i, :, :] = img
     self._bigimgstore = self._bigimgstore + fft.ifft2(fft.fft2(img2) * self._postfilter).real
     return self._bigimgstore
示例#11
0
def optimal_binary_image_subtraction(R,N,Pr,Pn,sr,sn):
    R_hat = fft.fft2(R)
    N_hat = fft.fft2(N)
    Pn_hat = fft.fft2(Pn)
    Pr_hat = fft.fft2(Pr)
    G_hat = (Pr_hat*N_hat - Pn_hat*R_hat) / np.sqrt((sr**2*abs(Pn_hat**2) + sn**2*abs(Pr_hat**2)))
    P_G_hat = (Pr_hat*Pn_hat) / np.sqrt((sr**2*abs(Pn_hat**2) + sn**2*abs(Pr_hat**2)))
    S_hat = G_hat*conj(P_G_hat)
    #S_hat = (conj(Pn_hat)*np.abs(Pr_hat)**2*N_hat - conj(Pr_hat)*np.abs(Pn_hat)**2*R_hat) / (sr**2*abs(Pn_hat**2) + sn**2*abs(Pr_hat**2))
    S = fft.ifft2(S_hat)
    G = fft.ifft2(G_hat)
    P_G = real(fft.ifft2(P_G_hat))
    return S/std(S[15::30,15::30]), G/std(G[15::30,15::30]), P_G / sum(P_G)
示例#12
0
def multislice_propagate_batch_numpy(grid_delta_batch, grid_beta_batch, probe_real, probe_imag, energy_ev, psize_cm, free_prop_cm=None, obj_batch_shape=None):

    minibatch_size = obj_batch_shape[0]
    grid_shape = obj_batch_shape[1:]
    voxel_nm = np.array([psize_cm] * 3) * 1.e7
    wavefront = np.zeros([minibatch_size, obj_batch_shape[1], obj_batch_shape[2]], dtype='complex64')
    wavefront += (probe_real + 1j * probe_imag)

    lmbda_nm = 1240. / energy_ev
    mean_voxel_nm = np.prod(voxel_nm) ** (1. / 3)
    size_nm = np.array(grid_shape) * voxel_nm

    n_slice = obj_batch_shape[-1]
    delta_nm = voxel_nm[-1]

    # h = get_kernel_ir(delta_nm, lmbda_nm, voxel_nm, grid_shape)
    h = get_kernel(delta_nm, lmbda_nm, voxel_nm, grid_shape)
    k = 2. * PI * delta_nm / lmbda_nm

    probe_array = []

    for i in range(n_slice):
        delta_slice = grid_delta_batch[:, :, :, i]
        beta_slice = grid_beta_batch[:, :, :, i]
        c = np.exp(1j * k * delta_slice) * np.exp(-k * beta_slice)
        wavefront = wavefront * c
        if i < n_slice - 1:
            wavefront = ifft2(np_ifftshift(np_fftshift(fft2(wavefront), axes=[1, 2]) * h, axes=[1, 2]))
        probe_array.append(wavefront)

    if free_prop_cm is not None:
        #1dxchange.write_tiff(abs(wavefront), '2d_1024/monitor_output/wv', dtype='float32', overwrite=True)
        if free_prop_cm == 'inf':
            wavefront = np_fftshift(fft2(wavefront), axes=[1, 2])
        else:
            dist_nm = free_prop_cm * 1e7
            l = np.prod(size_nm)**(1. / 3)
            crit_samp = lmbda_nm * dist_nm / l
            algorithm = 'TF' if mean_voxel_nm > crit_samp else 'IR'
            # print(algorithm)
            algorithm = 'TF'
            if algorithm == 'TF':
                h = get_kernel(dist_nm, lmbda_nm, voxel_nm, grid_shape)
                wavefront = ifft2(np_ifftshift(np_fftshift(fft2(wavefront), axes=[1, 2]) * h, axes=[1, 2]))
            else:
                h = get_kernel_ir(dist_nm, lmbda_nm, voxel_nm, grid_shape)
                wavefront = ifft2(np_ifftshift(np_fftshift(fft2(wavefront), axes=[1, 2]) * h, axes=[1, 2]))
            # dxchange.write_tiff(abs(wavefront), '2d_512/monitor_output/wv', dtype='float32', overwrite=True)
            # dxchange.write_tiff(np.angle(h), '2d_512/monitor_output/h', dtype='float32', overwrite=True)

    return wavefront, np.array(probe_array)
示例#13
0
文件: util.py 项目: mdw771/beyond_dof
def get_kernel_ir(dist_nm, lmbda_nm, voxel_nm, grid_shape):
    """
    Get Fresnel propagation kernel for IR algorithm.

    Parameters:
    -----------
    simulator : :class:`acquisition.Simulator`
        The Simulator object.
    dist : float
        Propagation distance in cm.
    """
    size_nm = np.array(voxel_nm) * np.array(grid_shape)
    k = 2 * PI / lmbda_nm
    ymin, xmin = np.array(size_nm)[:2] / -2.
    dy, dx = voxel_nm[0:2]
    x = np.arange(xmin, xmin + size_nm[1], dx)
    y = np.arange(ymin, ymin + size_nm[0], dy)
    x, y = np.meshgrid(x, y)
    try:
        h = np.exp(1j * k * dist_nm) / (1j * lmbda_nm * dist_nm) * np.exp(
            1j * k / (2 * dist_nm) * (x**2 + y**2))
        H = np_fftshift(fft2(h)) * voxel_nm[0] * voxel_nm[1]
        dxchange.write_tiff(x,
                            '2d_512/monitor_output/x',
                            dtype='float32',
                            overwrite=True)
    except:
        h = tf.exp(1j * k * dist_nm) / (1j * lmbda_nm * dist_nm) * tf.exp(
            1j * k / (2 * dist_nm) * (x**2 + y**2))
        # h = tf.convert_to_tensor(h, dtype='complex64')
        H = fftshift(tf.fft2d(h)) * voxel_nm[0] * voxel_nm[1]

    return H
示例#14
0
def _rapsd(X):
    """Compute radially averaged PSD of input field X.
    """
    
    if X.shape[0] != X.shape[1]:
        raise ValueError("a square array expected, but the shape of X is (%d,%d)" % \
                         (X.shape[0], X.shape[1]))
    
    L = X.shape[0]
    
    if L % 2 == 1:
        XC,YC = np.ogrid[-int(L/2):int(L/2)+1, -int(L/2):int(L/2)+1]
    else:
        XC,YC = np.ogrid[-int(L/2):int(L/2), -int(L/2):int(L/2)]
    
    R = np.sqrt(XC*XC + YC*YC).astype(int)
    
    F = fft.fftshift(fft.fft2(X, **fft_kwargs))
    F = abs(F)**2
    
    if L % 2 == 0:
        r_range = np.arange(0, int(L/2)+1)
    else:
        r_range = np.arange(0, int(L/2))
    
    result = []
    for r in r_range:
        MASK = R == r
        F_vals = F[MASK]
        result.append(np.mean(F_vals))
    
    return np.array(result)
示例#15
0
def downsample(stack, n, mask=None, stack_in_fourier=False):
    """ Use Fourier methods to change the sample interval and/or aspect ratio
        of any dimensions of the input image 'img'. If the optional argument
        stack is set to True, then the *first* dimension of 'img' is interpreted as the index of
        each image in the stack. The size argument side is an integer, the size of the
        output images.  Let the size of a stack
        of 2D images 'img' be n1 x n1 x k.  The size of the output will be side x side x k.

        If the optional mask argument is given, this is used as the
        zero-centered Fourier mask for the re-sampling. The size of mask should
        be the same as the output image size. For example for downsampling an
        n0 x n0 image with a 0.9 x nyquist filter, do the following:
        msk = fuzzymask(n,2,.45*n,.05*n)
        out = downsample(img, n, 0, msk)
        The size of the mask must be the size of output. The optional fx output
        argument is the padded or cropped, masked, FT of in, with zero
        frequency at the origin.
    """

    size_in = np.square(stack.shape[1])
    size_out = np.square(n)
    mask = 1 if mask is None else mask
    num_images = stack.shape[0]
    output = np.zeros((num_images, n, n), dtype='float32')
    images_batches = np.array_split(np.arange(num_images), 10)
    for batch in images_batches:
        curr_batch = np.array(stack[batch])
        curr_batch = curr_batch if stack_in_fourier else fft2(curr_batch)
        fx = common.crop(np.fft.fftshift(curr_batch, axes=(-2, -1)),
                         (-1, n, n)) * mask
        output[batch] = ifft2(np.fft.ifftshift(
            fx, axes=(-2, -1))) * (size_out / size_in)
        print('finished {}/{}'.format(batch[-1] + 1, num_images))
    return output
示例#16
0
def decomposition_fft(X, filter, **kwargs):
    """Decompose a 2d input field into multiple spatial scales by using the Fast 
    Fourier Transform (FFT) and a bandpass filter.
    
    Parameters
    ----------
    X : array_like
      Two-dimensional array containing the input field. All values are required 
      to be finite.
    filter : dict
      A filter returned by any method implemented in bandpass_filters.py.
    
    Other Parameters
    ----------------
    MASK : array_like
      Optional mask to use for computing the statistics for the cascade levels. 
      Pixels with MASK==False are excluded from the computations.
    
    Returns
    -------
    out : ndarray
      A dictionary described in the module documentation. The parameter n is 
      determined from the filter (see bandpass_filters.py).
    
    """
    MASK = kwargs.get("MASK", None)

    if len(X.shape) != 2:
        raise ValueError("the input is not two-dimensional array")
    if MASK is not None and MASK.shape != X.shape:
        raise ValueError("dimension mismatch between X and MASK: X.shape=%s, MASK.shape=%s" % \
          (str(X.shape), str(MASK.shape)))
    if X.shape != filter["weights_2d"].shape[1:3]:
        raise ValueError(
            "dimension mismatch between X and filter: X.shape=%s, filter['weights_2d'].shape[1:3]=%s"
            % (str(X.shape), str(filter["weights_2d"].shape[1:3])))
    if np.any(~np.isfinite(X)):
        raise ValueError("X contains non-finite values")

    result = {}
    means = []
    stds = []

    F = fft.fftshift(fft.fft2(X, **fft_kwargs))
    X_decomp = []
    for k in range(len(filter["weights_1d"])):
        W_k = filter["weights_2d"][k, :, :]
        X_ = np.real(fft.ifft2(fft.ifftshift(F * W_k), **fft_kwargs))
        X_decomp.append(X_)

        if MASK is not None:
            X_ = X_[MASK]
        means.append(np.mean(X_))
        stds.append(np.std(X_))

    result["cascade_levels"] = np.stack(X_decomp)
    result["means"] = means
    result["stds"] = stds

    return result
示例#17
0
def _rapsd(X):
    """Compute radially averaged PSD of input field X.
    """

    if len(X.shape) != 2:
        raise ValueError("%i dimensions are found, but the number of dimensions should be 2" % \
                         len(X.shape))

    M, N = X.shape

    YC, XC = _compute_centred_coord_array(M, N)

    R = np.sqrt(XC * XC + YC * YC).astype(int)

    F = fft.fftshift(fft.fft2(X, **fft_kwargs))
    F = abs(F)**2

    L = max(X.shape[0], X.shape[1])

    if L % 2 == 0:
        r_range = np.arange(0, int(L / 2) + 1)
    else:
        r_range = np.arange(0, int(L / 2))

    result = []
    for r in r_range:
        MASK = R == r
        F_vals = F[MASK]
        result.append(np.mean(F_vals))

    return np.array(result)
示例#18
0
def _get_ang_scale(ims, bgval, exponent='inf', constraints=None, reports=None):
    """
    Given two images, return their scale and angle difference.

    Args:
        ims (2-tuple-like of 2D ndarrays): The images
        bgval: We also pad here in the :func:`map_coordinates`
        exponent (float or 'inf'): The exponent stuff, see :func:`similarity`
        constraints (dict, optional)
        reports (optional)

    Returns:
        tuple: Scale, angle. Describes the relationship of
        the subject image to the first one.
    """
    assert len(ims) == 2, \
        "Only two images are supported as input"
    shape = ims[0].shape

    ims_apod = [utils._apodize(im) for im in ims]

    dfts = [
        fft.fftshift(
            fft.fft2(im,
                     threads=4,
                     overwrite_input=True,
                     auto_align_input=True,
                     auto_contiguous=True,
                     planner_effort='FFTW_ESTIMATE')) for im in ims_apod
    ]

    filt = _logpolar_filter(shape)
    dfts = [dft * filt for dft in dfts]

    # High-pass filtering used to be here, but we have moved it to a higher
    # level interface

    pcorr_shape = _get_pcorr_shape(shape)
    log_base = _get_log_base(shape, pcorr_shape[1])
    stuffs = [_logpolar(np.abs(dft), pcorr_shape, log_base) for dft in dfts]

    (arg_ang, arg_rad), success = _phase_correlation(stuffs[0], stuffs[1],
                                                     utils.argmax_angscale,
                                                     log_base, exponent,
                                                     constraints, reports)

    angle = -np.pi * arg_ang / float(pcorr_shape[0])
    angle = np.rad2deg(angle)
    angle = utils.wrap_angle(angle, 360)
    scale = log_base**arg_rad

    angle = -angle
    scale = 1.0 / scale

    if not 0.5 < scale < 2:
        raise ValueError(
            "Images are not compatible. Scale change %g too big to be true." %
            scale)

    return scale, angle
示例#19
0
def phrt(im, plan, method=4, nr_threads=2):
    """Process a tomographic projection image with the selected phase retrieval algorithm.

	Parameters
	----------
	im : array_like
		Flat corrected image data as numpy array.

	plan : structure
		Structure with pre-computed data (see prepare_plan function)

	method : int 
		Phase retrieval filter {1 = TIE (default), 2 = CTF, 3 = CTF first-half sine, 4 = Quasiparticle, 
		5 = Quasiparticle first half sine}.

	nr_threads : int 
		Number of threads to be used in the computation of FFT by PyFFTW

	Credits
	-------
	Julian Moosmann, KIT (Germany) is acknowledged for this code
		
	"""
    # Extract plan values:
    dim0_o = plan['dim0']
    dim1_o = plan['dim1']
    n_pad0 = plan['npad0']
    n_pad1 = plan['npad1']
    marg0 = (n_pad0 - dim0_o) / 2
    marg1 = (n_pad1 - dim1_o) / 2
    filter = plan['filter']

    # Pad image (if required):
    im = padImage(im, n_pad0, n_pad1)

    # (Un)comment the following two lines to use PyFFTW:
    n_byte_align(im, simd_alignment)
    im = fft2(im - 1, threads=nr_threads)

    # (Un)comment the following line to use NumPy:
    #im = fft2(im - 1)

    # Apply phase retrieval filter:
    im = filter * im

    # (Un)comment the following two lines to use PyFFTW:
    n_byte_align(im, simd_alignment)
    im = real(ifft2(im, threads=nr_threads))

    # (Un)comment the following line to use NumPy:
    #im = real(ifft2(im))

    # Return the negative:
    im = -im

    # Return cropped output:
    return im[marg0:dim0_o + marg0, marg1:dim1_o + marg1]
示例#20
0
def phrt(im, plan, method=4, nr_threads=2):
	"""Process a tomographic projection image with the selected phase retrieval algorithm.

	Parameters
	----------
	im : array_like
		Flat corrected image data as numpy array.

	plan : structure
		Structure with pre-computed data (see prepare_plan function)

	method : int 
		Phase retrieval filter {1 = TIE (default), 2 = CTF, 3 = CTF first-half sine, 4 = Quasiparticle, 
		5 = Quasiparticle first half sine}.

	nr_threads : int 
		Number of threads to be used in the computation of FFT by PyFFTW

	Credits
	-------
	Julian Moosmann, KIT (Germany) is acknowledged for this code
		
	"""
	# Extract plan values:
	dim0_o = plan['dim0']
	dim1_o = plan['dim1']
	n_pad0 = plan['npad0']
	n_pad1 = plan['npad1']
	marg0  = (n_pad0 - dim0_o) / 2
	marg1  = (n_pad1 - dim1_o) / 2
	filter = plan['filter']	
	
	# Pad image (if required):	
	im  = padImage(im, n_pad0, n_pad1) 

	# (Un)comment the following two lines to use PyFFTW:
	n_byte_align(im, simd_alignment) 
	im = fft2(im - 1, threads=nr_threads)			

	# (Un)comment the following line to use NumPy:	
	#im = fft2(im - 1)			

	# Apply phase retrieval filter:
	im = filter * im   

	# (Un)comment the following two lines to use PyFFTW:
	n_byte_align(im, simd_alignment)
	im = real(ifft2(im, threads=nr_threads))	

	# (Un)comment the following line to use NumPy:	
	#im = real(ifft2(im))	

	# Return the negative:
	im = - im

	# Return cropped output:
	return im[marg0:dim0_o + marg0, marg1:dim1_o + marg1]   
示例#21
0
文件: coad.py 项目: VirangParekh/ZiP
def coad_func(j,base_psfcat, base_sexcat):
    # j is the jth coadded image
    psf_dat, psf_hed, sexcat2, psfcat2 = get_psf(j)
    x_fratio, y_fratio, fratio, dx, dy = get_fratio(base_psfcat, psfcat2, base_sexcat, sexcat2) 
    R_j = fits.getdata(j)

    R_j_hat = fft.fft2(R_j)

    _, PSF = chop_kern(R_j, psf_dat, psf_hed,1,1)
    P_j =  PSF[0]
    #print(P_j.shape)
    P_j_hat = fft.fft2(P_j)
    P_j_hat_bar = np.conj(P_j_hat)
    
    F_j = 1.0/np.median(fratio) #Zeropoint flux
    sig_j_2 = np.std(R_j)**2

    Nomin = (F_j/sig_j_2) * P_j_hat_bar * R_j_hat
    Denom = (F_j**2/sig_j_2) * np.abs(P_j_hat**2)
    subprocess.call(['rm', sexcat2, psfcat2, sexcat2.replace('.fits', '.psf')])
    return(Nomin, Denom)
示例#22
0
def generate_signals(
    shape: tuple,
    specs: list[CompanionSpec],
    template: np.ndarray,
    derotation_angles: np.ndarray = None,
    template_scale_factors: Union[np.ndarray, float, None] = None,
):
    '''Inject signals for companions specified using
    optional derotation angles to *counter*rotate the coordinates
    before injection, such that rotation CCW (e.g. by `derotate_cube`)
    aligns 0 deg PA with +Y

    Parameters
    ----------
    shape : tuple[int,int,int]
    specs : list[CompanionSpec]
    template : np.ndarray
    derotation_angles : Optional[np.ndarray]
    template_scale_factors : Union[np.ndarray,float,None]
        Scale factor relative to 1.0 being the average brightness
        of the primary over the observation, used to scale the
        template image to reflect particularly sharp or poor
        AO correction

    Returns
    -------
    outcube : np.ndarray
    '''

    outcube = np.zeros(shape, dtype=template.dtype)
    n_obs = shape[0]
    template = improc.shift2(template, 0, 0, output_shape=shape[1:])
    ft_template = fft.fft2(template)
    xfreqs = fft.fftfreq(shape[2])
    yfreqs = fft.fftfreq(shape[1])
    if template_scale_factors is None:
        template_scale_factors = np.ones(n_obs)
    if np.isscalar(template_scale_factors):
        template_scale_factors = np.repeat(np.array([template_scale_factors]),
                                           n_obs)
    if derotation_angles is None:
        derotation_angles = np.zeros(n_obs)
    for spec in specs:
        theta = np.deg2rad(90 + spec.pa_deg - derotation_angles)
        for i in range(n_obs):
            dx = spec.r_px * np.cos(theta[i])
            dy = spec.r_px * np.sin(theta[i])
            shifter = np.exp(2j * np.pi * ((-dx * xfreqs[np.newaxis, :]) +
                                           (-dy * yfreqs[:, np.newaxis])))
            cube_contribution = fft.ifft2(ft_template * shifter).real
            cube_contribution *= template_scale_factors[i] * spec.scale
            outcube[i] += cube_contribution
    return outcube
示例#23
0
    def _coarseFindCarrier(self, band0, band1, mask):
        otf_exclude_min_radius = self.eta / 2  # Min Radius of the circular region around DC that is to be excluded from the cross-correlation calculation
        maskhpf = fft.fftshift(self._kr > otf_exclude_min_radius)

        band0_common = fft.ifft2(fft.fft2(band0) * maskhpf)
        # band1_common = fft.ifft2(fft.fft2(band1)*maskhpf)
        ix = band0_common * band1

        ixf = np.abs(fft.fftshift(fft.fft2(fft.fftshift(ix))))

        if self.debug:
            plt.figure()
            plt.title('Find carrier')
            plt.imshow(ixf, cmap=plt.get_cmap('gray'))

        # pyc0, pxc0 = self._findPeak((ixf - gaussian_filter(ixf, 20)) * mask)
        pyc0, pxc0 = self._findPeak(ixf * mask)
        kx = self._dk * (pxc0 - self.N / 2)
        ky = self._dk * (pyc0 - self.N / 2)

        return kx, ky
示例#24
0
def fresnel_propagate_numpy(wavefront, energy_ev, psize_cm, dist_cm):

    lmbda_nm = 1240. / energy_ev
    lmbda_cm = 0.000124 / energy_ev
    psize_nm = psize_cm * 1e7
    dist_nm = dist_cm * 1e7
    if dist_cm == 'inf':
        wavefront = np_fftshift(fft2(wavefront))
    else:
        n = np.mean(wavefront.shape)
        z_crit_cm = (psize_cm * n)**2 / (lmbda_cm * n)
        algorithm = 'TF' if dist_cm < z_crit_cm else 'IR'
        if algorithm == 'TF':
            h = get_kernel(dist_nm, lmbda_nm, [psize_nm, psize_nm],
                           wavefront.shape)
            wavefront = ifft2(np_ifftshift(np_fftshift(fft2(wavefront)) * h))
        else:
            h = get_kernel_ir(dist_nm, lmbda_nm, [psize_nm, psize_nm],
                              wavefront.shape)
            wavefront = np_ifftshift(ifft2(np_fftshift(fft2(wavefront)) * h))

    return wavefront
示例#25
0
def im_cov(im):  # image isotrope covariance function based on fft
    cov = np.real(fft.fftshift(fft.ifft2(np.absolute(fft.fft2(im))**
                                         2))) / im.size
    print(cov.shape)
    cov1 = cov[int(np.shape(cov)[0] / 2 + 0.5), int(np.shape(cov)[1] / 2):]
    cov2 = np.flip(cov[int(np.shape(cov)[0] / 2 +
                           0.5), :int(np.shape(cov)[1] / 2 + 0.5)])
    cov3 = cov[int(np.shape(cov)[1] / 2):, int(np.shape(cov)[0] / 2 + 0.5)]
    cov4 = np.flip(cov[:int(np.shape(cov)[1] / 2 + 0.5),
                       int(np.shape(cov)[0] / 2 + 0.5)])
    cov = (cov1 + cov2 + cov3 + cov4) / 4
    lags = np.arange(np.shape(cov)[0]) + 0.5
    return lags, cov  # x and y of the cov function
示例#26
0
def lens(wf, focal=660, lens_method='proper', offset_before=0, offset_after=0, **conf):
    
    # propagation before lens
    proper.prop_propagate(wf, focal + offset_before)
    # Fourier transform of an image using a lens
    if lens_method == 'proper':
        proper.prop_lens(wf, focal)
    elif lens_method == 'numpy':
        wf._wfarr = fft.fft2(wf._wfarr)/wf._ngrid
    elif lens_method == 'pyfftw':
        wf._wfarr = fftw.fft2(wf._wfarr)/wf._ngrid
    # propagation after lens
    proper.prop_propagate(wf, focal + offset_after)
示例#27
0
def usecorrelation( im1, im2 ):
	"""Assess the offset (to be used for e.g. the assessment of the center of rotation or the 
	ovarlap) by computation the peak of the correlation between the two input images.

    Parameters
    ----------    
    im1 : array_like
		Image data as numpy array.

	im2 : array_like
		Image data as numpy array.
			
	Return value
	----------
	An integer value of the location of the maximum peak correlation.
	
    """
	# Fourier transform both images:
	f_im1 = fft2( im1.astype(float32), threads=2 );
	f_im2 = fft2( im2.astype(float32), threads=2 );

	# Perform phase correlation (amplitude is normalized):
	fc    = f_im1 * ( f_im2.conjugate() );
	fcn   = fc / abs(fc);

	# Inverse fourier of peak correlation matrix and max location:
	peak_correlation_matrix = real( ifft2( fcn, threads=2 ));

	# Calculate actual translation:
	max_ix = argmax(peak_correlation_matrix.flatten())
	(row, col) = unravel_index(max_ix, peak_correlation_matrix.shape)
	
	if ( col < (peak_correlation_matrix.shape[1]/2) ):
		col = - (col - 1);
	else:
		col = peak_correlation_matrix.shape[1] - (col - 1);	

	return col / 2;
示例#28
0
        def worker():
            # generate Gaussian white noise field, multiply it with the standard
            # deviation of the observed field and apply the precipitation mask
            N = randstates[k].randn(R.shape[0], R.shape[1])
            N = np.real(fft.ifft2(fft.fft2(N) * R_fft))
            N = N / np.std(N) * sigma + mu
            N[~MASK] = R_thr_2

            # subtract the mean and decompose the masked noise field into a
            # cascade
            N -= mu
            decomp_N = decomp_method(N, F, MASK=MASK_)

            return decomp_N["stds"]
示例#29
0
def _phase_correlation(im0, im1, callback=None, *args):
    """
    Computes phase correlation between im0 and im1

    Args:
        im0
        im1
        callback (function): Process the cross-power spectrum (i.e. choose
            coordinates of the best element, usually of the highest one).
            Defaults to :func:`imreg_dft.utils.argmax2D`

    Returns:
        tuple: The translation vector (Y, X). Translation vector of (0, 0)
            means that the two images match.
    """
    if callback is None:
        callback = utils._argmax2D

    # TODO: Implement some form of high-pass filtering of PHASE correlation
    f0, f1 = [
        fft.fft2(arr,
                 threads=4,
                 overwrite_input=True,
                 auto_align_input=True,
                 auto_contiguous=True,
                 planner_effort='FFTW_ESTIMATE') for arr in (im0, im1)
    ]
    # spectrum can be filtered (already),
    # so we have to take precaution against dividing by 0
    eps = abs(f1).max() * 1e-15
    # cps == cross-power spectrum of im0 and im1
    cps = abs(
        fft.ifft2((f0 * f1.conjugate()) / (abs(f0) * abs(f1) + eps),
                  threads=4,
                  overwrite_input=True,
                  auto_align_input=True,
                  auto_contiguous=True,
                  planner_effort='FFTW_ESTIMATE'))
    # scps = shifted cps
    scps = fft.fftshift(cps)

    (t0, t1), success = callback(scps, *args)
    ret = np.array((t0, t1))

    # _compensate_fftshift is not appropriate here, this is OK.
    t0 -= f0.shape[0] // 2
    t1 -= f0.shape[1] // 2

    ret -= np.array(f0.shape, int) // 2
    return ret, success
示例#30
0
def exp_harm_period(img,
                    harmonicPeriod,
                    harmonic_ij='00',
                    searchRegion=10,
                    isFFT=False,
                    verbose=True):
    """
    Function to obtain the position (in pixels) in the reciprocal space
    of the first harmonic ().
    """

    (nRows, nColumns) = img.shape

    harV = int(harmonic_ij[0])
    harH = int(harmonic_ij[1])

    periodVert = harmonicPeriod[0]
    periodHor = harmonicPeriod[1]

    # adjusts for 1D grating
    if periodVert <= 0 or periodVert is None:
        periodVert = nRows
        if verbose:
            wpu.print_blue("MESSAGE: Assuming Horizontal 1D Grating")

    if periodHor <= 0 or periodHor is None:
        periodHor = nColumns
        if verbose:
            wpu.print_blue("MESSAGE: Assuming Vertical 1D Grating")

    #    _check_harmonic_inside_image(harV, harH, nRows, nColumns,
    #                                 periodVert, periodHor)

    if isFFT:
        imgFFT = img
    else:
        imgFFT = np.fft.fftshift(fft2(img, norm='ortho'))

    del_i, del_j = _error_harmonic_peak(imgFFT, harV, harH, periodVert,
                                        periodHor, searchRegion)

    if verbose:
        wpu.print_blue("MESSAGE: error experimental harmonics " +
                       "vertical: {:d}".format(del_i))
        wpu.print_blue("MESSAGE: error experimental harmonics " +
                       "horizontal: {:d}".format(del_j))

    return periodVert + del_i, periodHor + del_j
示例#31
0
def initialize_nonparam_2d_fft_filter(X, **kwargs):
    """Takes a 2d input field and produces a fourier filter by using the Fast
    Fourier Transform (FFT).

    Parameters
    ----------
    X : array-like
      Two-dimensional array containing the input field. All values are required
      to be finite.

    Other Parameters
    ----------------
    win_type : string
       Optional tapering function to be applied to X.
       Default : flat-hanning
    donorm : bool
       Option to normalize the real and imaginary parts.
       Default : False

    Returns
    -------
    F : array-like
      A two-dimensional array containing the non-parametric filter.
      It can be passed to generate_noise_2d_fft_filter().
    """
    if len(X.shape) != 2:
        raise ValueError("the input is not two-dimensional array")
    if np.any(~np.isfinite(X)):
        raise ValueError("X contains non-finite values")

    # defaults
    win_type = kwargs.get('win_type', 'flat-hanning')
    donorm = kwargs.get('donorm', False)

    X = X.copy()
    if win_type is not None:
        X -= X.min()
        tapering = build_2D_tapering_function(X.shape, win_type)
    else:
        tapering = np.ones_like(X)
    F = fft.fft2(X * tapering, **fft_kwargs)

    # normalize the real and imaginary parts
    if donorm:
        F.imag = (F.imag - np.mean(F.imag)) / np.std(F.imag)
        F.real = (F.real - np.mean(F.real)) / np.std(F.real)

    return np.abs(F)
示例#32
0
文件: improc.py 项目: xwcl/xpipeline
def ft_shift2(image: np.ndarray,
              dy: float,
              dx: float,
              flux_tol: Union[None, float] = 1e-15,
              output_shape=None):
    """
    Fast Fourier subpixel shifting

    Parameters
    ----------
    dy : float
        Translation in +Y direction (i.e. a feature at (x, y) moves to (x, y + dy))
    dx : float
        Translation in +X direction (i.e. a feature at (x, y) moves to (x + dx, y))
    flux_tol : float
        Fractional flux change permissible
        ``(sum(output) - sum(image)) / sum(image) < flux_tol``
        (default: 1e-15)
    output_shape : tuple
        shape of output array (default: same as input)
    """
    if output_shape is None:
        output_shape = image.shape
    xfreqs = fft.fftfreq(output_shape[1])
    yfreqs = fft.fftfreq(output_shape[0])
    xform = fft.fft2(image, s=output_shape)
    if output_shape is not None:
        # compute center-to-center displacement such that
        # supplying dx == dy == 0.0 will be a no-op (aside
        # from changing shape)
        orig_ctr_x, orig_ctr_y = (image.shape[1] - 1) / 2, (image.shape[0] -
                                                            1) / 2
        new_ctr_x, new_ctr_y = (output_shape[1] - 1) / 2, (output_shape[0] -
                                                           1) / 2
        base_dx, base_dy = new_ctr_x - orig_ctr_x, new_ctr_y - orig_ctr_y
    else:
        base_dx = base_dy = 0
    modified_xform = xform * np.exp(2j * np.pi * (
        (-(dx + base_dx) * xfreqs)[np.newaxis, :] +
        (-(dy + base_dy) * yfreqs)[:, np.newaxis]))
    new_image = fft.ifft2(modified_xform).real
    frac_diff_flux = (np.sum(image) - np.sum(new_image)) / np.sum(image)
    if flux_tol is not None and frac_diff_flux > flux_tol:
        raise RuntimeError(
            f"Flux conservation violated by {frac_diff_flux} fractional difference (more than {flux_tol})"
        )
    return new_image
示例#33
0
def exp_harm_period(img, harmonicPeriod,
                    harmonic_ij='00', searchRegion=10,
                    isFFT=False, verbose=True):
    """
    Function to obtain the position (in pixels) in the reciprocal space
    of the first harmonic ().
    """

    (nRows, nColumns) = img.shape

    harV = int(harmonic_ij[0])
    harH = int(harmonic_ij[1])

    periodVert = harmonicPeriod[0]
    periodHor = harmonicPeriod[1]

    # adjusts for 1D grating
    if periodVert <= 0 or periodVert is None:
        periodVert = nRows
        if verbose:
            wpu.print_blue("MESSAGE: Assuming Horizontal 1D Grating")

    if periodHor <= 0 or periodHor is None:
        periodHor = nColumns
        if verbose:
            wpu.print_blue("MESSAGE: Assuming Vertical 1D Grating")

    #    _check_harmonic_inside_image(harV, harH, nRows, nColumns,
    #                                 periodVert, periodHor)

    if isFFT:
        imgFFT = img
    else:
        imgFFT = np.fft.fftshift(fft2(img, norm='ortho'))

    del_i, del_j = _error_harmonic_peak(imgFFT, harV, harH,
                                        periodVert, periodHor,
                                        searchRegion)

    if verbose:
        wpu.print_blue("MESSAGE: error experimental harmonics " +
                       "vertical: {:d}".format(del_i))
        wpu.print_blue("MESSAGE: error experimental harmonics " +
                       "horizontal: {:d}".format(del_j))

    return periodVert + del_i, periodHor + del_j
示例#34
0
文件: pstd.py 项目: FRidh/pstd
def velocity_abs_exp(alpha, timestep, spacing, wavenumber):
    """
    Absorption coefficient exponent.
    
    :param alpha: :math:`\\alpha_{\\xi}`
    :param timestep: Timestep :math:`\\Delta t`
    
    This value is calculated according to
    
    .. math:: e^{-\\alpha_{\\xi} \\Delta t / 2}
    
    However, since the velocity field is shifted by half a spacing, a correction needs to be applied.
    
    .. math:: \\mathcal{F}^{-1} \\left[ e^{+j k_{\\xi} \\Delta \\xi / 2} \\mathcal{F} \\left( e^{-\\alpha_{\\xi} \Delta t / 2} \\right) \\right]
        
    """
    j = 1j
    return ifft2(ne.evaluate("exp(+j * wavenumber*spacing/2.0)") * fft2(ne.evaluate("exp(-alpha * timestep / 2.0)"))) 
示例#35
0
文件: pstd.py 项目: FRidh/pstd
def update(d):
    """
    Calculation steps to be taken every step. 
    
    :param d: Dictionary containing simulation data.
    
    .. note:: This method should only contain calculation steps.
    
    """
    step = d['step']
    
    
    # Calculate FFT of pressure
    pressure_fft = fft2(d['field'][('pressure', None)])    # Apply atmospheric absorption here?

    #out_x = d['executor'].submit(sync_steps, d['temp']['p_x'], d['field'][('velocity', 'x')], pressure_fft, d['k_x'], 
                            #d['kappa'], d['spacing'], d['timestep'], d['density'], d['soundspeed'], 
                            #d['abs_exp']['p']['x'], d['abs_exp']['v']['x'], d['source'][('pressure', None)], d['source'][('velocity', 'x')])

    #out_y = d['executor'].submit(sync_steps, d['temp']['p_y'], d['field'][('velocity', 'y')], pressure_fft, d['k_y'], 
                            #d['kappa'], d['spacing'], d['timestep'], d['density'], d['soundspeed'], 
                            #d['abs_exp']['p']['y'], d['abs_exp']['v']['y'], d['source'][('pressure', None)], d['source'][('velocity', 'y')])

    #out_x = out_x.result()
    #out_y = out_y.result()
        
    out_x = sync_steps(d['temp']['p_x'], d['field'][('velocity', 'x')], pressure_fft, d['k_x'], 
                                d['kappa'], d['spacing'], d['timestep'], d['density'], d['soundspeed'], 
                                d['abs_exp']['p']['x'], d['abs_exp']['v']['x'], d['source'][('pressure', None)], d['source'][('velocity', 'x')])

    out_y = sync_steps(d['temp']['p_y'], d['field'][('velocity', 'y')], pressure_fft, d['k_y'], 
                                d['kappa'], d['spacing'], d['timestep'], d['density'], d['soundspeed'], 
                                d['abs_exp']['p']['y'], d['abs_exp']['v']['y'], d['source'][('pressure', None)], d['source'][('velocity', 'y')])

    d['temp']['p_x'], d['field'][('velocity', 'x')] = out_x
    d['temp']['p_y'], d['field'][('velocity', 'y')] = out_y

    d['field'][('pressure', None)] = d['temp']['p_x'] + d['temp']['p_y']
    
    return d
示例#36
0
def _phase_correlation(im0, im1, callback=None, *args):
    """
    Computes phase correlation between im0 and im1

    Args:
        im0
        im1
        callback (function): Process the cross-power spectrum (i.e. choose
            coordinates of the best element, usually of the highest one).
            Defaults to :func:`imreg_dft.utils.argmax2D`

    Returns:
        tuple: The translation vector (Y, X). Translation vector of (0, 0)
            means that the two images match.
    """
    if callback is None:
        callback = utils._argmax2D

    # TODO: Implement some form of high-pass filtering of PHASE correlation
    f0, f1 = [fft.fft2(arr) for arr in (im0, im1)]
    # spectrum can be filtered (already),
    # so we have to take precaution against dividing by 0
    eps = abs(f1).max() * 1e-15
    # cps == cross-power spectrum of im0 and im1
    cps = abs(fft.ifft2((f0 * f1.conjugate()) / (abs(f0) * abs(f1) + eps)))
    # scps = shifted cps
    scps = fft.fftshift(cps)

    (t0, t1), success = callback(scps, *args)
    ret = np.array((t0, t1))

    # _compensate_fftshift is not appropriate here, this is OK.
    t0 -= f0.shape[0] // 2
    t1 -= f0.shape[1] // 2

    ret -= np.array(f0.shape, int) // 2
    return ret, success
示例#37
0
def plot_harmonic_grid(img, harmonicPeriod=None, isFFT=False):
    """
    Takes the FFT of single 2D grating Talbot imaging and plot the grid from
    where we extract the harmonic in a image of the



    Parameters
    ----------
    img : 	ndarray – Data (data_exchange format)
        Experimental image, whith proper blank image, crop and rotation already
        applied.

    harmonicPeriod : integer or list of integers
        If list, it must be in the format ``[periodVert, periodHor]``. If
        integer, then [periodVert = periodHor``.
        ``periodVert`` and ``periodVert`` are the period of the harmonics in
        the reciprocal space in pixels. For the checked board grating,
        ``periodVert = sqrt(2) * pixel Size / grating Period * number of
        rows in the image``

    isFFT : Boolean
        Flag that tells if the input image ``img`` is in the reciprocal
        (``isFFT=True``) or in the real space (``isFFT=False``)

    """

    if not isFFT:
        imgFFT = np.fft.fftshift(fft2(np.fft.fftshift(img),
                                             norm='ortho'))
    else:
        imgFFT = img

    (nRows, nColumns) = imgFFT.shape

    periodVert = harmonicPeriod[0]
    periodHor = harmonicPeriod[1]

    # adjusts for 1D grating
    if periodVert <= 0 or periodVert is None:
        periodVert = nRows

    if periodHor <= 0 or periodHor is None:
        periodHor = nColumns

    plt.figure(figsize=(8, 7))
    plt.imshow(np.log10(np.abs(imgFFT)), cmap='inferno',
               extent=wpu.extent_func(imgFFT))

    plt.xlabel('Pixels')
    plt.ylabel('Pixels')

    harV_min = -(nRows + 1) // 2 // periodVert
    harV_max = (nRows + 1) // 2 // periodVert

    harH_min = -(nColumns + 1) // 2 // periodHor
    harH_max = (nColumns + 1) // 2 // periodHor

    for harV in range(harV_min + 1, harV_max + 2):

        idxPeak_ij = _idxPeak_ij(harV, 0, nRows, nColumns,
                                 periodVert, periodHor)

        plt.axhline(idxPeak_ij[0] - periodVert//2 - nRows//2,
                    lw=2, color='r')

    for harH in range(harH_min + 1, harH_max + 2):

        idxPeak_ij = _idxPeak_ij(0, harH, nRows, nColumns,
                                 periodVert, periodHor)
        plt.axvline(idxPeak_ij[1] - periodHor // 2 - nColumns//2,
                    lw=2, color='r')

    for harV in range(harV_min, harV_max + 1):
        for harH in range(harH_min, harH_max + 1):

            idxPeak_ij = _idxPeak_ij(harV, harH,
                                     nRows, nColumns,
                                     periodVert, periodHor)

            plt.plot(idxPeak_ij[1] - nColumns//2,
                     idxPeak_ij[0] - nRows//2,
                    'ko', mew=2, mfc="None", ms=15)

            plt.annotate('{:d}{:d}'.format(-harV, harH),
                         (idxPeak_ij[1] - nColumns//2,
                          idxPeak_ij[0] - nRows//2,),
                         color='red', fontsize=20)

    plt.xlim(-nColumns//2, nColumns - nColumns//2)
    plt.ylim(-nRows//2, nRows - nRows//2)
    plt.title('log scale FFT magnitude, Hamonics Subsets and Indexes',
              fontsize=16, weight='bold')
示例#38
0
def plot_harmonic_peak(img, harmonicPeriod=None, isFFT=False, fname=None):
    """
    Funtion to plot the profile of the harmonic peaks ``10`` and ``01``.
    It is ploted 11 profiles of the 11 nearest vertical (horizontal)
    lines to the peak ``01`` (``10``)

    img : 	ndarray – Data (data_exchange format)
        Experimental image, whith proper blank image, crop and rotation already
        applied.

    harmonicPeriod : integer or list of integers
        If list, it must be in the format ``[periodVert, periodHor]``. If
        integer, then [periodVert = periodHor``.
        ``periodVert`` and ``periodVert`` are the period of the harmonics in
        the reciprocal space in pixels. For the checked board grating,
        ``periodVert = sqrt(2) * pixel Size / grating Period * number of
        rows in the image``

    isFFT : Boolean
        Flag that tells if the input image ``img`` is in the reciprocal
        (``isFFT=True``) or in the real space (``isFFT=False``)
    """

    if not isFFT:
        imgFFT = np.fft.fftshift(fft2(np.fft.fftshift(img),
                                             norm='ortho'))
    else:
        imgFFT = img

    (nRows, nColumns) = img.shape

    periodVert = harmonicPeriod[0]
    periodHor = harmonicPeriod[1]

    # adjusts for 1D grating
    if periodVert <= 0 or periodVert is None:
        periodVert = nRows

    if periodHor <= 0 or periodHor is None:
        periodHor = nColumns

    fig = plt.figure(figsize=(8, 7))

    ax1 = fig.add_subplot(121)

    ax2 = fig.add_subplot(122)

    idxPeak_ij = _idxPeak_ij(0, 1,
                             nRows, nColumns,
                             periodVert, periodHor)

    for i in range(-5, 5):

        ax1.plot(np.abs(imgFFT[idxPeak_ij[0] - 100:idxPeak_ij[0] + 100,
                               idxPeak_ij[1]-i]),
                 lw=2, label='01 Vert ' + str(i))

    ax1.grid()

    idxPeak_ij = _idxPeak_ij(1, 0,
                             nRows, nColumns,
                             periodVert, periodHor)

    for i in range(-5, 5):

        ax2.plot(np.abs(imgFFT[idxPeak_ij[0]-i,
                               idxPeak_ij[1] - 100:idxPeak_ij[1] + 100]),
                 lw=2, label='10 Horz ' + str(i))

    ax2.grid()

    ax1.set_xlabel('Pixels')
    ax1.set_ylabel(r'$| FFT |$ ')
    ax1.legend(loc=1, fontsize='xx-small')
    ax1.title.set_text('Horz')


    ax2.set_xlabel('Pixels')
    ax2.set_ylabel(r'$| FFT |$ ')
    ax2.legend(loc=1, fontsize='xx-small')
    ax2.title.set_text('Vert')
    plt.show(block=False)

    if fname is not None:
        plt.savefig(fname, transparent=True)
示例#39
0
def single_grating_harmonic_images(img, harmonicPeriod,
                                   searchRegion=10,
                                   plotFlag=False, verbose=False):
    """
    Auxiliary function to process the data of single 2D grating Talbot imaging.
    It obtain the (real space) harmonic images  00, 01 and 10.

    Parameters
    ----------
    img : 	ndarray – Data (data_exchange format)
        Experimental image, whith proper blank image, crop and rotation already
        applied.

    harmonicPeriod : list of integers in the format [periodVert, periodHor]
        ``periodVert`` and ``periodVert`` are the period of the harmonics in
        the reciprocal space in pixels. For the checked board grating,
        periodVert = sqrt(2) * pixel Size / grating Period * number of
        rows in the image. For 1D grating, set one of the values to negative or
        zero (it will set the period to number of rows or colunms).

    searchRegion: int
        search for the peak will be in a region of harmonicPeriod/searchRegion
        around the theoretical peak position. See also
        `:py:func:`wavepy.grating_interferometry.plot_harmonic_grid`

    plotFlag: boolean
        Flag to plot the image in the reciprocal space and to show the position
        of the found peaked and the limits of the harmonic image

    verbose: Boolean
        verbose flag.

    Returns
    -------
    three 2D ndarray data
        Images obtained from the harmonics 00, 01 and 10.

    """

    imgFFT = np.fft.fftshift(fft2(img, norm='ortho'))

    if plotFlag:
        plot_harmonic_grid(imgFFT, harmonicPeriod=harmonicPeriod, isFFT=True)
        plt.show(block=False)

    imgFFT00 = extract_harmonic(imgFFT,
                                harmonicPeriod=harmonicPeriod,
                                harmonic_ij='00',
                                searchRegion=searchRegion,
                                isFFT=True,
                                plotFlag=plotFlag,
                                verbose=verbose)

    imgFFT01 = extract_harmonic(imgFFT,
                                harmonicPeriod=harmonicPeriod,
                                harmonic_ij=['0', '1'],
                                searchRegion=searchRegion,
                                isFFT=True,
                                plotFlag=plotFlag,
                                verbose=verbose)

    imgFFT10 = extract_harmonic(imgFFT,
                                harmonicPeriod=harmonicPeriod,
                                harmonic_ij=['1', '0'],
                                searchRegion=searchRegion,
                                isFFT=True,
                                plotFlag=plotFlag,
                                verbose=verbose)

    #  Plot Fourier image (intensity)
    if plotFlag:

        # Intensity is Fourier Space
        intFFT00 = np.log10(np.abs(imgFFT00))
        intFFT01 = np.log10(np.abs(imgFFT01))
        intFFT10 = np.log10(np.abs(imgFFT10))

        fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(14, 5))

        for dat, ax, textTitle in zip([intFFT00, intFFT01, intFFT10],
                                      axes.flat,
                                      ['FFT 00', 'FFT 01', 'FFT 10']):

            # The vmin and vmax arguments specify the color limits
            im = ax.imshow(dat, cmap='inferno', vmin=np.min(intFFT00),
                           vmax=np.max(intFFT00),
                           extent=wpu.extent_func(dat))

            ax.set_title(textTitle)
            if textTitle == 'FFT 00':
                ax.set_ylabel('Pixels')

            ax.set_xlabel('Pixels')

        # Make an axis for the colorbar on the right side
        cax = fig.add_axes([0.92, 0.1, 0.03, 0.8])
        fig.colorbar(im, cax=cax)
        plt.suptitle('FFT subsets - Intensity', fontsize=18, weight='bold')
        plt.show(block=False)

    img00 = ifft2(np.fft.ifftshift(imgFFT00), norm='ortho')

    # non existing harmonics will return NAN, so here we check NAN
    if np.all(np.isfinite(imgFFT01)):
        img01 = ifft2(np.fft.ifftshift(imgFFT01), norm='ortho')
    else:
        img01 = imgFFT01

    if np.all(np.isfinite(imgFFT10)):
        img10 = ifft2(np.fft.ifftshift(imgFFT10), norm='ortho')
    else:
        img10 = imgFFT10

    return (img00, img01, img10)
示例#40
0
def visib_1st_harmonics(img, harmonicPeriod, searchRegion=20,
                        unFilterSize=1, verbose=False):
    """
    This function obtain the visibility in a grating imaging experiment by the
    ratio of the amplitudes of the first and zero harmonics. See
    https://doi.org/10.1364/OE.22.014041 .

    Note
    ----
    Note that the absolute visibility also depends on the higher harmonics, and
    for a absolute value of visibility all of them must be considered.


    Parameters
    ----------
    img : 	ndarray – Data (data_exchange format)
        Experimental image, whith proper blank image, crop and rotation already
        applied.

    harmonicPeriod : list of integers in the format [periodVert, periodHor]
        ``periodVert`` and ``periodVert`` are the period of the harmonics in
        the reciprocal space in pixels. For the checked board grating,
        periodVert = sqrt(2) * pixel Size / grating Period * number of
        rows in the image. For 1D grating, set one of the values to negative or
        zero (it will set the period to number of rows or colunms).

    searchRegion: int
        search for the peak will be in a region of harmonicPeriod/searchRegion
        around the theoretical peak position. See also
        `:py:func:`wavepy.grating_interferometry.plot_harmonic_grid`

    verbose: Boolean
        verbose flag.


    Returns
    -------
    (float, float)
        horizontal and vertical visibilities respectivelly from
        harmonics 01 and 10


    """

    imgFFT = np.fft.fftshift(fft2(img, norm='ortho'))

    _idxPeak_ij_exp00 = _idxPeak_ij_exp(imgFFT, 0, 0,
                                        harmonicPeriod[0], harmonicPeriod[1],
                                        searchRegion)

    _idxPeak_ij_exp10 = _idxPeak_ij_exp(imgFFT, 1, 0,
                                        harmonicPeriod[0], harmonicPeriod[1],
                                        searchRegion)

    _idxPeak_ij_exp01 = _idxPeak_ij_exp(imgFFT, 0, 1,
                                        harmonicPeriod[0], harmonicPeriod[1],
                                        searchRegion)


    from scipy.ndimage.filters import uniform_filter

    arg_imgFFT = np.abs(imgFFT)

    if unFilterSize > 1:
        arg_imgFFT = uniform_filter(arg_imgFFT, unFilterSize)

    peak00 = arg_imgFFT[_idxPeak_ij_exp00[0], _idxPeak_ij_exp00[1]]
    peak10 = arg_imgFFT[_idxPeak_ij_exp10[0], _idxPeak_ij_exp10[1]]
    peak01 = arg_imgFFT[_idxPeak_ij_exp01[0], _idxPeak_ij_exp01[1]]

    return (2*peak10/peak00, 2*peak01/peak00, _idxPeak_ij_exp00, _idxPeak_ij_exp10, _idxPeak_ij_exp01)
示例#41
0
    def compute_bispectrum(self, show_progress=True, use_pyfftw=False,
                           threads=1, nsamples=100, seed=1000,
                           mean_subtract=False, **pyfftw_kwargs):
        '''
        Do the computation.

        Parameters
        ----------
        show_progress : optional, bool
            Show progress bar while sampling the bispectrum.
        use_pyfftw : bool, optional
            Enable to use pyfftw, if it is installed.
        threads : int, optional
            Number of threads to use in FFT when using pyfftw.
        nsamples : int, optional
            Sets the number of samples to take at each vector
            magnitude.
        seed : int, optional
            Sets the seed for the distribution draws.
        mean_subtract : bool, optional
            Subtract the mean from the data before computing. This removes the
            "zero frequency" (i.e., constant) portion of the power, resulting
            in a loss of phase coherence along the k_1=k_2 line.
        pyfft_kwargs : Passed to
            `~turbustat.statistics.rfft_to_fft.rfft_to_fft`. See
            `here <https://hgomersall.github.io/pyFFTW/pyfftw/interfaces/interfaces.html#interfaces-additional-args>`_
            for a list of accepted kwargs.
        '''

        if mean_subtract:
            norm_data = self.data - self.data.mean()
        else:
            norm_data = self.data

        if use_pyfftw:
            if PYFFTW_FLAG:
                if pyfftw_kwargs.get('threads') is not None:
                    pyfftw_kwargs.pop('threads')

                fftarr = fft2(norm_data,
                              threads=threads,
                              **pyfftw_kwargs)
            else:
                warn("pyfftw not installed. Reverting to using numpy.")
                use_pyfftw = False

        if not use_pyfftw:
            fftarr = np.fft.fft2(norm_data)

        conjfft = np.conj(fftarr)

        bispec_shape = (int(self.shape[0] / 2.), int(self.shape[1] / 2.))

        self._bispectrum = np.zeros(bispec_shape, dtype=np.complex)
        self._bicoherence = np.zeros(bispec_shape, dtype=np.float)
        self._tracker = np.zeros(self.shape, dtype=np.int16)

        biconorm = np.ones_like(self.bispectrum, dtype=float)

        if show_progress:
            bar = ProgressBar(np.prod(fftarr.shape) / 4.)

        prod = product(range(int(fftarr.shape[0] / 2.)),
                       range(int(fftarr.shape[1] / 2.)))

        with NumpyRNGContext(seed):
            for n, (k1mag, k2mag) in enumerate(prod):
                phi1 = ra.uniform(0, 2 * np.pi, nsamples)
                phi2 = ra.uniform(0, 2 * np.pi, nsamples)

                k1x = np.asarray([int(k1mag * np.cos(angle))
                                  for angle in phi1])
                k2x = np.asarray([int(k2mag * np.cos(angle))
                                  for angle in phi2])
                k1y = np.asarray([int(k1mag * np.sin(angle))
                                  for angle in phi1])
                k2y = np.asarray([int(k2mag * np.sin(angle))
                                  for angle in phi2])

                k3x = np.asarray([int(k1mag * np.cos(ang1) +
                                      k2mag * np.cos(ang2))
                                  for ang1, ang2 in zip(phi1, phi2)])
                k3y = np.asarray([int(k1mag * np.sin(ang1) +
                                      k2mag * np.sin(ang2))
                                  for ang1, ang2 in zip(phi1, phi2)])

                samps = fftarr[k1x, k1y] * fftarr[k2x, k2y] * conjfft[k3x, k3y]

                self._bispectrum[k1mag, k2mag] = np.sum(samps)

                biconorm[k1mag, k2mag] = np.sum(np.abs(samps))

                # Track where we're sampling from in fourier space
                self._tracker[k1x, k1y] += 1
                self._tracker[k2x, k2y] += 1
                self._tracker[k3x, k3y] += 1

                if show_progress:
                    bar.update(n + 1)

        self._bicoherence = (np.abs(self.bispectrum) / biconorm)
        self._bispectrum_amp = np.log10(np.abs(self.bispectrum))
示例#42
0
def phase_retrieval(im, plan, method=1, nr_threads=2):
	"""Process a tomographic projection image with the selected phase retrieval algorithm.

	Parameters
	----------
	im : array_like
		Flat corrected image data as numpy array.
	plan : structure
		Structure with pre-computed data (see prepare_plan function)
	method : int 
		Phase retrieval algorithm {1 = TIE (default), 2 = Born, 3 = Rytov, 4 = Wu}
	nr_threads : int 
		Number of threads to be used in the computation of FFT by PyFFTW
		
	"""
	# Extract plan values:
	dim0_o = plan['dim0']
	dim1_o = plan['dim1']
	n_pad0 = plan['npad0']
	n_pad1 = plan['npad1']
	marg0 = (n_pad0 - dim0_o) / 2
	marg1 = (n_pad1 - dim1_o) / 2
	den = plan['den']
	mu = plan['mu']
	
	# Pad image (if required):	
	im  = padImage(im, n_pad0, n_pad1) 

	# (Un)comment the following two lines to use PyFFTW:
	n_byte_align(im, simd_alignment) 
	im = fft2(im, threads=nr_threads)			

	# (Un)comment the following line to use NumPy:	
	#im = fft2(im)			

	# Apply formula:
	if method == 1:		
		im = im / den
		
		# (Un)comment the following two lines to use PyFFTW:
		n_byte_align(im, simd_alignment)
		im = ifft2(im, threads=nr_threads)
		
		# (Un)comment the following line to use NumPy:
		#im = ifft2(im)
		im = im.astype(complex64)
		 		
		im = real(im)
		im = im.astype(float32)		
		im = -1 / mu * nplog(im)    		

	#
	# WARNING: The following methods are not tested
	#
	elif method == 2:
		im = real(ifft2((im - 1.0) / 2.0) / den)
	elif method == 3:
		im = real(ifft2(nplog(im) / 2.0) / den)
	elif method == 4:       
		im = real(ifft2(im / den))
		im = -1 / 2 * (delta / beta) * nplog(im)    

	# Return cropped output:
	return im[marg0:dim0_o + marg0, marg1:dim1_o + marg1]   
示例#43
0
def similarity(im0, im1):
    """Return similarity transformed image im1 and transformation parameters.

    Transformation parameters are: isotropic scale factor, rotation angle (in
    degrees), and translation vector.

    A similarity transformation is an affine transformation with isotropic
    scale and without shear.

    Limitations:
    Image shapes must be equal and square.
    All image areas must have same scale, rotation, and shift.
    Scale change must be less than 1.8.
    No subpixel precision.

    """
    if im0.shape != im1.shape:
        raise ValueError("Images must have same shapes.")
    elif len(im0.shape) != 2:
        raise ValueError("Images must be 2 dimensional.")

    f0 = fftshift(abs(fft2(im0)))
    f1 = fftshift(abs(fft2(im1)))

    h = highpass(f0.shape)
    f0 *= h
    f1 *= h
    del h

    f0, log_base = logpolar(f0)
    f1, log_base = logpolar(f1)

    f0 = fft2(f0)
    f1 = fft2(f1)
    r0 = abs(f0) * abs(f1)
    ir = abs(ifft2((f0 * f1.conjugate()) / r0))

    i0, i1 = np.unravel_index(np.argmax(ir), ir.shape)
    angle = 180.0 * i0 / ir.shape[0]
    scale = log_base ** i1

    if scale > 1.8:
        ir = abs(ifft2((f1 * f0.conjugate()) / r0))
        i0, i1 = np.unravel_index(np.argmax(ir), ir.shape)
        angle = -180.0 * i0 / ir.shape[0]
        scale = 1.0 / (log_base ** i1)
        if scale > 1.8:
            raise ValueError("Images are not compatible. Scale change > 1.8")

    if angle < -90.0:
        angle += 180.0
    elif angle > 90.0:
        angle -= 180.0

    im2 = ndii.zoom(im1, 1.0 / scale)
    im2 = ndii.rotate(im2, angle)

    if im2.shape < im0.shape:
        t = np.zeros_like(im0)
        t[:im2.shape[0], :im2.shape[1]] = im2
        im2 = t
    elif im2.shape > im0.shape:
        im2 = im2[:im0.shape[0], :im0.shape[1]]

    f0 = fft2(im0)
    f1 = fft2(im2)
    ir = abs(ifft2((f0 * f1.conjugate()) / (abs(f0) * abs(f1))))
    t0, t1 = np.unravel_index(np.argmax(ir), ir.shape)

    if t0 > f0.shape[0] // 2:
        t0 -= f0.shape[0]
    if t1 > f0.shape[1] // 2:
        t1 -= f0.shape[1]

    im2 = ndii.shift(im2, [t0, t1])

    # correct parameters for ndimage's internal processing
    if angle > 0.0:
        d = int((int(im1.shape[1] / scale) * math.sin(math.radians(angle))))
        t0, t1 = t1, d + t0
    elif angle < 0.0:
        d = int((int(im1.shape[0] / scale) * math.sin(math.radians(angle))))
        t0, t1 = d + t1, d + t0
    scale = (im1.shape[1] - 1) / (int(im1.shape[1] / scale) - 1)

    return im2, scale, angle, [-t0, -t1]
示例#44
0
from __future__ import division
import warnings
import numpy as np
from functools import wraps

from menpo.feature.base import rebuild_feature_image

try:
    # try importing pyfftw
    from pyfftw.interfaces.numpy_fft import fft2, ifft2, fftshift, ifftshift

    try:
        # try calling fft2 on a 4-dimensional array (this is known to have
        # problem in some linux distributions)
        fft2(np.zeros((1, 1, 1, 1)))
    except RuntimeError:
        warnings.warn("pyfftw is known to be buggy on your system, numpy.fft "
                      "will be used instead. Consequently, all algorithms "
                      "using ffts will be running at a slower speed.",
                      RuntimeWarning)
        from numpy.fft import fft2, ifft2, fftshift, ifftshift
except ImportError:
    warnings.warn("pyfftw is not installed on your system, numpy.fft will be "
                  "used instead. Consequently, all algorithms using ffts "
                  "will be running at a slower speed. Consider installing "
                  "pyfftw (pip install pyfftw) to speed up your ffts.",
                  ImportWarning)
    from numpy.fft import fft2, ifft2, fftshift, ifftshift


# TODO: Document me!
示例#45
0
def _get_ang_scale(ims, bgval, exponent='inf', constraints=None, reports=None):
    """
    Given two images, return their scale and angle difference.

    Args:
        ims (2-tuple-like of 2D ndarrays): The images
        bgval: We also pad here in the :func:`map_coordinates`
        exponent (float or 'inf'): The exponent stuff, see :func:`similarity`
        constraints (dict, optional)
        reports (optional)

    Returns:
        tuple: Scale, angle. Describes the relationship of
        the subject image to the first one.
    """
    assert len(ims) == 2, \
        "Only two images are supported as input"
    shape = ims[0].shape

    ims_apod = [utils._apodize(im) for im in ims]
    dfts = [fft.fftshift(fft.fft2(im)) for im in ims_apod]
    filt = _logpolar_filter(shape)
    dfts = [dft * filt for dft in dfts]

    # High-pass filtering used to be here, but we have moved it to a higher
    # level interface

    pcorr_shape = _get_pcorr_shape(shape)
    log_base = _get_log_base(shape, pcorr_shape[1])
    stuffs = [_logpolar(np.abs(dft), pcorr_shape, log_base)
              for dft in dfts]

    (arg_ang, arg_rad), success = _phase_correlation(
        stuffs[0], stuffs[1],
        utils.argmax_angscale, log_base, exponent, constraints, reports)

    angle = -np.pi * arg_ang / float(pcorr_shape[0])
    angle = np.rad2deg(angle)
    angle = utils.wrap_angle(angle, 360)
    scale = log_base ** arg_rad

    angle = - angle
    scale = 1.0 / scale

    if reports is not None:
        reports["shape"] = filt.shape
        reports["base"] = log_base

        if reports.show("spectra"):
            reports["dfts_filt"] = dfts
        if reports.show("inputs"):
            reports["ims_filt"] = [fft.ifft2(np.fft.ifftshift(dft))
                                   for dft in dfts]
        if reports.show("logpolar"):
            reports["logpolars"] = stuffs

        if reports.show("scale_angle"):
            reports["amas-result-raw"] = (arg_ang, arg_rad)
            reports["amas-result"] = (scale, angle)
            reports["amas-success"] = success
            extent_el = pcorr_shape[1] / 2.0
            reports["amas-extent"] = (
                log_base ** (-extent_el), log_base ** extent_el,
                -90, 90
            )

    if not 0.5 < scale < 2:
        raise ValueError(
            "Images are not compatible. Scale change %g too big to be true."
            % scale)

    return scale, angle
示例#46
0
def fft_convolve2d(x, f, mode='same', boundary='constant', fft_filter=False):
    r"""
    Performs fast 2d convolution in the frequency domain convolving each image
    channel with its corresponding filter channel.

    Parameters
    ----------
    x : ``(channels, height, width)`` `ndarray`
        Image.
    f : ``(channels, height, width)`` `ndarray`
        Filter.
    mode : str {`full`, `same`, `valid`}, optional
        Determines the shape of the resulting convolution.
    boundary: str {`constant`, `symmetric`}, optional
        Determines how the image is padded.
    fft_filter: `bool`, optional
        If `True`, the filter is assumed to be defined on the frequency
        domain. If `False` the filter is assumed to be defined on the
        spatial domain.

    Returns
    -------
    c: ``(channels, height, width)`` `ndarray`
        Result of convolving each image channel with its corresponding
        filter channel.
    """
    if fft_filter:
        # extended shape is filter shape
        ext_shape = np.asarray(f.shape[-2:])

        # extend image and filter
        ext_x = pad(x, ext_shape, boundary=boundary)

        # compute ffts of extended image
        fft_ext_x = fft2(ext_x)
        fft_ext_f = f
    else:
        # extended shape
        x_shape = np.asarray(x.shape[-2:])
        f_shape = np.asarray(f.shape[-2:])
        f_half_shape = (f_shape / 2).astype(int)
        ext_shape = x_shape + f_half_shape - 1

        # extend image and filter
        ext_x = pad(x, ext_shape, boundary=boundary)
        ext_f = pad(f, ext_shape)

        # compute ffts of extended image and extended filter
        fft_ext_x = fft2(ext_x)
        fft_ext_f = fft2(ext_f)

    # compute extended convolution in Fourier domain
    fft_ext_c = fft_ext_f * fft_ext_x

    # compute ifft of extended convolution
    ext_c = np.real(ifftshift(ifft2(fft_ext_c), axes=(-2, -1)))

    if mode is 'full':
        return ext_c
    elif mode is 'same':
        return crop(ext_c, x_shape)
    elif mode is 'valid':
        return crop(ext_c, x_shape - f_half_shape + 1)
    else:
        raise ValueError(
            "mode={}, is not supported. The only supported "
            "modes are: 'full', 'same' and 'valid'.".format(mode))
示例#47
0
def extract_harmonic(img, harmonicPeriod,
                     harmonic_ij='00', searchRegion=10, isFFT=False,
                     plotFlag=False, verbose=True):

    """
    Function to extract one harmonic image of the FFT of single grating
    Talbot imaging.


    The function use the provided value of period to search for the harmonics
    peak. The search is done in a rectangle of size
    ``periodVert*periodHor/searchRegion**2``. The final result is a rectagle of
    size ``periodVert x periodHor`` centered at
    ``(harmonic_Vertical*periodVert x harmonic_Horizontal*periodHor)``


    Parameters
    ----------

    img : 	ndarray – Data (data_exchange format)
        Experimental image, whith proper blank image, crop and rotation already
        applied.

    harmonicPeriod : list of integers in the format [periodVert, periodHor]
        ``periodVert`` and ``periodVert`` are the period of the harmonics in
        the reciprocal space in pixels. For the checked board grating,
        periodVert = sqrt(2) * pixel Size / grating Period * number of
        rows in the image. For 1D grating, set one of the values to negative or
        zero (it will set the period to number of rows or colunms).

    harmonic_ij : string or list of string
        string with the harmonic to extract, for instance '00', '01', '10'
        or '11'. In this notation negative harmonics are not allowed.

        Alternativelly, it accepts a list of string
        ``harmonic_ij=[harmonic_Vertical, harmonic_Horizontal]``, for instance
        ``harmonic_ij=['0', '-1']``

        Note that since the original image contain only real numbers (not
        complex), then negative and positive harmonics are symetric
        related to zero.
    isFFT : Boolean
        Flag that tells if the input image ``img`` is in the reciprocal
        (``isFFT=True``) or in the real space (``isFFT=False``)

    searchRegion: int
        search for the peak will be in a region of harmonicPeriod/searchRegion
        around the theoretical peak position

    plotFlag: Boolean
        Flag to plot the image in the reciprocal space and to show the position
        of the found peaked and the limits of the harmonic image

    verbose: Boolean
        verbose flag.


    Returns
    -------
    2D ndarray
        Copped Images of the harmonics ij


    This functions crops a rectagle of size ``periodVert x periodHor`` centered
    at ``(harmonic_Vertical*periodVert x harmonic_Horizontal*periodHor)`` from
    the provided FFT image.


    Note
    ----
        * Note that it is the FFT of the image that is required.
        * The search for the peak is only used to print warning messages.

    **Q: Why not the real image??**

    **A:** Because FFT can be time consuming. If we use the real image, it will
    be necessary to run FFT for each harmonic. It is encourage to wrap this
    function within a function that do the FFT, extract the harmonics, and
    return the real space harmonic image.


    See Also
    --------
    :py:func:`wavepy.grating_interferometry.plot_harmonic_grid`

    """

    (nRows, nColumns) = img.shape

    harV = int(harmonic_ij[0])
    harH = int(harmonic_ij[1])

    periodVert = harmonicPeriod[0]
    periodHor = harmonicPeriod[1]

    if verbose:
            wpu.print_blue("MESSAGE: Extracting harmonic " +
                           harmonic_ij[0] + harmonic_ij[1])
            wpu.print_blue("MESSAGE: Harmonic period " +
                           "Horizontal: {:d} pixels".format(periodHor))
            wpu.print_blue("MESSAGE: Harmonic period " +
                           "Vertical: {:d} pixels".format(periodVert))

    # adjusts for 1D grating
    if periodVert <= 0 or periodVert is None:
        periodVert = nRows
        if verbose:
            wpu.print_blue("MESSAGE: Assuming Horizontal 1D Grating")

    if periodHor <= 0 or periodHor is None:
        periodHor = nColumns
        if verbose:
            wpu.print_blue("MESSAGE: Assuming Vertical 1D Grating")

    try:
        _check_harmonic_inside_image(harV, harH, nRows, nColumns,
                                     periodVert, periodHor)
    except ValueError:
        raise SystemExit

    if isFFT:
        imgFFT = img
    else:
        imgFFT = np.fft.fftshift(fft2(img, norm='ortho'))

    intensity = (np.abs(imgFFT))

    #  Estimate harmonic positions
    idxPeak_ij = _idxPeak_ij(harV, harH, nRows, nColumns,
                             periodVert, periodHor)

    del_i, del_j = _error_harmonic_peak(imgFFT, harV, harH,
                                        periodVert, periodHor,
                                        searchRegion)

    if verbose:
        print("MESSAGE: extract_harmonic:" +
              " harmonic peak " + harmonic_ij[0] + harmonic_ij[1] +
              " is misplaced by:")
        print("MESSAGE: {:d} pixels in vertical, {:d} pixels in hor".format(
               del_i, del_j))

        print("MESSAGE: Theoretical peak index: {:d},{:d} [VxH]".format(
              idxPeak_ij[0], idxPeak_ij[1]))

    if ((np.abs(del_i) > searchRegion // 2) or
       (np.abs(del_j) > searchRegion // 2)):

        wpu.print_red("ATTENTION: Harmonic Peak " + harmonic_ij[0] +
                      harmonic_ij[1] + " is too far from theoretical value.")
        wpu.print_red("ATTENTION: {:d} pixels in vertical,".format(del_i) +
                      "{:d} pixels in hor".format(del_j))

    if plotFlag:

        from matplotlib.patches import Rectangle
        plt.figure(figsize=(8, 7))
        plt.imshow(np.log10(intensity), cmap='inferno', extent=wpu.extent_func(intensity))

        plt.xlabel('Pixels')
        plt.ylabel('Pixels')

        xo = idxPeak_ij[1] - nColumns//2 - periodHor//2
        yo = nRows//2 - idxPeak_ij[0] - periodVert//2
        # xo yo are the lower left position of the reangle

        plt.gca().add_patch(Rectangle((xo, yo),
                                      periodHor, periodVert,
                                      lw=2, ls='--', color='red',
                                      fill=None, alpha=1))

        plt.title('Selected Region ' + harmonic_ij[0] + harmonic_ij[1],
                  fontsize=18, weight='bold')
        plt.show(block=False)

    return imgFFT[idxPeak_ij[0] - periodVert//2:
                  idxPeak_ij[0] + periodVert//2,
                  idxPeak_ij[1] - periodHor//2:
                  idxPeak_ij[1] + periodHor//2]
示例#48
0
文件: pstd.py 项目: FRidh/pstd
def sync_steps(p, v, p_fft, k, kappa, spacing, timestep, density, soundspeed, abs_exp_p, abs_exp_v, source_p, source_v):
    
    v = velocity_with_pml(v, ifft2(to_pressure_gradient(p_fft, k, kappa, spacing)), timestep, density, abs_exp_v, source_v)
    p = pressure_with_pml(p, ifft2(to_velocity_gradient(fft2(v), k, kappa, spacing)), timestep, density, soundspeed, abs_exp_p, source_p)
    
    return p, v
示例#49
0
def fftFromLiteMap(liteMap, applySlepianTaper=False, nresForSlepian=3.0, threads=1):
    """
    Create an fft2D object from a liteMap.
    
    Parameters
    ----------
    liteMap : liteMap.liteMap 
        The map object whose fft is being taken.
    applySlepianTaper : bool, optional 
        If ``True``, apply the lowest order taper (to minimize edge-leakage).
        Default is ``False``.
    nresForSlepian : float, optional 
        If ``applySlepianTaper`` = ``True``, this specifies the resolution of 
        the taper to use. Default is 3.0.
    threads : int, optional
        Number of threads to use in pyFFTW calculations. Default is 1.
        
    Returns
    -------
    ft : fftTools.fft2D
        The fft2D object corresponding the input liteMap.
    """
    ft = fft2D()
        
    ft.Nx = liteMap.Nx
    ft.Ny = liteMap.Ny
    trace.issue("flipper.fftTools", 1, "Taking FFT of map with (Ny, Nx)= (%f, %f)" %(ft.Ny,ft.Nx))
    
    ft.pixScaleX = liteMap.pixScaleX 
    ft.pixScaleY = liteMap.pixScaleY
    
    lx =  2*numpy.pi*fftfreq(ft.Nx, d=ft.pixScaleX)
    ly =  2*numpy.pi*fftfreq(ft.Ny, d=ft.pixScaleY)
    
    ix = numpy.mod(numpy.arange(ft.Nx*ft.Ny), ft.Nx)
    iy = numpy.arange(ft.Nx*ft.Ny)/ft.Nx
    
    modLMap        = numpy.zeros([ft.Ny, ft.Nx])
    modLMap[iy,ix] = numpy.sqrt(lx[ix]**2 + ly[iy]**2)
    ft.modLMap  =  modLMap
    
    ft.lx = lx
    ft.ly = ly
    ft.ix = ix
    ft.iy = iy
    ft.thetaMap = numpy.zeros([ft.Ny, ft.Nx])
    ft.thetaMap[iy[:], ix[:]] = numpy.arctan2(ly[iy[:]], lx[ix[:]])
    ft.thetaMap *= 180./numpy.pi
    
    mp = liteMap.data.copy()
    taper = mp.copy()*0. + 1.0

    if (applySlepianTaper):
        try:
            f = open(taperDir + os.path.sep + 'taper_Ny%d_Nx%d_Nres%3.1f' %(ft.Ny, ft.Nx, nresForSlepian))
            taper = pickle.load(f)
            f.close()
        except:
            taper = slepianTaper00(ft.Nx, ft.Ny,nresForSlepian)
            f = open(taperDir + os.path.sep + 'taper_Ny%d_Nx%d_Nres%3.1f'%(ft.Ny, ft.Nx, nresForSlepian), mode="w")
            pickle.dump(taper,f)
            f.close()
    
    if have_pyFFTW: 
        ft.kMap = fft2(mp*taper, threads=threads)
    else:
        ft.kMap = fft2(mp*taper)
    del mp, modLMap, lx, ly
    return ft
示例#50
0
def upgradePixelPitch(m, N=1, threads=1):
    """
    Go to finer pixels with fourier interpolation.
    
    Parameters
    ----------
    m : liteMap
        The liteMap object holding the data to upgrade the pixel size of. 
    N : int, optional
        Go to 2^N times smaller pixels. Default is 1.
    threads : int, optional
        Number of threads to use in pyFFTW calculations. Default is 1.
    
    Returns
    -------
    mNew : liteMap
        The map with smaller pixels.
    """
    if N < 1:
        return m.copy()

    Ny = m.Ny * 2 ** N
    Nx = m.Nx * 2 ** N
    npix = Ny * Nx

    if have_pyFFTW:
        ft = fft2(m.data, threads=threads)
    else:
        ft = fft2(m.data)
    ftShifted = fftshift(ft)
    newFtShifted = numpy.zeros((Ny, Nx), dtype=numpy.complex128)

    # From the numpy.fft.fftshift help:
    # """
    # Shift zero-frequency component to center of spectrum.
    #
    # This function swaps half-spaces for all axes listed (defaults to all).
    # If len(x) is even then the Nyquist component is y[0].
    # """
    #
    # So in the case that we have an odd dimension in our map, we want to put
    # the extra zero at the beginning

    if m.Nx % 2 != 0:
        offsetX = (Nx - m.Nx) / 2 + 1
    else:
        offsetX = (Nx - m.Nx) / 2
    if m.Ny % 2 != 0:
        offsetY = (Ny - m.Ny) / 2 + 1
    else:
        offsetY = (Ny - m.Ny) / 2

    newFtShifted[offsetY : offsetY + m.Ny, offsetX : offsetX + m.Nx] = ftShifted
    del ftShifted
    ftNew = ifftshift(newFtShifted)
    del newFtShifted

    # Finally, deconvolve by the pixel window
    mPix = numpy.copy(numpy.real(ftNew))
    mPix[:] = 0.0
    mPix[
        mPix.shape[0] / 2 - (2 ** (N - 1)) : mPix.shape[0] / 2 + (2 ** (N - 1)),
        mPix.shape[1] / 2 - (2 ** (N - 1)) : mPix.shape[1] / 2 + (2 ** (N - 1)),
    ] = (1.0 / (2.0 ** N) ** 2)

    if have_pyFFTW:
        ftPix = fft2(mPix, threads=threads)
    else:
        ftPix = fft2(mPix)

    del mPix
    inds = numpy.where(ftNew != 0)
    ftNew[inds] /= numpy.abs(ftPix[inds])

    if have_pyFFTW:
        newData = ifft2(ftNew, threads=threads) * (2 ** N) ** 2
    else:
        newData = ifft2(ftNew) * (2 ** N) ** 2
    del ftNew
    del ftPix

    x0_new, y0_new = m.pixToSky(0, 0)

    m = m.copy()  # don't overwrite original
    m.wcs.header.update("NAXIS1", 2 ** N * m.wcs.header["NAXIS1"])
    m.wcs.header.update("NAXIS2", 2 ** N * m.wcs.header["NAXIS2"])
    m.wcs.header.update("CDELT1", m.wcs.header["CDELT1"] / 2.0 ** N)
    m.wcs.header.update("CDELT2", m.wcs.header["CDELT2"] / 2.0 ** N)
    m.wcs.updateFromHeader()

    p_x, p_y = m.skyToPix(x0_new, y0_new)

    m.wcs.header.update("CRPIX1", m.wcs.header["CRPIX1"] - p_x)
    m.wcs.header.update("CRPIX2", m.wcs.header["CRPIX2"] - p_y)
    m.wcs.updateFromHeader()

    mNew = liteMapFromDataAndWCS(numpy.real(newData), m.wcs)
    mNew.data[:] = numpy.real(newData[:])
    return mNew