Пример #1
0
def nufft2(field, fx, fy, size=None, sign=1, eps=10**(-12)):
    """
    """
    if np.__name__ == 'cupy':
        fx = np.asnumpy(fx).astype(np.float64)
        fy = np.asnumpy(fy).astype(np.float64)
        image = np.asnumpy(np.copy(field)).astype(np.complex128)
    else:
        image = np.copy(field).astype(np.complex128)
    if type(size) == type(None):
        result = finufft.nufft2d1(fx.flatten(),
                                  fy.flatten(),
                                  image.flatten(),
                                  image.shape,
                                  eps=eps,
                                  isign=sign)
    else:
        result = finufft.nufft2d1(fx.flatten(),
                                  fy.flatten(),
                                  image.flatten(), (size[0], size[1]),
                                  eps=eps,
                                  isign=sign)

    if np.__name__ == 'cupy':
        result = np.asarray(result)
    return result
Пример #2
0
def crop_center(field, size=None):
    """
    Definition to crop the center of a field with 2Mx2N size. The outcome is a MxN array.

    Parameters
    ----------
    field       : ndarray
                  Input field 2Mx2N array.

    Returns
    ----------
    cropped     : ndarray
                  Cropped version of the input field.
    """
    if type(size) == type(None):
        qx = int(np.ceil(field.shape[0]) / 4)
        qy = int(np.ceil(field.shape[1]) / 4)
        cropped = np.copy(field[qx:3 * qx, qy:3 * qy])
    else:
        cx = int(np.ceil(field.shape[0] / 2))
        cy = int(np.ceil(field.shape[1] / 2))
        hx = int(np.ceil(size[0] / 2))
        hy = int(np.ceil(size[1] / 2))
        cropped = np.copy(field[cx - hx:cx + hx, cy - hy:cy + hy])
    return cropped
Пример #3
0
    def draw_a_ray(self, point0, point1, k=0.02, color=[255, 255, 255]):
        """
        Definition to draw a ray.

        Parameters
        ----------
        point0      : list
                      List that contains X, Y, and Z start locations of a ray.
        point1      : list
                      List that contains X, Y, and Z end locations of a ray.
        k           : float
                      Thickness of a ray.
        color       : list
                      List that contains red, green and blue color channel values (8 bit).
        """
        import numpy as np_cpu
        point0 = np_cpu.reshape(np_cpu.array(point0), (3))
        point1 = np_cpu.reshape(np_cpu.array(point1), (3))
        if type(self.pnts) == type(None):
            a = 0
        elif type(self.pnts) != type(None):
            a = np_cpu.asarray(self.pnts).shape[0]
        pnts = np_cpu.array([(point0[0], point0[1], point0[2]),
                             (point0[0] + k, point0[1], point0[2]),
                             (point0[0] + k, point0[1] + k, point0[2]),
                             (point0[0], point0[1] + k, point0[2]),
                             (point1[0], point1[1], point1[2]),
                             (point1[0] + k, point1[1], point1[2]),
                             (point1[0] + k, point1[1] + k, point1[2]),
                             (point1[0], point1[1] + k, point1[2])],
                            dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])
        tris = np_cpu.array(
            [([0 + a, 3 + a, 1 + a], color[0], color[1], color[2]),
             ([1 + a, 3 + a, 2 + a], color[0], color[1], color[2]),
             ([0 + a, 4 + a, 7 + a], color[0], color[1], color[2]),
             ([0 + a, 7 + a, 3 + a], color[0], color[1], color[2]),
             ([4 + a, 5 + a, 6 + a], color[0], color[1], color[2]),
             ([4 + a, 6 + a, 7 + a], color[0], color[1], color[2]),
             ([5 + a, 1 + a, 2 + a], color[0], color[1], color[2]),
             ([5 + a, 2 + a, 6 + a], color[0], color[1], color[2]),
             ([2 + a, 3 + a, 6 + a], color[0], color[1], color[2]),
             ([3 + a, 7 + a, 6 + a], color[0], color[1], color[2]),
             ([0 + a, 1 + a, 5 + a], color[0], color[1], color[2]),
             ([0 + a, 5 + a, 4 + a], color[0], color[1], color[2])],
            dtype=[('vertex_indices', 'i4', (3, )), ('red', 'u1'),
                   ('green', 'u1'), ('blue', 'u1')])
        if type(self.pnts) != type(None):
            self.tris = np_cpu.concatenate([np.copy(self.tris), np.copy(tris)])
            self.pnts = np_cpu.concatenate([np.copy(self.pnts), np.copy(pnts)])
        else:
            self.tris = np_cpu.copy(tris)
            self.pnts = np_cpu.copy(pnts)
Пример #4
0
def propagate_a_ray(ray, distance):
    """
    Definition to propagate a ray at a certain given distance.

    Parameters
    ----------
    ray        : ndarray
                 A ray.
    distance   : float
                 Distance.

    Returns
    ----------
    new_ray    : ndarray
                 Propagated ray.
    """
    if len(ray.shape) == 2:
        ray = ray.reshape((1, 2, 3))
    new_ray = np.copy(ray)
    new_ray[:, 0, 0] = distance * new_ray[:, 1, 0] + new_ray[:, 0, 0]
    new_ray[:, 0, 1] = distance * new_ray[:, 1, 1] + new_ray[:, 0, 1]
    new_ray[:, 0, 2] = distance * new_ray[:, 1, 2] + new_ray[:, 0, 2]
    if new_ray.shape[0] == 1:
        new_ray = new_ray.reshape((2, 3))
    return new_ray
Пример #5
0
def gerchberg_saxton(field,n_iterations,distance,dx,wavelength,slm_range=6.28,propagation_type='IR Fresnel'):
    """
    Definition to compute a hologram using an iterative method called Gerchberg-Saxton phase retrieval algorithm. For more on the method, see: Gerchberg, Ralph W. "A practical algorithm for the determination of phase from image and diffraction plane pictures." Optik 35 (1972): 237-246.

    Parameters
    ----------
    field            : np.complex
                       Complex field (MxN).
    distance         : float
                       Propagation distance.
    dx               : float
                       Size of one single pixel in the field grid (in meters).
    wavelength       : float
                       Wavelength of the electric field.
    slm_range        : float
                       Typically this is equal to two pi. See odak.wave.adjust_phase_only_slm_range() for more.
    propagation_type : str
                       Type of the propagation (IR Fresnel, TR Fresnel, Fraunhofer).

    Result
    ---------
    hologram         : np.complex
                       Calculated complex hologram.
    reconstruction   : np.complex
                       Calculated reconstruction using calculated hologram. 
    """
    k              = wavenumber(wavelength)
    reconstruction = np.copy(field)
    for i in tqdm(range(n_iterations)):
        hologram       = propagate_beam(reconstruction,k,-distance,dx,wavelength,propagation_type)
        hologram       = produce_phase_only_slm_pattern(hologram,slm_range)
        reconstruction = propagate_beam(hologram,k,distance,dx,wavelength,propagation_type)
        reconstruction = set_amplitude(hologram,field)
    reconstruction = propagate_beam(hologram,k,distance,dx,wavelength,propagation_type)
    return hologram,reconstruction
Пример #6
0
def fraunhofer_equal_size_adjust(field,distance,dx,wavelength):
    """
    A definition to match the physical size of the original field with the propagated field.

    Parameters
    ----------
    field            : np.complex
                       Complex field (MxN).
    distance         : float
                       Propagation distance.
    dx               : float
                       Size of one single pixel in the field grid (in meters).
    wavelength       : float
                       Wavelength of the electric field.

    Returns
    =======
    new_field        : np.complex
                       Final complex field (MxN).
    """
    nv,nu     = field.shape
    l1        = nu*dx
    l2        = wavelength*distance/dx
    m         = l1/l2
    px        = int(m*nu)
    py        = int(m*nv)
    nx        = int(field.shape[0]/2-px/2)
    ny        = int(field.shape[1]/2-py/2)
    new_field = np.copy(field[nx:nx+px,ny:ny+py])
    return new_field
Пример #7
0
def nuifft2(field, fx, fy, size=None, sign=1, eps=10**(-12)):
    """
    A definition to take 2D Adjoint Non-Uniform Fast Fourier Transform (NUFFT).

    Parameters
    ----------
    field       : ndarray
                  Input field.
    fx          : ndarray
                  Frequencies along x axis.
    fy          : ndarray
                  Frequencies along y axis.
    size        : list or ndarray
                  Shape of the NUFFT calculated for an input field.
    sign        : float
                  Sign of the exponential used in NUFFT kernel.
    eps         : float
                  Accuracy of NUFFT.

    Returns
    ----------
    result      : ndarray
                  NUFFT of the input field.
    """
    if np.__name__ == 'cupy':
        fx = np.asnumpy(fx).astype(np.float64)
        fy = np.asnumpy(fy).astype(np.float64)
        image = np.asnumpy(np.copy(field)).astype(np.complex128)
    else:
        image = np.copy(field).astype(np.complex128)
    if type(size) == type(None):
        result = finufft.nufft2d1(fx.flatten(),
                                  fy.flatten(),
                                  image.flatten(),
                                  image.shape,
                                  eps=eps,
                                  isign=sign)
    else:
        result = finufft.nufft2d1(fx.flatten(),
                                  fy.flatten(),
                                  image.flatten(), (size[0], size[1]),
                                  eps=eps,
                                  isign=sign)
    if np.__name__ == 'cupy':
        result = np.asarray(result)
    return result
Пример #8
0
def nuifft2(field, fx, fy, sign=1, eps=10**(-12)):
    """
    """
    if np.__name__ == 'cupy':
        fx = np.asnumpy(fx).astype(np.float64)
        fy = np.asnumpy(fy).astype(np.float64)
        image = np.asnumpy(np.copy(field)).astype(np.complex128)
    else:
        image = np.copy(field).astype(np.complex128)
    result = finufft.nufft2d2(fx.flatten(),
                              fy.flatten(),
                              image,
                              eps=eps,
                              isign=sign)
    result = result.reshape(field.shape)
    if np.__name__ == 'cupy':
        result = np.asarray(result)
    return result
Пример #9
0
    def get_field(self):
        """
        A definition to return the field measured on the detector.

        Returns
        ----------
        field       : ndarray
                      A copy of the field measured by the detector.
        """
        return np.copy(self.field)
Пример #10
0
def save_image(fn, img, cmin=0, cmax=255):
    """
    Definition to save a Numpy array as an image.

    Parameters
    ----------
    fn           : str
                   Filename.
    img          : ndarray
                   A numpy array with NxMx3 or NxMx1 shapes.
    cmin         : int
                   Minimum value that will be interpreted as 0 level in the final image.
    cmax         : int
                   Maximum value that will be interpreted as 255 level in the final image.

    Returns
    ----------
    bool         :  bool
                    True if successful.

    """
    input_img = np.copy(img).astype(np.float)
    colorflag = False
    if len(input_img.shape) == 3:
        if input_img.shape[2] > 1:
            input_img = input_img[:, :, 0:3]
            colorflag = True
    input_img[input_img < cmin] = cmin
    input_img[input_img > cmax] = cmax
    input_img /= cmax
    input_img *= 255
    input_img = input_img.astype(np.uint8)
    if np.__name__ == 'cupy':
        input_img = np.asnumpy(input_img)
    if colorflag == True:
        result_img = Image.fromarray(input_img)
    elif colorflag == False:
        result_img = Image.fromarray(input_img).convert("L")
    result_img.save(fn)
    return True