Esempio n. 1
0
def linearpolarizer(field, rotation=0):
    """
    Definition that represents a linear polarizer.

    Parameters
    ----------
    field        : ndarray
                   Polarization vector of an input beam.
    rotation     : float
                   Represents rotation of the polarizer along propagation direction in angles (couter-clockwise).

    Returns
    ----------
    result       : ndarray
                   Polarization vector of an output beam.
    """
    rotation = np.radians(rotation)
    rotmat = np.array([[float(np.cos(rotation)),
                        float(np.sin(rotation))],
                       [float(-np.sin(rotation)),
                        float(np.cos(rotation))]])
    linearpolarizer = np.array([[1, 0], [0, 0]])
    linearpolarizer = np.dot(rotmat.transpose(),
                             np.dot(linearpolarizer, rotmat))
    result = np.dot(linearpolarizer, field)
    return result
Esempio n. 2
0
def sphere_sample(no=[10, 10], radius=1., center=[0., 0., 0.], k=[1, 2]):
    """
    Definition to generate a regular sample set on the surface of a sphere using polar coordinates.

    Parameters
    ----------
    no          : list
                  Number of samples.
    radius      : float
                  Radius of a sphere.
    center      : list
                  Center of a sphere.
    k           : list
                  Multipliers for gathering samples. If you set k=[1,2] it will draw samples from a perfect sphere.

    Returns
    ----------
    samples     : ndarray
                  Samples generated.
    """
    samples = np.zeros((no[0], no[1], 3))
    psi, teta = np.mgrid[0:no[0], 0:no[1]]
    psi = k[0] * np.pi / no[0] * psi
    teta = k[1] * np.pi / no[1] * teta
    samples[:, :, 0] = center[0] + radius * np.sin(psi) * np.cos(teta)
    samples[:, :, 1] = center[0] + radius * np.sin(psi) * np.sin(teta)
    samples[:, :, 2] = center[0] + radius * np.cos(psi)
    samples = samples.reshape((no[0] * no[1], 3))
    return samples
Esempio n. 3
0
def create_ray(x0y0z0, abg):
    """
    Definition to create a ray.

    Parameters
    ----------
    x0y0z0       : list
                   List that contains X,Y and Z start locations of a ray.
    abg          : list
                   List that contaings angles in degrees with respect to the X,Y and Z axes.

    Returns
    ----------
    ray          : ndarray
                   Array that contains starting points and cosines of a created ray.
    """
    # Due to Python 2 -> Python 3.
    x0, y0, z0 = x0y0z0
    alpha, beta, gamma = abg
    # Create a vector with the given points and angles in each direction
    point = np.array([x0, y0, z0], dtype=np.float)
    alpha = np.cos(np.radians(alpha))
    beta = np.cos(np.radians(beta))
    gamma = np.cos(np.radians(gamma))
    # Cosines vector.
    cosines = np.array([alpha, beta, gamma], dtype=np.float)
    ray = np.array([point, cosines], dtype=np.float)
    return ray
Esempio n. 4
0
def circular_uniform_sample(no=[10, 50],
                            radius=10.,
                            center=[0., 0., 0.],
                            angles=[0., 0., 0.]):
    """
    Definition to generate sample inside a circle uniformly.

    Parameters
    ----------
    no          : list
                  Number of samples.
    radius      : float
                  Radius of the circle.
    center      : list
                  Center location of the surface.
    angles      : list
                  Tilt of the surface.

    Returns
    ----------
    samples     : ndarray
                  Samples generated.
    """
    samples = np.empty((0, 3))
    for i in range(0, no[0]):
        r = i / no[0] * radius
        ang_no = no[1] * i / no[0]
        for j in range(0, int(no[1] * i / no[0])):
            angle = j / ang_no * 2 * np.pi
            point = np.array(
                [float(r * np.cos(angle)),
                 float(r * np.sin(angle)), 0])
            samples = np.vstack((samples, point))
    samples = rotate_points(samples, angles=angles, offset=center)
    return samples
Esempio n. 5
0
def circular_uniform_random_sample(no=[10, 50],
                                   radius=10.,
                                   center=[0., 0., 0.],
                                   angles=[0., 0., 0.]):
    """ 
    Definition to generate sample inside a circle uniformly but randomly.

    Parameters
    ----------
    no          : list
                  Number of samples.
    radius      : float
                  Radius of the circle.
    center      : list
                  Center location of the surface.
    angles      : list
                  Tilt of the surface.

    Returns
    ----------
    samples     : ndarray
                  Samples generated.
    """
    samples = np.empty((0, 3))
    rs = np.sqrt(np.random.uniform(0, 1, no[0]))
    angs = np.random.uniform(0, 2 * np.pi, no[1])
    for i in rs:
        for angle in angs:
            r = radius * i
            point = np.array(
                [float(r * np.cos(angle)),
                 float(r * np.sin(angle)), 0])
            samples = np.vstack((samples, point))
    samples = rotate_points(samples, angles=angles, offset=center)
    return samples
Esempio n. 6
0
def circular_sample(no=[10, 10],
                    radius=10.,
                    center=[0., 0., 0.],
                    angles=[0., 0., 0.]):
    """
    Definition to generate samples inside a circle over a surface.

    Parameters
    ----------
    no          : list
                  Number of samples.
    radius      : float
                  Radius of the circle.
    center      : list
                  Center location of the surface.
    angles      : list
                  Tilt of the surface.

    Returns
    ----------
    samples     : ndarray
                  Samples generated.
    """
    samples = np.zeros((no[0] + 1, no[1] + 1, 3))
    r_angles, r = np.mgrid[0:no[0] + 1, 0:no[1] + 1]
    r = r / np.amax(r) * radius
    r_angles = r_angles / np.amax(r_angles) * np.pi * 2
    samples[:, :, 0] = r * np.cos(r_angles)
    samples[:, :, 1] = r * np.sin(r_angles)
    samples = samples[1:no[0] + 1, 1:no[1] + 1, :]
    samples = samples.reshape(
        (samples.shape[0] * samples.shape[1], samples.shape[2]))
    samples = rotate_points(samples, angles=angles, offset=center)
    return samples
Esempio n. 7
0
def main():
    # Variables to be set.
    wavelength = 0.5 * pow(10, -6)
    pixeltom = 6 * pow(10, -6)
    distance = 0.2
    propagation_type = 'IR Fresnel'
    k = wavenumber(wavelength)
    sample_field = np.zeros((500, 500), dtype=np.complex64)
    sample_field[240:260, 240:260] = 1000
    random_phase = np.pi * np.random.random(sample_field.shape)
    sample_field = sample_field * np.cos(
        random_phase) + 1j * sample_field * np.sin(random_phase)
    sample_field = torch.from_numpy(sample_field)
    hologram = propagate_beam_torch(sample_field, k, distance, pixeltom,
                                    wavelength, propagation_type)
    reconstruction = propagate_beam_torch(hologram, k, -distance, pixeltom,
                                          wavelength, propagation_type)
    # from odak.visualize.plotly import detectorshow
    # detector       = detectorshow()
    # detector.add_field(sample_field)
    # detector.show()
    # detector.add_field(hologram)
    # detector.show()
    # detector.add_field(reconstruction)
    # detector.show()
    assert True == True
Esempio n. 8
0
def compare():
    wavelength = 0.5 * pow(10, -6)
    pixeltom = 6 * pow(10, -6)
    distance = 0.2
    propagation_type = 'IR Fresnel'
    k = wavenumber(wavelength)
    sample_field = np.zeros((500, 500), dtype=np.complex64)
    sample_field[240:260, 240:260] = 1000
    random_phase = np.pi * np.random.random(sample_field.shape)
    sample_field = sample_field * np.cos(
        random_phase) + 1j * sample_field * np.sin(random_phase)

    sample_field_torch = torch.from_numpy(sample_field)

    ## Propagate and reconstruct using torch.
    hologram_torch = propagate_beam_torch(sample_field_torch, k, distance,
                                          pixeltom, wavelength,
                                          propagation_type)
    reconstruction_torch = propagate_beam_torch(hologram_torch, k, -distance,
                                                pixeltom, wavelength,
                                                propagation_type)

    ## Propagate and reconstruct using np.
    hologram = propagate_beam(sample_field, k, distance, pixeltom, wavelength,
                              propagation_type)
    reconstruction = propagate_beam(hologram, k, -distance, pixeltom,
                                    wavelength, propagation_type)

    np.testing.assert_array_almost_equal(hologram_torch.numpy(), hologram, 3)
Esempio n. 9
0
def produce_phase_only_slm_pattern(hologram,slm_range):
    """
    Definition for producing a pattern for a phase only Spatial Light Modulator (SLM) using a given field.

    Parameters
    ==========
    hologram           : torch.cfloat
                         Input holographic field.
    slm_range          : float
                         Range of the phase only SLM in radians for a working wavelength (i.e. two pi). See odak.wave.adjust_phase_only_slm_range() for more.
    filename           : str
                         Optional variable, if provided the patterns will be save to given location.

    Returns
    ==========
    pattern            : torch.cfloat
                         Adjusted phase only pattern.
    """
    hologram_phase                            = calculate_phase(hologram) % (2*np.pi)
    hologram_phase[hologram_phase>slm_range]  = slm_range
    hologram_phase                           /= slm_range
    hologram_phase                           *= 255
    hologram_phase                            = hologram_phase.int()
    hologram_phase                            = hologram_phase.float()
    hologram_phase                           *= slm_range/255.
    return np.cos(hologram_phase)+1j*np.sin(hologram_phase)
Esempio n. 10
0
def main():
    # Variables to be set.
    wavelength                 = 0.5*pow(10,-6)
    pixeltom                   = 6*pow(10,-6)
    distance                   = 0.2
    propagation_type           = 'Bandlimited Angular Spectrum'
    k                          = wavenumber(wavelength)
    sample_field               = np.zeros((500,500),dtype=np.complex64)
    sample_field[
                 240:260,
                 240:260
                ]              = 1000
    random_phase               = np.pi*np.random.random(sample_field.shape)
    sample_field               = sample_field*np.cos(random_phase)+1j*sample_field*np.sin(random_phase)
    criterion = torch.nn.MSELoss()

    if np.__name__ == 'cupy':
        sample_field = np.asnumpy(sample_field)

    sample_field               = torch.from_numpy(sample_field)

    hologram                   = propagate_beam_torch(
                                                sample_field,
                                                k,
                                                distance,
                                                pixeltom,
                                                wavelength,
                                                propagation_type
                                               )
    hologram.requires_grad = True
    reconstruction             = propagate_beam_torch(
                                                hologram,
                                                k,
                                                -distance,
                                                pixeltom,
                                                wavelength,
                                                propagation_type
                                               )
    loss = criterion(torch.abs(sample_field), torch.abs(reconstruction))
    loss.backward()
    print(hologram.grad)
    print('backward successfully')

    #from odak.visualize.plotly import detectorshow
    #detector       = detectorshow()
    #detector.add_field(sample_field)
    #detector.show()
    #detector.add_field(hologram)
    #detector.show()
    #detector.add_field(reconstruction)
    #detector.show()
    assert True==True
Esempio n. 11
0
def set_amplitude(field, amplitude):
    """
    Definition to keep phase as is and change the amplitude of a given field.
    Parameters
    ----------
    field        : np.complex64
                   Complex field.
    amplitude    : np.array or np.complex64
                   Amplitudes.
    Returns
    ----------
    new_field    : np.complex64
                   Complex field.
    """
    amplitude = calculate_amplitude(amplitude)
    phase = calculate_phase(field)
    new_field = amplitude * np.cos(phase) + 1j * amplitude * np.sin(phase)
    return new_field
Esempio n. 12
0
def rayleigh_sommerfeld(field,k,distance,dx,wavelength):
    """
    Definition to compute beam propagation using Rayleigh-Sommerfeld's diffraction formula (Huygens-Fresnel Principle). For more see Section 3.5.2 in Goodman, Joseph W. Introduction to Fourier optics. Roberts and Company Publishers, 2005.

    Parameters
    ----------
    field            : np.complex
                       Complex field (MxN).
    k                : odak.wave.wavenumber
                       Wave number of a wave, see odak.wave.wavenumber for more.
    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
    =======
    result           : np.complex
                       Final complex field (MxN).
    """
    nv,nu     = field.shape
    x         = np.linspace(-nv*dx/2,nv*dx/2,nv)
    y         = np.linspace(-nu*dx/2,nu*dx/2,nu)
    X,Y       = np.meshgrid(x,y)
    Z         = X**2+Y**2
    result    = np.zeros(field.shape,dtype=np.complex64)
    direction = int(distance/np.abs(distance))
    for i in range(nu):
        for j in range(nv):
            if field[i,j] != 0:
                r01      = np.sqrt(distance**2+(X-X[i,j])**2+(Y-Y[i,j])**2)*direction
                cosnr01  = np.cos(distance/r01)
                result  += field[i,j]*np.exp(1j*k*r01)/r01*cosnr01
    result *= 1./(1j*wavelength)
    return result