示例#1
0
def propagate_1D_fresnel_radius(wavefront, propagation_distance, eta):
    """
    1D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance
    :return: a new 1D wavefront object with propagated wavefront
    """
    fft_scale = numpy.fft.fftfreq(wavefront.size()) / wavefront.delta()

    fft = numpy.fft.fft(wavefront.get_complex_amplitude())
    fft *= numpy.exp(1.0j * numpy.pi * wavefront.get_wavelength() *
                     propagation_distance *
                     (-fft_scale**2 + eta * fft_scale**2))
    H = numpy.fft.ifft(fft)
    H *= -1.0j * eta * propagation_distance / wavefront.get_wavelength(
    ) * numpy.exp(1.0j * numpy.pi / eta / propagation_distance /
                  wavefront.get_wavelength() * wavefront.get_abscissas()**2)
    ifft = numpy.fft.fft(H)
    ifft *= numpy.exp(1.0j * numpy.pi / eta / propagation_distance /
                      wavefront.get_wavelength() *
                      wavefront.get_abscissas()**2)

    return Wavefront1D(
        wavefront.get_wavelength(),
        ScaledArray.initialize_from_steps(ifft, wavefront.offset(),
                                          wavefront.delta()))
示例#2
0
def propagator1d_fourier_rescaling(wavefront, propagation_distance, m=1):

    wf = wavefront.duplicate()  # todo: cambiato da giovanni, controllare
    shape = wf.size()
    delta = wf.delta()
    wavenumber = wf.get_wavenumber()
    wavelength = wf.get_wavelength()

    fft_scale = numpy.fft.fftfreq(shape, d=delta)

    x = wf.get_abscissas()

    x_rescaling = wf.get_abscissas() * m

    r1sq = x**2 * (1 - m)
    r2sq = x_rescaling**2 * ((m - 1) / m)
    fsq = (fft_scale**2 / m)

    Q1 = wavenumber / 2 / propagation_distance * r1sq
    Q2 = numpy.exp(-1.0j * numpy.pi * wavelength * propagation_distance * fsq)
    Q3 = numpy.exp(1.0j * wavenumber / 2 / propagation_distance * r2sq)

    wf.add_phase_shift(Q1)

    fft = numpy.fft.fft(wf.get_complex_amplitude())

    ifft = numpy.fft.ifft(fft * Q2) * Q3 / numpy.sqrt(m)

    return Wavefront1D(
        wf.get_wavelength(),
        ScaledArray.initialize_from_steps(ifft, m * wf.offset(),
                                          m * wf.delta()))
示例#3
0
def propagate_1D_integral(wavefront,
                          propagation_distance,
                          detector_abscissas=[None],
                          method=0,
                          magnification=1.0,
                          npoints_exit=None):
    """
    1D Fresnel-Kirchhoff propagator via integral implemented as sum
    :param wavefront:
    :param propagation_distance: propagation distance
    :param detector_abscissas: a numpy array with the abscissas at the image position. If undefined ([None])
                            it uses the same abscissas present in input wavefront.
    :param method: 0 (default_ makes a loop over detector coordinates, 1: makes matrices (outer products) so
                            it is more memory hungry.
    :param magnification: if detector_abscissas is [None], the detector abscissas range is the input
                            wavefront range times this magnification factor. Default =1
    :param npoints_exit: if detector_abscissas is [None], the number of points of detector abscissas.
                            Default=None meaning that the same number of points than wavefront are used.
    :return: a new 1D wavefront object with propagated wavefront
    """

    if detector_abscissas[0] == None:

        x = wavefront.get_abscissas()
        if npoints_exit is None:
            npoints_exit = x.size
        detector_abscissas = numpy.linspace(magnification * x[0],
                                            magnification * x[-1],
                                            npoints_exit)

    wavenumber = numpy.pi * 2 / wavefront.get_wavelength()
    if method == 0:
        x1 = wavefront.get_abscissas()
        x2 = detector_abscissas
        fieldComplexAmplitude = numpy.zeros_like(x2, dtype=complex)
        for ix, x in enumerate(x2):
            r = numpy.sqrt(
                numpy.power(x1 - x, 2) + numpy.power(propagation_distance, 2))
            distances_array = numpy.exp(1.j * wavenumber * r)
            fieldComplexAmplitude[ix] = (wavefront.get_complex_amplitude() *
                                         distances_array).sum()
    elif method == 1:
        # calculate via outer product, it spreads over a lot of memory, but it is OK for 1D
        x1 = numpy.outer(wavefront.get_abscissas(),
                         numpy.ones(detector_abscissas.size))
        x2 = numpy.outer(numpy.ones(wavefront.size()), detector_abscissas)
        r = numpy.sqrt(
            numpy.power(x1 - x2, 2) + numpy.power(propagation_distance, 2))
        distances_matrix = numpy.exp(1.j * wavenumber * r)
        fieldComplexAmplitude = numpy.dot(wavefront.get_complex_amplitude(),
                                          distances_matrix)

    return Wavefront1D(wavefront.get_wavelength(), ScaledArray.initialize_from_steps(fieldComplexAmplitude, \
                            detector_abscissas[0], detector_abscissas[1]-detector_abscissas[0] ))
示例#4
0
def propagate_1D_fresnel_convolution(wavefront, propagation_distance):
    """
    1D Fresnel propagator using direct convolution
    :param wavefront:
    :param propagation_distance:
    :return:
    """

    # instead of numpy.convolve, this can be used:
    # from scipy.signal import fftconvolve

    kernel = numpy.exp(1j * 2 * numpy.pi / wavefront.get_wavelength() *
                       wavefront.get_abscissas()**2 / 2 / propagation_distance)
    kernel *= numpy.exp(1j * 2 * numpy.pi / wavefront.get_wavelength() *
                        propagation_distance)
    kernel /= 1j * wavefront.get_wavelength() * propagation_distance
    tmp = numpy.convolve(wavefront.get_complex_amplitude(),
                         kernel,
                         mode='same')

    return Wavefront1D(
        wavefront.get_wavelength(),
        ScaledArray.initialize_from_steps(tmp, wavefront.offset(),
                                          wavefront.delta()))