Exemple #1
0
    def test_fft_pos(self):

        dt = 0.46436
        for n in [2, 3, 4, 5, 9, 10, 481, 5468]:
            pos = np.arange(n) * dt

            pos_e = tools.get_fft_pos(n, dt, centered=False, mode="positive")
            self.assertAlmostEqual(np.max(np.abs(pos - pos_e)), 0, places=12)

            pos_c = tools.get_fft_pos(n, dt, centered=True, mode="positive")
            self.assertAlmostEqual(np.max(np.abs(fft.fftshift(pos) - pos_c)),
                                   0,
                                   places=12)

            pos = fft.fftshift(pos)
            ind, = np.where(pos == 0)
            pos[:ind[0]] = pos[:ind[0]] - n * dt

            pos_c_symm = tools.get_fft_pos(n,
                                           dt,
                                           centered=True,
                                           mode="symmetric")
            self.assertAlmostEqual(np.max(np.abs(pos - pos_c_symm)),
                                   0,
                                   places=12)
Exemple #2
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)
Exemple #3
0
def phase_fft2edge(frq, phase, img_shape, dx=1):
    """

    :param list[float] or np.array frq:
    :param float phase:
    :param tuple or list img_shape:
    :param float dx:

    :return phase_edge:
    """

    xft = tools.get_fft_pos(img_shape[1],
                            dt=dx,
                            centered=True,
                            mode="symmetric")
    yft = tools.get_fft_pos(img_shape[0],
                            dt=dx,
                            centered=True,
                            mode="symmetric")
    phase_edge = xform_phase_translation(frq[0], frq[1], phase,
                                         [xft[0], yft[0]])

    return phase_edge
Exemple #4
0
    def test_fit_phase_realspace(self):
        """
        Test fit_phase_realspace()
        :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 at edge
        x_edge = dx * np.arange(nx)
        y_edge = x_edge
        xx_edge, yy_edge = np.meshgrid(x_edge, y_edge)
        m_edge = 1 + 0.2 * np.cos(2 * np.pi *
                                  (frqs[0] * xx_edge + frqs[1] * yy_edge) +
                                  phi)

        phase_guess_edge = sim.get_phase_realspace(m_edge,
                                                   frqs,
                                                   dx,
                                                   phase_guess=0,
                                                   origin="edge")

        self.assertAlmostEqual(phi, float(phase_guess_edge), places=5)

        # 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)

        phase_guess_center = sim.get_phase_realspace(m_center,
                                                     frqs,
                                                     dx,
                                                     phase_guess=0,
                                                     origin="center")

        self.assertAlmostEqual(phi, float(phase_guess_center), places=5)
Exemple #5
0
def xform_sinusoid_params_roi(fx,
                              fy,
                              phase,
                              object_size,
                              img_roi,
                              affine_mat,
                              input_origin="fft",
                              output_origin="fft"):
    """
    Transform sinusoid parameter from object space to a region of interest in image space.

    # todo: would it be more appropriate to put this function in sim_reconstruction.py?

    This is an unfortunately complicated function because we have five coordinate systems to worry about
    o: object space coordinates with origin at the corner of the DMD pattern
    o': object space coordinates assumed by fft functions
    i: image space coordinates, with origin at corner of the camera
    r: roi coordinates with origin at the edge of the roi
    r': roi coordinates, with origin near the center of the roi (coordinates for fft)
    The frequencies don't care about the coordinate origin, but the phase does

    :param float fx: x-component of frequency in object space
    :param float fy: y-component of frequency in object space
    :param float phase: phase of pattern in object space coordinates system o or o'.
    :param list[int] object_size: [sy, sx], size of object space, required to define origin of o'
    :param list[int] img_roi: [ystart, yend, xstart, xend], region of interest in image space. Note: this region does not include
    the pixels at yend and xend! In coordinates with integer values the pixel centers, it is the area
    [ystart - 0.5*dy, yend-0.5*dy] x [xstart -0.5*dx, xend - 0.5*dx]
    :param np.array affine_mat: affine transformation matrix, which takes points from o -> i
    :param str input_origin: "fft" if phase is provided in coordinate system o', or "edge" if provided in coordinate sysem o
    :param str output_origin: "fft" if output phase should be in coordinate system r' or "edge" if in coordinate system r

    :return fx_xform: x-component of frequency in coordinate system r'
    :return fy_xform: y-component of frequency in coordinates system r'
    :return phi_xform: phase in coordinates system r or r' (depending on the value of output_origin)
    """

    if input_origin == "fft":
        phase_o = phase_fft2edge([fx, fy], phase, object_size, dx=1)
        # xft = tools.get_fft_pos(object_size[1])
        # yft = tools.get_fft_pos(object_size[0])
        # phase_o = xform_phase_translation(fx, fy, phase, [xft[0], yft[0]])
    elif input_origin == "edge":
        phase_o = phase
    else:
        raise ValueError("input origin must be 'fft' or 'edge' but was '%s'" %
                         input_origin)

    # affine transformation, where here we take coordinate origins at the corners
    fx_xform, fy_xform, phase_i = xform_sinusoid_params(
        fx, fy, phase_o, affine_mat)

    if output_origin == "edge":
        phase_r = xform_phase_translation(fx_xform, fy_xform, phase_i,
                                          [img_roi[2], img_roi[0]])
        phase_xform = phase_r
    elif output_origin == "fft":
        # transform so that phase is relative to center of ROI
        ystart, yend, xstart, xend = img_roi

        x_rp = tools.get_fft_pos(xend - xstart,
                                 dt=1,
                                 centered=True,
                                 mode="symmetric")
        y_rp = tools.get_fft_pos(yend - ystart,
                                 dt=1,
                                 centered=True,
                                 mode="symmetric")

        # origin of rp-coordinate system, written in the i-coordinate system
        cx = xstart - x_rp[0]
        cy = ystart - y_rp[0]

        phase_rp = xform_phase_translation(fx_xform, fy_xform, phase_i,
                                           [cx, cy])
        phase_xform = phase_rp
    else:
        raise ValueError("output_origin must be 'fft' or 'edge' but was '%s'" %
                         output_origin)

    return fx_xform, fy_xform, phase_xform
Exemple #6
0
    def test_kmat(self):
        """
        Test that the real-space and Fourier-space pattern generation models agree.

        i.e. that D_i(x) = amp * (1 + m * cos(2*pi*f + phi_i)) * S(r)
        matches the result given using the fourier space matrix
        [[D_1(k)], [D_2(k)], [D_3(k)]] = M * [[S(k)], [S(k-p)], [S(k+p)]]

        :return:
        """

        # set options
        dx = 0.065
        sim_options = {'pixel_size': 0.065, 'wavelength': 0.5, 'na': 1.3}

        # set values for SIM images
        frqs = np.array([[3.5785512, 2.59801082]])
        phases = np.array([[0, 2 * np.pi / 3, 3 * np.pi / 3]])
        mods = np.array([[0.85, 0.26, 0.19]])
        amps = np.array([[1.11, 1.23, 0.87]])

        nangles, nphases = phases.shape

        # ground truth image
        ny = 512
        nx = ny
        gt = np.random.rand(ny, nx)

        # calculate sim patterns using real space method
        x = tools.get_fft_pos(nx, dx)
        y = tools.get_fft_pos(ny, dx)
        xx, yy = np.meshgrid(x, y)

        sim_rs = np.zeros((nangles, nphases, ny, nx))
        sim_rs_ft = np.zeros((nangles, nphases, ny, nx), dtype=np.complex)
        for ii in range(nangles):
            for jj in range(nphases):
                pattern = amps[ii, jj] * (1 + mods[ii, jj] * np.cos(
                    2 * np.pi *
                    (xx * frqs[ii, 0] + yy * frqs[ii, 1]) + phases[ii, jj]))
                sim_rs[ii, jj] = gt * pattern
                sim_rs_ft[ii, jj] = fft.fftshift(
                    fft.fft2(fft.ifftshift(sim_rs[ii, jj])))

        # calculate SIM patterns using Fourier space method
        # frq shifted gt images
        gt_ft_shifted = np.zeros((nangles, nphases, ny, nx), dtype=np.complex)
        for ii in range(nangles):
            gt_ft_shifted[ii, 0] = fft.fftshift(fft.fft2(fft.ifftshift(gt)))
            gt_ft_shifted[ii, 1] = tools.translate_ft(gt_ft_shifted[ii, 0],
                                                      -frqs[ii], dx)
            gt_ft_shifted[ii, 2] = tools.translate_ft(gt_ft_shifted[ii, 0],
                                                      frqs[ii], dx)

        sim_fs_ft = np.zeros(gt_ft_shifted.shape, dtype=np.complex)
        for ii in range(nangles):
            kmat = sim.get_band_mixing_matrix(phases[ii], mods[ii], amps[ii])
            sim_fs_ft[ii] = sim.image_times_matrix(gt_ft_shifted[ii], kmat)

        sim_fs_rs = np.zeros(gt_ft_shifted.shape)
        for ii in range(nangles):
            for jj in range(nphases):
                sim_fs_rs[ii, jj] = fft.fftshift(
                    fft.ifft2(fft.ifftshift(sim_fs_ft[ii, jj]))).real

        # fx = tools.get_fft_frqs(nx, dx)
        # dfx = fx[1] - fx[0]
        # fy = tools.get_fft_frqs(ny, dx)
        # extent = sim.get_extent(fy, fx)
        #
        # fig, fig_ax = plt.subplots(ncols=2, nrows=2, constrained_layout=True)
        # ii = 0
        # jj = 1
        #
        # fig_ax[0][0].imshow(np.abs(sim_rs_ft[ii, jj])**2, norm=PowerNorm(gamma=0.1), extent=extent)
        # plt.title('calculated in real space')
        #
        # fig_ax[0][1].imshow(np.abs(sim_fs_ft[ii, jj])**2, norm=PowerNorm(gamma=0.1), extent=extent)
        # plt.title('calculated in fourier space')
        #
        # fig_ax[1][0].imshow(sim_rs[ii, jj])
        # plt.title('real space')
        #
        # fig_ax[1][1].imshow(sim_fs_rs[ii, jj])
        # plt.title('real space (calculated in Fourier space)')

        np.testing.assert_allclose(sim_fs_ft, sim_rs_ft, atol=1e-10)
        np.testing.assert_allclose(sim_fs_rs, sim_rs, atol=1e-12)