示例#1
0
    def applyWeights(self,img_red,ws_img):

        af = self.af
        af2 = self.af2
        
        nc, ny, nx = ws_img.shape[1:]
        nc, nyr, nxr = img_red.shape
        
        if (ny > nyr):
          
            af = round(ny/nyr)
            af2 = round(nx/nxr)
            print('Assuming the data is passed without zeros at not sampled lines ......')
            print('Acceleration factor is af = ' + str(af) + '.....')
            sig_red = img_red
            for idx in range(1,3):
                sig_red = fftshift(fft(fftshift(sig_red,axes=idx),axis=idx,norm='ortho'),axes=idx)
                
            sig_new = np.zeros((nc,ny,nx),dtype=np.complex64)
            sig_new[:,::af,::af2] = sig_red
            img_red = sig_new
            for idx in range(1,3):
                img_red = ifftshift(ifft(ifftshift(img_red,axes=idx),axis=idx,norm='ortho'),axes=idx)
                
        recon = np.zeros((nc,ny,nx),dtype=np.complex64)
        
        for k in range(0,nc):
            recon[k,:,:] = np.sum(ws_img[k,:,:,:] * img_red,axis=0)
            
        return recon
示例#2
0
 def ringthickness(self):
     """
     Define indexes for ring_thick
     """
     nmax = np.max(self.n)
     x = (np.arange(-np.fix(self.nc / 2.0), np.ceil(self.nc / 2.0)) *
          np.floor(nmax / 2.0) / np.floor(self.nc / 2.0))
     y = (np.arange(-np.fix(self.nr / 2.0), np.ceil(self.nr / 2.0)) *
          np.floor(nmax / 2.0) / np.floor(self.nr / 2.0))
     # bring the central pixel to the corners  (important for odd array dimensions)
     x = ifftshift(x)
     y = ifftshift(y)
     if self.ndim == 2:
         # meshgriding
         X = np.meshgrid(x, y)
     elif self.ndim == 3:
         z = (np.arange(-np.fix(self.ns / 2.0), np.ceil(self.ns / 2.0)) *
              np.floor(nmax / 2.0) / np.floor(self.ns / 2.0))
         # bring the central pixel to the corners  (important for odd array dimensions)
         z = ifftshift(z)
         # meshgriding
         X = np.meshgrid(y, z, x)
     # sum of the squares independent of ndim
     sumsquares = np.zeros_like(X[0])
     for ii in range(len(X)):
         sumsquares += X[ii]**2
     index = np.round(np.sqrt(sumsquares)).astype(np.int)
     return index
示例#3
0
def _applyPMD_einsum(field, H, h3):
    Sf = fft.fftshift(fft.fft(fft.ifftshift(field, axes=1),axis=1), axes=1)
    SSf = np.einsum('ijk,ik -> ik',H , Sf)
    SS = fft.fftshift(fft.ifft(fft.ifftshift(SSf, axes=1),axis=1), axes=1)
    SS = np.dot(h3, SS)
    try:
        return field.recreate_from_np_array(SS.astype(field.dtype))
    except:
        return SS.astype(field.dtype)
示例#4
0
def _applyPMD_dot(field, theta, t_dgd, omega):
    Sf = fft.fftshift(fft.fft(fft.ifftshift(field, axes=1),axis=1), axes=1)
    Sff = rotate_field(Sf, theta)
    h2 = np.array([np.exp(-1.j*omega*t_dgd/2),  np.exp(1.j*omega*t_dgd/2)])
    Sn = Sff*h2
    Sf2 = rotate_field(Sn, -theta)
    SS = fft.fftshift(fft.ifft(fft.ifftshift(Sf2, axes=1), axis=1), axes=1)
    try:
        return field.recreate_from_np_array(SS.astype(field.dtype))
    except:
        return SS.astype(field.dtype)
示例#5
0
    def test_expand_fourier_sp_even2d(self):
        """
        test function with even input size
        """
        arr = np.random.rand(100, 100)
        arr_ft = fft.fftshift(fft.fft2(fft.ifftshift(arr)))

        arr_ex_ft = tools.resample_bandlimited_ft(arr_ft, (2, 2))
        arr_exp = fft.fftshift(fft.ifft2(fft.ifftshift(arr_ex_ft))).real

        max_err = np.max(np.abs(arr_exp[::2, ::2] - arr))
        self.assertTrue(max_err < 1e-14)
示例#6
0
    def test_expand_fourier_sp_odd1d(self):
        """
        Test function with odd input size
        """
        arr = np.random.rand(151)
        arr_ft = fft.fftshift(fft.fft(fft.ifftshift(arr)))

        arr_ex_ft = tools.resample_bandlimited_ft(arr_ft, (2, ))
        arr_exp = fft.fftshift(fft.ifft(fft.ifftshift(arr_ex_ft))).real

        max_err = np.max(np.abs(arr_exp[1::2] - arr))
        self.assertTrue(max_err < 1e-14)
示例#7
0
    def test_estimate_phase(self):
        """
        Test estimate_phase() function, which guesses phase from value of image FT
        :return:
        """
        # set parameters
        dx = 0.065
        nx = 2048
        f = 1 / 0.25
        angle = 30 * np.pi / 180
        frqs = [f * np.cos(angle), f * np.sin(angle)]
        phi = 0.2377747474

        # create sample image with origin in center
        x_center = tools.get_fft_pos(nx, dx)
        y_center = x_center
        xx_center, yy_center = np.meshgrid(x_center, y_center)
        m_center = 1 + 0.2 * np.cos(
            2 * np.pi * (frqs[0] * xx_center + frqs[1] * yy_center) + phi)

        m_center_ft = fft.fftshift(fft.fft2(fft.ifftshift(m_center)))

        phase_guess_center = sim.get_phase_ft(m_center_ft, frqs, dx)

        self.assertAlmostEqual(phi, float(phase_guess_center), places=5)
示例#8
0
    def test_translate_ft(self):
        """
        Test translate_ft() function
        :return:
        """

        img = np.random.rand(100, 100)
        img_ft = fft.fftshift(fft.fft2(fft.ifftshift(img)))
        dx = 0.065

        fx = tools.get_fft_frqs(img.shape[1], dx)
        fy = tools.get_fft_frqs(img.shape[0], dx)
        df = fx[1] - fx[0]

        # x-shifting
        for n in range(1, 20):
            img_ft_shifted = tools.translate_ft(img_ft, [n * df, 0], dx)
            max_err = np.abs(img_ft_shifted[:, :-n] - img_ft[:, n:]).max()
            self.assertTrue(max_err < 1e-7)

        # y-shifting
        for n in range(1, 20):
            img_ft_shifted = tools.translate_ft(img_ft, [0, n * df], dx)
            max_err = np.abs(img_ft_shifted[:-n, :] - img_ft[n:, :]).max()
            self.assertTrue(max_err < 1e-7)

        # x+y shifting
        for n in range(1, 20):
            img_ft_shifted = tools.translate_ft(img_ft, [n * df, n * df], dx)
            max_err = np.abs(img_ft_shifted[:-n, :-n] - img_ft[n:, n:]).max()
            self.assertTrue(max_err < 1e-7)
示例#9
0
    def test_fit_modulation_frq(self):
        """
        Test fit_modulation_frq() function

        :return:
        """
        # set parameters
        options = {'pixel_size': 0.065, 'wavelength': 0.5, 'na': 1.3}
        fmax = 1 / (0.5 * options["wavelength"] / options["na"])
        nx = 512
        f = 1 / 0.25
        angle = 30 * np.pi / 180
        frqs = [f * np.cos(angle), f * np.sin(angle)]
        phi = 0.2377747474

        # create sample image
        x = options['pixel_size'] * np.arange(nx)
        y = x
        xx, yy = np.meshgrid(x, y)
        m = 1 + 0.5 * np.cos(2 * np.pi * (frqs[0] * xx + frqs[1] * yy) + phi)

        mft = fft.fftshift(fft.fft2(fft.ifftshift(m)))
        frq_extracted, mask, = sim.fit_modulation_frq(mft,
                                                      mft,
                                                      options["pixel_size"],
                                                      fmax,
                                                      exclude_res=0.6)

        self.assertAlmostEqual(np.abs(frq_extracted[0]),
                               np.abs(frqs[0]),
                               places=5)
        self.assertAlmostEqual(np.abs(frq_extracted[1]),
                               np.abs(frqs[1]),
                               places=5)
示例#10
0
def add_dispersion(sig, fs, D, L, wl0=1550e-9):
    """
    Add dispersion to signal.

    Parameters
    ----------
    sig : array_like
        input signal
    fs : flaot
        sampling frequency of the signal (in SI units)
    D : float
        Dispersion factor in s/m/m
    L : float
        Length of the dispersion in m
    wl0 : float,optional
        center wavelength of the signal

    Returns
    -------
    sig_out : array_like
        dispersed signal
    """
    C = 2.99792458e8
    N = sig.shape[-1]
    omega = fft.fftfreq(N, 1/fs)*np.pi*2
    beta2 = D * wl0**2 / (C*np.pi*2)
    H = np.exp(-0.5j * omega**2 * beta2 * L).astype(sig.dtype)
    sff = fft.fft(fft.ifftshift(sig, axes=-1), axis=-1)
    sig_out = fft.fftshift(fft.ifft(sff*H))
    return sig_out
示例#11
0
    def test_test_patterns(self):
        """
        Generate SIM test patterns with no noise or OTF blurring, and verify that these can be reconstructed.
        :return:
        """
        gt = sim.get_test_pattern([600, 600])
        otf = np.ones(gt.shape)
        frqs = np.array([[0.21216974, 3.97739458], [-3.17673383, 1.97618225],
                         [3.24054346, 1.8939568]])
        phases = np.zeros((3, 3))
        phases[:, 0] = 0
        phases[:, 1] = 2 * np.pi / 3
        phases[:, 2] = 4 * np.pi / 3
        mod_depths = np.array([[0.9, 0.8, 0.87], [1, 0.98, 0.88],
                               [0.89, 0.912, 0.836]])
        amps = np.array([[1, 0.7, 1.1], [1, 1.16, 0.79], [1, 0.83, 1.2]])

        max_photons = 1
        sim_imgs, _ = sim.get_simulated_sim_imgs(gt,
                                                 frqs,
                                                 phases,
                                                 mod_depths,
                                                 max_photons,
                                                 1,
                                                 0,
                                                 0,
                                                 0.065,
                                                 amps,
                                                 otf=otf,
                                                 photon_shot_noise=False)
        nangles, nphases, ny, nx = sim_imgs.shape

        imgs_ft = np.zeros(sim_imgs.shape, dtype=np.complex)
        for ii in range(nangles):
            for jj in range(nphases):
                imgs_ft[ii, jj] = fft.fftshift(
                    fft.fft2(fft.ifftshift(sim_imgs[ii, jj])))

        separated_components = sim.do_sim_band_separation(
            imgs_ft, phases, mod_depths, amps)

        gt_per_angle = np.zeros((nangles, ny, nx))
        for ii in range(nangles):
            gt_per_angle[ii] = fft.fftshift(
                fft.ifft2(fft.ifftshift(separated_components[ii, 0]))).real

            np.testing.assert_allclose(gt, gt_per_angle[ii], atol=1e-14)
示例#12
0
    def __init__(self, psf0, psf1, wvl, dx, dz, fno, phase_guess=None):
        """Create a new MiselTwoPSF problem.

        Parameters
        ----------
        psf0 : `numpy.ndarray`
            array containing the incoherent PSF, |F_0|^2, of shape (m,n)
        psf1 : `numpy.ndarray`
            array containing the defocused PSF, |F_1|^2, of shape (m,n)
        wvl : `float`
            wavelength, microns
        dx : `float`
            inter-sample spacing for both psf0 and psf1, microns
        dz : `float`
            longitudinal separation between psf0 and psf1, microns
        fno : `float`
            f number, dimmensionless
        phase_guess : `numpy.ndarray`
            array containing the guess for the phase, np.angle(g), of shape (m,n)

        """
        # this code is basically identical to _init_iterative_transform
        if phase_guess is None:
            phase_guess = np.random.rand(*psf0.shape)

        absF0 = np.sqrt(psf0)
        absF1 = np.sqrt(psf1)

        self.absF0 = fft.ifftshift(absF0)
        self.absF1 = fft.ifftshift(absF1)
        phase_guess = fft.ifftshift(phase_guess)

        self.G0 = self.absF0 * np.exp(1j * phase_guess)
        self.G1 = self.absF1  # per Misel, initialization of defocused plane is zero phase

        # only compute the transfer function between 0 -> 1 and 1 -> 0 one time
        # for efficiency
        self.tf0to1 = _angular_spectrum_transfer_function(
            psf0.shape, wvl, dx, dz)
        self.tf1to0 = _angular_spectrum_transfer_function(
            psf0.shape, wvl, dx, -dz)

        self.mse_denom0 = np.sum((self.absF0)**2)
        self.mse_denom1 = np.sum((self.absF1)**2)
        self.iter = 0
        self.costF0 = []
        self.costF1 = []
示例#13
0
    def test_expand_fourier_sp(self):
        """
        Test expand_fourier_sp() function
        :return:
        """

        arr = np.array([[1, 2], [3, 4]])
        arr_ft = fft.fftshift(fft.fft2(fft.ifftshift(arr)))

        arr_ft_ex = tools.resample_bandlimited_ft(arr_ft, (2, 2))
        arr_ex = fft.fftshift(fft.ifft2(fft.ifftshift(arr_ft_ex)))

        self.assertTrue(
            np.array_equal(
                arr_ex.real,
                np.array([[1, 1.5, 2, 1.5], [2, 2.5, 3, 2.5], [3, 3.5, 4, 3.5],
                          [2, 2.5, 3, 2.5]])))
示例#14
0
def _asm_sfft(cmode_to_propagate, wavelength, nx, ny, xstart, ystart, xend,
              yend, rx, ry, distance):

    dx = (xstart - xend) / nx
    dy = (ystart - yend) / ny

    fx = np.linspace(-1 / (2 * dx), 1 / (2 * dx), nx)
    fy = np.linspace(-1 / (2 * dy), 1 / (2 * dy), ny)

    mesh_fx, mesh_fy = np.meshgrid(fx, fy)

    impulse = np.exp(-1j * 2 * np.pi * distance *
                     np.sqrt(1 / wavelength**2 - (mesh_fx**2 + mesh_fy**2)))

    cmode_to_propagate = fft.ifftshift(fft.fft2(cmode_to_propagate))
    propagated_cmode = fft.ifft2(fft.ifftshift(impulse * cmode_to_propagate))

    return propagated_cmode
示例#15
0
def _init_iterative_transform(self, psf, pupil_amplitude, phase_guess=None):
    """Initialize an instance of an iterative transform type algorithm."""
    # python teaching moment -- self as an argument name is only a convention,
    # and carries no special meaning.  This function exists to refactor the
    # various iterative transform types without subclassing or inheritance
    if phase_guess is None:
        phase_guess = np.random.rand(*pupil_amplitude.shape)

    absF = np.sqrt(psf)
    absg = pupil_amplitude

    self.absF = fft.ifftshift(absF)
    self.absg = fft.ifftshift(absg)
    phase_guess = fft.ifftshift(phase_guess)

    self.g = self.absg * np.exp(1j * phase_guess)
    self.mse_denom = np.sum((self.absF)**2)
    self.iter = 0
    self.costF = []
示例#16
0
 def calcGfact(self,ws_img,imgref):
     af = self.af
     af2 = self.af2
     corr_mtx = self.corr_mtx
     
     nc, ny, nx = ws_img.shape[1:]
     
     ws_img = ws_img/(af*af2)
     
     print('Calculating G-factor......')
     sigref = imgref
     for idx in range(1,3):
         sigref = fftshift(fft(fftshift(sigref,axes=idx),axis=idx,norm='ortho'),axes=idx)
             
     nc, nyref, nxref = sigref.shape
     
     # filter kspace
     sigref = sigref * np.reshape(tukey(nyref,alpha=1),(1, nyref, 1))
     sigref = sigref * np.reshape(tukey(nxref,alpha=1),(1, 1, nxref))
     # 
     sigreff = np.zeros((nc,ny,nx),dtype=np.complex64)
     yidx = slice(int(np.floor((ny-nyref)/2)),int(nyref + np.floor((ny-nyref)/2)))
     xidx = slice(int(np.floor((nx-nxref)/2)),int(nxref + np.floor((nx-nxref)/2)))
     sigreff[:,yidx,xidx] = sigref
     
     imgref = sigreff
     for idx in range(1,3):
         imgref = ifftshift(ifft(ifftshift(imgref,axes=idx),axis=idx,norm='ortho'),axes=idx)
                 
     g = np.zeros((ny,nx))
     
     for y in range(0,ny):
         for x in range(0,nx):
             tmp = imgref[:,y,x]
             norm_tmp = norm2(tmp,2)
             
             W = ws_img[:,:,y,x]            # Weights in image space
             n = tmp.conj().T / norm_tmp
             # This is the generalized g-factor formulation
             g[y,x] = np.sqrt(np.abs((n@W)@(corr_mtx@((n@W).conj().T)))) / np.sqrt(np.abs(n@(corr_mtx@(n.conj().T))))       
    
     return g
示例#17
0
def fft_hankel(integrator,
               integrator_args,
               integrator_kwargs,
               log_limit,
               npoints,
               in_ndim=0,
               is_complex=True,
               fft=scipy.fft):
    """Inverse HankelTransform using Fast Fourier Transform"""
    if hasattr(fft, "next_fast_len"):
        npoints = fft.next_fast_len(npoints, not is_complex)
    sp = np.linspace(-log_limit, log_limit, npoints)
    dt = sp[1] - sp[0]
    wq = 2 * pi * (fft.fftfreq if is_complex else fft.rfftfreq)(len(sp), dt)
    dw = wq[1] - wq[0]
    sp = _expand_first_ndim(sp, in_ndim)
    wq = _expand_first_ndim(wq, in_ndim)
    s = np.exp(-sp)
    r = np.exp(sp)
    # Weird tricks ahead to reduce memory usage
    res = np.nan_to_num(integrator(s, *integrator_args, **integrator_kwargs),
                        copy=False)
    res *= s
    shifted = fft.ifftshift(res, axes=-1)
    del res
    fres = (fft.fft if is_complex else fft.rfft)(shifted,
                                                 norm="ortho",
                                                 axis=-1)
    del shifted
    fres *= dt
    fres *= fourierBesselJv(wq)
    shifted_hres = (fft.ifft if is_complex else fft.irfft)(fres,
                                                           norm="ortho",
                                                           axis=-1)
    del fres
    hres = fft.ifftshift(shifted_hres, axes=-1)
    del shifted_hres
    hres *= sp.size * dw / (2 * pi)
    hres /= r
    return sp, hres
示例#18
0
def _get_nd_butterworth_filter(shape,
                               factor,
                               order,
                               high_pass,
                               real,
                               dtype=np.float64,
                               squared_butterworth=True):
    """Create a N-dimensional Butterworth mask for an FFT

    Parameters
    ----------
    shape : tuple of int
        Shape of the n-dimensional FFT and mask.
    factor : float
        Fraction of mask dimensions where the cutoff should be.
    order : float
        Controls the slope in the cutoff region.
    high_pass : bool
        Whether the filter is high pass (low frequencies attenuated) or
        low pass (high frequencies are attenuated).
    real : bool
        Whether the FFT is of a real (True) or complex (False) image
    squared_butterworth : bool, optional
        When True, the square of the Butterworth filter is used.

    Returns
    -------
    wfilt : ndarray
        The FFT mask.

    """
    ranges = []
    for i, d in enumerate(shape):
        # start and stop ensures center of mask aligns with center of FFT
        axis = np.arange(-(d - 1) // 2, (d - 1) // 2 + 1) / (d * factor)
        ranges.append(fft.ifftshift(axis**2))
    # for real image FFT, halve the last axis
    if real:
        limit = d // 2 + 1
        ranges[-1] = ranges[-1][:limit]
    # q2 = squared Euclidian distance grid
    q2 = functools.reduce(np.add,
                          np.meshgrid(*ranges, indexing="ij", sparse=True))
    q2 = q2.astype(dtype)
    q2 = np.power(q2, order)
    wfilt = 1 / (1 + q2)
    if high_pass:
        wfilt *= q2
    if not squared_butterworth:
        np.sqrt(wfilt, out=wfilt)
    return wfilt
示例#19
0
def _fresnel_old_dfft(cmode_to_propagate, wavelength, nx, ny, xstart, ystart,
                      xend, yend, rx, ry, distance):

    # Warning! The fft2 of impulse function and ic should be done together with
    # numpy fft fft2. Or some speckle will apear.
    """
    Double FFT Fresnel propagation of coherent mode.
    
    Args: cmode_to_propagate - the coherent mode to propagate.
          cmode_mask         - the mask of coherent mode.
          wavelength         - the wavelength of light field.
          nx                 - the dim of aixs x.
          ny                 - the dim of axis y.
          xstart             - location of start along axis x.
          ystart             - location of start along axis y.
          xend               - location of end along axis x.
          yend               - lcoation of end along axis y.
          rx                 - the range of x.
          ry                 - the range of y.
          distance           - the distance of the propagation.
          
    Return: propagated coherent mode.
    """

    # cmode_to_propagate = cmode_to_propagate

    # wave number k

    wave_num = 2 * np.pi / wavelength

    # the axis in frequency space

    x0 = np.linspace(xstart, xend, nx)
    y0 = np.linspace(ystart, yend, ny)

    mesh_x, mesh_y = np.meshgrid(x0, y0)

    # propagation function

    impulse = (np.exp(1j * wave_num * distance) *
               np.exp(-1j * wave_num * (mesh_x**2 + mesh_y**2) /
                      (2 * distance)) / (1j * wavelength * distance))

    # the multiply of coherent mode and propagation function

    propagated_cmode = fft.ifftshift(
        fft.ifft2(fft.fft2(cmode_to_propagate) * fft.fft2(impulse)))

    return propagated_cmode
示例#20
0
    def __init__(self, psf, pupil_amplitude, phase_guess=None, beta=1):
        """Create a new Hybrid Input-Output problem.

        Parameters
        ----------
        psf : `numpy.ndarray`
            array containing the incoherent PSF, |G|^2, of shape (m,n)
        pupil_amplitude : `numpy.ndarray`
            array containing the amplitude of the pupil, |g|, of shape (m,n)
        phase_guess : `numpy.ndarray`
            array containing the guess for the phase, np.angle(g), of shape (m,n)
        beta : `bool`, optional
            gain parameter

        Notes
        -----
        psf and pupil_amplitude should both be centered with the origin in the
        middle of the array.

        """
        if phase_guess is None:
            phase_guess = np.random.rand(*pupil_amplitude.shape)

        absF = np.sqrt(psf)
        absg = pupil_amplitude

        self.absF = fft.ifftshift(absF)
        self.absg = fft.ifftshift(absg)
        phase_guess = fft.ifftshift(phase_guess)

        self.g = self.absg * np.exp(1j * phase_guess)
        self.supportmask = absg < 1e-6
        self.iter = 0
        self.beta = beta
        self.costF = []
        self.costf = []
示例#21
0
def hybrid(low, high, factor=.8, cutoff_low=25, cutoff_high=20):
    low_pass_input_image, low_std = low
    high_pass_input_image, high_std = high

    # get low fft
    low_fft = low_pass_filter(low_pass_input_image, low_std, cutoff_low)

    # save low image frequency domain
    # low_fft_image = 8 * np.log(np.abs(low_fft))
    # cv.imwrite('q4_12_lowpassed.jpg', low_fft_image, )

    # calculate low image in spatial domain
    low = np.abs(fft.ifft2(fft.ifftshift(low_fft)))

    ##############

    # get high fft
    high_fft = high_pass_filter(high_pass_input_image, high_std, cutoff_high)

    # save high image frequency domain
    # high_fft_image = 8 * np.log(np.abs(high_fft))
    # cv.imwrite('q4_11_highpassed.jpg', high_fft_image)

    # calculate low image in spatial domain
    high = np.abs(fft.ifft2(fft.ifftshift(high_fft)))

    # calculate hybrid fft
    hybrid_fft = factor * low_fft + (1 - factor) * high_fft

    # save hybrid image frequency domain
    # hybrid_fft_image = 8 * np.log(np.abs(hybrid_fft))
    # cv.imwrite('q4_13_hybrid_frequency.jpg', hybrid_fft_image)

    hybrid_result = np.abs(fft.ifft2(hybrid_fft))

    return hybrid_result, low, high
示例#22
0
    def getWeights(ws_kernel,ny,nx):
        
        nc, nky, nkx = ws_kernel.shape[1:4]
        
        ws_k = np.zeros((nc,nc,ny,nx),dtype=np.complex64)
        ystart = int(np.ceil((ny-nky)/2))
        ystop = int(np.ceil((ny+nky)/2))
        yrange = slice(ystart,ystop)
        
        xstart = int(np.ceil((nx-nkx)/2))
        xstop = int(np.ceil((nx+nkx)/2))
        xrange = slice(xstart,xstop)
        
        ws_k[:,:,yrange,xrange] = ws_kernel  #put reconstruction kernel in the center of matrix

        tmp0 = ifftshift(ws_k,axes=2)           # shift in phase
        tmp1 = ifftshift(tmp0,axes=3)           # shift in read
        tmp0 = ifft(tmp1,axis=2,norm='ortho')             # ifft in phase
        tmp1 = ifft(tmp0,axis=3,norm='ortho')             # ifft in read
        tmp0 = ifftshift(tmp1,axes=2)           # shift in phase
        tmp1 = ifftshift(tmp0,axes=3)          # shift in read
        
        ws_img = np.sqrt(ny*nx)*tmp1
        return ws_img
示例#23
0
文件: amos.py 项目: apertif/amosaic
def reconvolve_gaussian_kernel(img, old_maj, old_min, old_pa, new_maj, new_min, new_pa):
    """
    convolve image with a gaussian kernel without FFTing it
    bmaj, bmin -- in pixels,
    bpa -- in degrees from top clockwise (like in Beam)
    inverse -- use True to deconvolve.
    NOTE: yet works for square image without NaNs
    """
    size = len(img)
    imean = img.mean()
    img -= imean
    fimg = np.fft.fft2(img)
    krel = fft_psf(new_maj, new_min, new_pa, size) / fft_psf(old_maj, old_min, old_pa, size)
    fconv = fimg * ifftshift(krel)
    return ifft2(fconv).real + imean
示例#24
0
    def test_xform_sinusoid_params_roi(self):
        """
        Test function xform_sinusoid_params_roi() by constructing sinusoid pattern and passing through an affine
        transformation. Compare the resulting frequency determined numerically with the resulting frequency determined
        from the initial frequency + affine parameters
        :return:
        """
        # define object space parameters
        # roi_img = [0, 2048, 0, 2048]
        roi_img = [512, 788, 390, 871]

        fobj = np.array([0.08333333, 0.08333333])
        phase_obj = 5.497787143782089
        fn = lambda x, y: 1 + np.cos(2 * np.pi * (fobj[0] * x + fobj[1] * y) + phase_obj)

        # define affine transform
        xform = affine.params2xform([1.4296003114502853, 2.3693263411981396, 2671.39109,
                                     1.4270495211450602, 2.3144621088632635, 790.402632])

        # sinusoid parameter transformation
        fxi, fyi, phase_roi = affine.xform_sinusoid_params_roi(fobj[0], fobj[1], phase_obj, None, roi_img, xform,
                                                               input_origin="edge", output_origin="edge")
        fimg = np.array([fxi, fyi])

        # FFT phase
        _, _, phase_roi_ft = affine.xform_sinusoid_params_roi(fobj[0], fobj[1], phase_obj, None, roi_img, xform,
                                                              input_origin="edge", output_origin="fft")

        # compared with phase from fitting image directly
        out_coords = np.meshgrid(range(roi_img[2], roi_img[3]), range(roi_img[0], roi_img[1]))
        img = affine.xform_fn(fn, xform, out_coords)
        phase_fit_roi = float(sim.get_phase_realspace(img, fimg, 1, phase_guess=phase_roi, origin="edge"))

        # phase FFT
        ny, nx = img.shape
        window = scipy.signal.windows.hann(nx)[None, :] * scipy.signal.windows.hann(ny)[:, None]
        img_ft = fft.fftshift(fft.fft2(fft.ifftshift(img * window)))
        fx = tools.get_fft_frqs(nx, 1)
        fy = tools.get_fft_frqs(ny, 1)

        peak = tools.get_peak_value(img_ft, fx, fy, fimg, 2)
        phase_fit_roi_ft = np.mod(np.angle(peak), 2*np.pi)

        # accuracy is limited by frequency fitting routine...
        self.assertAlmostEqual(phase_roi, phase_fit_roi, 1)
        # probably limited by peak height finding routine
        self.assertAlmostEqual(phase_roi_ft, phase_fit_roi_ft, 3)
示例#25
0
def test_buffer():
    """Test that CPU & GPU outputs match for `modulated=True` & `=False`,
    and that `modulated=True` matches `ifftshift(buffer(modulated=False))`.
    Also that single- & multi-thread CPU outputs agree.

    Test both single and batched input.
    """
    N = 128
    tsigs = TestSignals(N=N)

    for dtype in ('float64', 'float32'):
        for ndim in (1, 2):
            x = (tsigs.cosine()[0].astype(dtype)
                 if ndim == 1 else np.random.randn(4, N))
            xt = torch.as_tensor(x, device='cuda') if CAN_GPU else 0
            for modulated in (False, True):
                for seg_len in (N // 2, N // 2 - 1):
                    for n_overlap in (N // 2 - 1, N // 2 - 2, N // 2 - 3):
                        if seg_len == n_overlap:
                            continue

                        out0 = buffer(x,
                                      seg_len,
                                      n_overlap,
                                      modulated,
                                      parallel=True)
                        if modulated:
                            out00 = buffer(x,
                                           seg_len,
                                           n_overlap,
                                           modulated=False,
                                           parallel=False)
                            out00 = ifftshift(out00,
                                              axes=0 if ndim == 1 else 1)
                        if CAN_GPU:
                            out1 = buffer(xt, seg_len, n_overlap,
                                          modulated).cpu().numpy()

                        assert_params = (dtype, modulated, seg_len, n_overlap)
                        if modulated:
                            adiff000 = np.abs(out0 - out00).mean()
                            assert adiff000 == 0, (*assert_params, adiff000)
                        if CAN_GPU:
                            adiff01 = np.abs(out0 - out1).mean()
                            assert adiff01 == 0, (*assert_params, adiff01)
示例#26
0
def fourier_grid(n_pixels, n_pad_pixels):

    pi = np.pi

    n_elements = int(np.floor((n_pixels + 2 * n_pad_pixels)/2 + (n_pixels + 2 * n_pad_pixels)/2))

    # Create real grid from linspace 
    x = np.linspace(-(n_pixels + 2 * n_pad_pixels)/2, (n_pixels + 2 * n_pad_pixels)/2 - 1, num=n_elements)
    y = x
    XSI1, XSI2 = np.meshgrid( x, y ) 

    # Normalize
    XSI1 = (2 * pi) / (n_pixels + 2 * n_pad_pixels) * XSI1
    XSI2 = (2 * pi) / (n_pixels + 2 * n_pad_pixels) * XSI2

    # Create Fourier grid
    XSISQ = ifftshift(XSI1 ** 2 + XSI2 ** 2)

    return XSISQ
示例#27
0
def _fresnel_dfft(cmode_to_propagate, wavelength, nx, ny, xstart, ystart, xend,
                  yend, rx, ry, distance):

    # Warning! The fft2 of impulse function and ic should be done together with
    # numpy fft fft2. Or some speckle will apear.
    """
    Double FFT Fresnel propagation of coherent mode.
    
    Args: cmode_to_propagate - the coherent mode to propagate.
          cmode_mask         - the mask of coherent mode.
          wavelength         - the wavelength of light field.
          nx                 - the dim of aixs x.
          ny                 - the dim of axis y.
          xstart             - location of start along axis x.
          ystart             - location of start along axis y.
          xend               - location of end along axis x.
          yend               - location of end along axis y.
          rx                 - the range of x.
          ry                 - the range of y.
          distance           - the distance of the propagation.
          
    Return: propagated coherent mode.
    """

    # wave number k
    wave_num = 2 * np.pi / wavelength

    # the axis in frequency space
    qx = np.linspace(0.25 / xstart, 0.25 / xend, nx) * nx
    qy = np.linspace(0.25 / ystart, 0.25 / yend, ny) * ny

    mesh_qx, mesh_qy = np.meshgrid(qx, qy)

    # propagation function
    impulse_q = np.exp((-1j * wave_num * distance) *
                       (1 - wavelength**2 * (mesh_qx**2 + mesh_qy**2)) / 2)

    # the multiply of coherent mode and propagation function
    propagated_cmode = fft.ifft2(
        fft.fft2(cmode_to_propagate) * fft.ifftshift(impulse_q))

    return propagated_cmode
示例#28
0
def wiener(data, impulse_response=None, filter_params={}, K=0.25,
           predefined_filter=None):
    """Minimum Mean Square Error (Wiener) inverse filter.

    Parameters
    ----------
    data : (M,N) ndarray
        Input data.
    K : float or (M,N) ndarray
        Ratio between power spectrum of noise and undegraded
        image.
    impulse_response : callable `f(r, c, **filter_params)`
        Impulse response of the filter.  See LPIFilter2D.__init__.
    filter_params : dict
        Additional keyword parameters to the impulse_response function.

    Other Parameters
    ----------------
    predefined_filter : LPIFilter2D
        If you need to apply the same filter multiple times over different
        images, construct the LPIFilter2D and specify it here.

    """
    check_nD(data, 2, 'data')

    if not isinstance(K, float):
        check_nD(K, 2, 'K')

    if predefined_filter is None:
        filt = LPIFilter2D(impulse_response, **filter_params)
    else:
        filt = predefined_filter

    F, G = filt._prepare(data)
    _min_limit(F, val=np.finfo(F.real.dtype).eps)

    H_mag_sqr = np.abs(F) ** 2
    F = 1 / F * H_mag_sqr / (H_mag_sqr + K)

    return _centre(np.abs(fft.ifftshift(fft.ifftn(G * F))), data.shape)
示例#29
0
    def test_pattern_main_phase_vs_phase_index(self):
        """
        Test get_sim_phase() on the main frequency component for one SIM pattern. Ensure works for all phase indices.

        Tests only a single pattern vector
        :return:
        """
        nx = 1920
        ny = 1080
        nphases = 3

        fx = tools.get_fft_frqs(nx)
        fy = tools.get_fft_frqs(ny)
        window = scipy.signal.windows.hann(nx)[
            None, :] * scipy.signal.windows.hann(ny)[:, None]

        va = [-3, 11]
        vb = [3, 12]
        # va = [-1, 117]
        # vb = [-6, 117]
        rva, rvb = dmd.get_reciprocal_vects(va, vb)

        for jj in range(nphases):
            phase = dmd.get_sim_phase(va,
                                      vb,
                                      nphases,
                                      jj, [nx, ny],
                                      origin="fft")
            pattern, _ = dmd.get_sim_pattern([nx, ny], va, vb, nphases, jj)
            pattern_ft = fft.fftshift(fft.fft2(fft.ifftshift(pattern *
                                                             window)))

            pattern_phase_est = np.mod(
                np.angle(tools.get_peak_value(pattern_ft, fx, fy, rvb, 2)),
                2 * np.pi)

            # assert np.round(np.abs(pattern_phase_est - float(phase)), 3) == 0
            self.assertAlmostEqual(pattern_phase_est, float(phase), 3)
示例#30
0
def inverse(data, impulse_response=None, filter_params={}, max_gain=2,
            predefined_filter=None):
    """Apply the filter in reverse to the given data.

    Parameters
    ----------
    data : (M,N) ndarray
        Input data.
    impulse_response : callable `f(r, c, **filter_params)`
        Impulse response of the filter.  See LPIFilter2D.__init__.
    filter_params : dict
        Additional keyword parameters to the impulse_response function.
    max_gain : float
        Limit the filter gain.  Often, the filter contains zeros, which would
        cause the inverse filter to have infinite gain.  High gain causes
        amplification of artefacts, so a conservative limit is recommended.

    Other Parameters
    ----------------
    predefined_filter : LPIFilter2D
        If you need to apply the same filter multiple times over different
        images, construct the LPIFilter2D and specify it here.

    """
    check_nD(data, 2, 'data')
    if predefined_filter is None:
        filt = LPIFilter2D(impulse_response, **filter_params)
    else:
        filt = predefined_filter

    F, G = filt._prepare(data)
    _min_limit(F, val=np.finfo(F.real.dtype).eps)

    F = 1 / F
    mask = np.abs(F) > max_gain
    F[mask] = np.sign(F[mask]) * max_gain

    return _centre(np.abs(fft.ifftshift(fft.ifftn(G * F))), data.shape)