Exemplo n.º 1
0
def propagate_2D_fresnel_convolution(wavefront, propagation_distance,shift_half_pixel=1):
    """
    2D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance
    :param shift_half_pixel: set to 1 to shift half pixel (recommended using an even number of pixels) Set as default.
    :return: a new 2D wavefront object with propagated wavefront
    """

    from scipy.signal import fftconvolve

    wavelength = wavefront.get_wavelength()

    X = wavefront.get_mesh_x()
    Y = wavefront.get_mesh_y()

    if shift_half_pixel:
        x = wavefront.get_coordinate_x()
        y = wavefront.get_coordinate_y()
        X += 0.5 * numpy.abs( x[0] - x[1] )
        Y += 0.5 * numpy.abs( y[0] - y[1] )

    kernel = numpy.exp(1j*2*numpy.pi/wavefront.get_wavelength() *
                       (X**2 + Y**2) / 2 / propagation_distance)
    kernel *= numpy.exp(1j*2*numpy.pi/wavefront.get_wavelength() * propagation_distance)
    kernel /=  1j * wavefront.get_wavelength() * propagation_distance
    tmp = fftconvolve(wavefront.get_complex_amplitude(),kernel,mode='same')

    wf_propagated = Wavefront2D.initialize_wavefront_from_arrays(wavefront.get_coordinate_x(),
                                                                 wavefront.get_coordinate_y(),
                                                                 tmp,
                                                                 wavelength=wavelength)
    return wf_propagated
Exemplo n.º 2
0
    def test_polarization_interpolation(self):

        print("#                                                             ")
        print("# Tests polarization with interpolation                       ")
        print("#                                                             ")
        #
        # from arrays
        #
        x = numpy.linspace(-100, 100, 50)
        y = numpy.linspace(-50, 50, 200)
        X = numpy.outer(x, numpy.ones_like(y))
        Y = numpy.outer(numpy.ones_like(x), y)
        sigma = 10
        Z = numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) * 1j
        Zp = 0.3333 * numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) * 1j
        wf2 = Wavefront2D.initialize_wavefront_from_arrays(x, y, Z, Zp)

        ca1 = wf2.get_complex_amplitude(polarization=Polarization.SIGMA)
        ca2 = wf2.get_interpolated_complex_amplitude(
            X + 1e-3, Y + 1e-4, polarization=Polarization.SIGMA)
        assert_array_almost_equal(ca1, ca2, 4)

        ca1pi = wf2.get_complex_amplitude(polarization=Polarization.PI)
        ca2pi = wf2.get_interpolated_complex_amplitude(
            X + 1e-3, Y + 1e-4, polarization=Polarization.PI)
        assert_array_almost_equal(ca1pi, ca2pi, 4)
Exemplo n.º 3
0
def propagate_2D_fraunhofer(wavefront, propagation_distance=1.0,shift_half_pixel=1):
    """
    2D Fraunhofer propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance. If set to zero, the abscissas
                                 of the returned wavefront are in angle (rad)
    :param shift_half_pixel: set to 1 to shift half pixel (recommended using an even number of pixels) Set as default.
    :return: a new 2D wavefront object with propagated wavefront
    """
    wavelength = wavefront.get_wavelength()

    #
    # check validity
    #
    x =  wavefront.get_coordinate_x()
    y =  wavefront.get_coordinate_y()
    half_max_aperture = 0.5 * numpy.array( (x[-1]-x[0],y[-1]-y[0])).max()
    far_field_distance = half_max_aperture**2/wavelength
    if propagation_distance < far_field_distance:
        print("WARNING: Fraunhoffer diffraction valid for distances > > half_max_aperture^2/lambda = %f m (propagating at %4.1f)"%
                    (far_field_distance,propagation_distance))
    #
    #compute Fourier transform
    #
    F1 = numpy.fft.fft2(wavefront.get_complex_amplitude())  # Take the fourier transform of the image.
    # Now shift the quadrants around so that low spatial frequencies are in
    # the center of the 2D fourier transformed image.
    F2 = numpy.fft.fftshift( F1 )

    # frequency for axis 1
    shape = wavefront.size()
    delta = wavefront.delta()

    pixelsize = delta[0] # p_x[1] - p_x[0]
    npixels = shape[0]
    freq_nyquist = 0.5/pixelsize
    freq_n = numpy.linspace(-1.0,1.0,npixels)
    freq_x = freq_n * freq_nyquist
    freq_x *= wavelength

    # frequency for axis 2
    pixelsize = delta[1]
    npixels = shape[1]
    freq_nyquist = 0.5/pixelsize
    freq_n = numpy.linspace(-1.0,1.0,npixels)
    freq_y = freq_n * freq_nyquist
    freq_y *= wavelength


    if shift_half_pixel:
        freq_x = freq_x - 0.5 * numpy.abs(freq_x[1] - freq_x[0])
        freq_y = freq_y - 0.5 * numpy.abs(freq_y[1] - freq_y[0])

    if propagation_distance != 1.0:
        freq_x *= propagation_distance
        freq_y *= propagation_distance

    wf_propagated = Wavefront2D.initialize_wavefront_from_arrays(freq_x,freq_y,F2,wavelength=wavelength)
    return  wf_propagated
Exemplo n.º 4
0
def propagate_2D_fresnel_convolution(wavefront,
                                     propagation_distance,
                                     shift_half_pixel=1):
    """
    2D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance
    :param shift_half_pixel: set to 1 to shift half pixel (recommended using an even number of pixels) Set as default.
    :return: a new 2D wavefront object with propagated wavefront
    """

    from scipy.signal import fftconvolve

    wavelength = wavefront.get_wavelength()

    X = wavefront.get_mesh_x()
    Y = wavefront.get_mesh_y()

    if shift_half_pixel:
        x = wavefront.get_coordinate_x()
        y = wavefront.get_coordinate_y()
        X += 0.5 * numpy.abs(x[0] - x[1])
        Y += 0.5 * numpy.abs(y[0] - y[1])

    kernel = numpy.exp(1j * 2 * numpy.pi / wavefront.get_wavelength() *
                       (X**2 + Y**2) / 2 / propagation_distance)
    kernel *= numpy.exp(1j * 2 * numpy.pi / wavefront.get_wavelength() *
                        propagation_distance)
    kernel /= 1j * wavefront.get_wavelength() * propagation_distance

    tmp = fftconvolve(wavefront.get_complex_amplitude(), kernel, mode='same')

    # tmp = convolve(wavefront.get_complex_amplitude(), kernel, mode='full',method='auto')

    # print(">>>>>>>>>>>> kernel: ",kernel.shape)
    # print(">>>>>>>>>>>> wavefront: ", wavefront.get_complex_amplitude().shape)
    # print(">>>>>>>>>>>> result: ", tmp.shape,numpy.arange(0, tmp.shape[1]).shape)

    wf_propagated = Wavefront2D.initialize_wavefront_from_arrays(
        wavefront.get_coordinate_x(),
        wavefront.get_coordinate_y(),
        tmp,
        wavelength=wavelength)

    # start = 0.75 * (tmp.shape)[0]
    # start = int(start)
    # end = start + (tmp.shape)[0]
    #
    # tmp2 = (numpy.copy(tmp))[start:end,start:end]
    #
    # print(">>>>>>>>>>> tmp2,start,end",tmp2.shape,start,end)
    #
    #
    # wf_propagated = Wavefront2D.initialize_wavefront_from_arrays(numpy.arange(0,tmp2.shape[0]),
    #                                                              numpy.arange(0, tmp2.shape[1]),
    #                                                              tmp2,
    #                                                              wavelength=wavelength)

    return wf_propagated
Exemplo n.º 5
0
def propagate_2D_fresnel(wavefront, propagation_distance, shift_half_pixel=1):
    """
    2D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance
    :param shift_half_pixel: set to 1 to shift half pixel (recommended using an even number of pixels) Set as default.
    :return: a new 2D wavefront object with propagated wavefront
    """
    wavelength = wavefront.get_wavelength()

    #
    # convolving with the Fresnel kernel via FFT multiplication
    #
    fft = numpy.fft.fft2(wavefront.get_complex_amplitude())

    # frequency for axis 1
    shape = wavefront.size()
    delta = wavefront.delta()

    pixelsize = delta[0]  # p_x[1] - p_x[0]
    npixels = shape[0]
    freq_nyquist = 0.5 / pixelsize
    freq_n = numpy.linspace(-1.0, 1.0, npixels)
    freq_x = freq_n * freq_nyquist

    # frequency for axis 2
    pixelsize = delta[1]
    npixels = shape[1]
    freq_nyquist = 0.5 / pixelsize
    freq_n = numpy.linspace(-1.0, 1.0, npixels)
    freq_y = freq_n * freq_nyquist

    if shift_half_pixel:
        freq_x = freq_x - 0.5 * numpy.abs(freq_x[1] - freq_x[0])
        freq_y = freq_y - 0.5 * numpy.abs(freq_y[1] - freq_y[0])

    freq_xy = numpy.array(numpy.meshgrid(freq_y, freq_x))
    fft *= numpy.exp(
        (-1.0j) * numpy.pi * wavelength * propagation_distance *
        numpy.fft.fftshift(freq_xy[0] * freq_xy[0] + freq_xy[1] * freq_xy[1]))

    ifft = numpy.fft.ifft2(fft)

    wf_propagated = Wavefront2D.initialize_wavefront_from_arrays(
        wavefront.get_coordinate_x(),
        wavefront.get_coordinate_y(),
        ifft,
        wavelength=wavelength)
    return wf_propagated
Exemplo n.º 6
0
def propagate_2D_fresnel(wavefront, propagation_distance,shift_half_pixel=1):
    """
    2D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance
    :param shift_half_pixel: set to 1 to shift half pixel (recommended using an even number of pixels) Set as default.
    :return: a new 2D wavefront object with propagated wavefront
    """
    wavelength = wavefront.get_wavelength()

    #
    # convolving with the Fresnel kernel via FFT multiplication
    #
    fft = numpy.fft.fft2(wavefront.get_complex_amplitude())

    # frequency for axis 1
    shape = wavefront.size()
    delta = wavefront.delta()

    pixelsize = delta[0] # p_x[1] - p_x[0]
    npixels = shape[0]
    freq_nyquist = 0.5/pixelsize
    freq_n = numpy.linspace(-1.0,1.0,npixels)
    freq_x = freq_n * freq_nyquist

    # frequency for axis 2
    pixelsize = delta[1]
    npixels = shape[1]
    freq_nyquist = 0.5/pixelsize
    freq_n = numpy.linspace(-1.0,1.0,npixels)
    freq_y = freq_n * freq_nyquist

    if shift_half_pixel:
        freq_x = freq_x - 0.5 * numpy.abs(freq_x[1] - freq_x[0])
        freq_y = freq_y - 0.5 * numpy.abs(freq_y[1] - freq_y[0])

    freq_xy = numpy.array(numpy.meshgrid(freq_y,freq_x))
    fft *= numpy.exp((-1.0j) * numpy.pi * wavelength * propagation_distance *
                  numpy.fft.fftshift(freq_xy[0]*freq_xy[0] + freq_xy[1]*freq_xy[1]) )

    ifft = numpy.fft.ifft2(fft)

    wf_propagated = Wavefront2D.initialize_wavefront_from_arrays(wavefront.get_coordinate_x(),
                                                                 wavefront.get_coordinate_y(),
                                                                 ifft,
                                                                 wavelength=wavelength)
    return wf_propagated
Exemplo n.º 7
0
    def test_initializers(self,do_plot=do_plot):

        print("#                                                             ")
        print("# Tests for initializars (2D)                                 ")
        print("#                                                             ")

        x = numpy.linspace(-100,100,50)
        y = numpy.linspace(-50,50,200)
        XY = numpy.meshgrid(x,y)
        X = XY[0].T
        Y = XY[1].T
        sigma = 10
        Z = numpy.exp(- (X**2 + Y**2)/2/sigma**2) * 1j
        print("Shapes x,y,z: ",x.shape,y.shape,Z.shape)

        wf0 = Wavefront2D.initialize_wavefront_from_steps(x[0],numpy.abs(x[1]-x[0]),y[0],numpy.abs(y[1]-y[0]),number_of_points=Z.shape)
        wf0.set_complex_amplitude(Z)

        wf1 = Wavefront2D.initialize_wavefront_from_range(x[0],x[-1],y[0],y[-1],number_of_points=Z.shape)
        wf1.set_complex_amplitude(Z)

        wf2 = Wavefront2D.initialize_wavefront_from_arrays(x,y,Z)

        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf0.get_intensity(),wf0.get_coordinate_x(),wf0.get_coordinate_y(),
                       title="initialize_wavefront_from_steps",show=0)
            plot_image(wf1.get_intensity(),wf1.get_coordinate_x(),wf1.get_coordinate_y(),
                       title="initialize_wavefront_from_range",show=0)
            plot_image(wf2.get_intensity(),wf2.get_coordinate_x(),wf2.get_coordinate_y(),
                       title="initialize_wavefront_from_arrays",show=1)


        numpy.testing.assert_almost_equal(numpy.abs(Z)**2,wf0.get_intensity(),11)
        numpy.testing.assert_almost_equal(numpy.abs(Z)**2,wf1.get_intensity(),11)
        numpy.testing.assert_almost_equal(numpy.abs(Z)**2,wf2.get_intensity(),11)

        numpy.testing.assert_almost_equal(x,wf0.get_coordinate_x(),11)
        numpy.testing.assert_almost_equal(x,wf1.get_coordinate_x(),11)
        numpy.testing.assert_almost_equal(x,wf2.get_coordinate_x(),11)

        numpy.testing.assert_almost_equal(y,wf0.get_coordinate_y(),11)
        numpy.testing.assert_almost_equal(y,wf1.get_coordinate_y(),11)
        numpy.testing.assert_almost_equal(y,wf2.get_coordinate_y(),11)
Exemplo n.º 8
0
 def get_wavefront2d(self,i_mode,wavelength):
     return Wavefront2D.initialize_wavefront_from_arrays(self.x_coordinates(),self.y_coordinates(),
                                                 self.mode(i_mode),wavelength=wavelength)
Exemplo n.º 9
0
def propagate_2D_integral(wavefront, propagation_distance,
                          shuffle_interval=0,calculate_grid_only=1):

    """
    2D Fresnel-Kirchhoff propagator via simplified integral

    NOTE: this propagator is experimental and much less performant than the ones using Fourier Optics
          Therefore, it is not recommended to use.

    :param wavefront:
    :param propagation_distance: propagation distance
    :param shuffle_interval: it is known that this method replicates the central diffraction spot
                            The distace of the replica is proportional to 1/pixelsize
                            To avoid that, it is possible to change a bit (randomly) the coordinates
                            of the wavefront. shuffle_interval controls this shift: 0=No shift. A typical
                             value can be 1e5.
                             The result shows a diffraction pattern without replica but with much noise.
    :param calculate_grid_only: if set, it calculates only the horizontal and vertical profiles, but returns the
                             full image with the other pixels to zero. This is useful when calculating large arrays,
                             so it is set as the default.
    :return: a new 2D wavefront object with propagated wavefront
    """

    #
    # Fresnel-Kirchhoff integral (neglecting inclination factor)
    #

    if calculate_grid_only == 0:
        #
        # calculation over the whole detector area
        #
        p_x = wavefront.get_coordinate_x()
        p_y = wavefront.get_coordinate_y()
        wavelength = wavefront.get_wavelength()
        amplitude = wavefront.get_complex_amplitude()

        det_x = p_x.copy()
        det_y = p_y.copy()

        p_X = wavefront.get_mesh_x()
        p_Y = wavefront.get_mesh_y()

        det_X = p_X
        det_Y = p_Y


        amplitude_propagated = numpy.zeros_like(amplitude,dtype='complex')

        wavenumber = 2 * numpy.pi / wavelength

        for i in range(det_x.size):
            for j in range(det_y.size):
                if shuffle_interval == 0:
                    rd_x = 0.0
                    rd_y = 0.0
                else:
                    rd_x = (numpy.random.rand(p_x.size,p_y.size)-0.5)*shuffle_interval
                    rd_y = (numpy.random.rand(p_x.size,p_y.size)-0.5)*shuffle_interval

                r = numpy.sqrt( numpy.power(p_X + rd_x - det_X[i,j],2) +
                                numpy.power(p_Y + rd_y - det_Y[i,j],2) +
                                numpy.power(propagation_distance,2) )

                amplitude_propagated[i,j] = (amplitude / r * numpy.exp(1.j * wavenumber *  r)).sum()

        wavefront2 = Wavefront2D.initialize_wavefront_from_arrays(det_x,det_y,amplitude_propagated)

    else:
        x = wavefront.get_coordinate_x()
        y = wavefront.get_coordinate_y()
        X = wavefront.get_mesh_x()
        Y = wavefront.get_mesh_y()
        wavenumber = 2 * numpy.pi / wavefront.get_wavelength()
        amplitude = wavefront.get_complex_amplitude()

        used_indices = wavefront.get_mask_grid(width_in_pixels=(1,1),number_of_lines=(1,1))
        indices_x = wavefront.get_mesh_indices_x()
        indices_y = wavefront.get_mesh_indices_y()

        indices_x_flatten = indices_x[numpy.where(used_indices == 1)].flatten()
        indices_y_flatten = indices_y[numpy.where(used_indices == 1)].flatten()
        X_flatten         =         X[numpy.where(used_indices == 1)].flatten()
        Y_flatten         =         Y[numpy.where(used_indices == 1)].flatten()
        complex_amplitude_propagated = amplitude*0

        print("propagate_2D_integral: Calculating %d points from a total of %d x %d = %d"%(
            X_flatten.size,amplitude.shape[0],amplitude.shape[1],amplitude.shape[0]*amplitude.shape[1]))

        for i in range(X_flatten.size):
            r = numpy.sqrt( numpy.power(wavefront.get_mesh_x() - X_flatten[i],2) +
                            numpy.power(wavefront.get_mesh_y() - Y_flatten[i],2) +
                            numpy.power(propagation_distance,2) )

            complex_amplitude_propagated[indices_x_flatten[i],indices_y_flatten[i]] = (amplitude / r * numpy.exp(1.j * wavenumber *  r)).sum()


        wavefront2 = Wavefront2D.initialize_wavefront_from_arrays(x,y,complex_amplitude_propagated,wavefront.get_wavelength())

    return  wavefront2
Exemplo n.º 10
0
def propagate_2D_fraunhofer(wavefront,
                            propagation_distance=1.0,
                            shift_half_pixel=0):  #todo: modificato da giovanni
    """
    2D Fraunhofer propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance. If set to zero, the abscissas
                                 of the returned wavefront are in angle (rad)
    :param shift_half_pixel: set to 1 to shift half pixel (recommended using an even number of pixels) Set as default.
    :return: a new 2D wavefront object with propagated wavefront
    """
    wavelength = wavefront.get_wavelength()

    #
    # check validity
    #
    x = wavefront.get_coordinate_x()
    y = wavefront.get_coordinate_y()
    half_max_aperture = 0.5 * numpy.array((x[-1] - x[0], y[-1] - y[0])).max()
    far_field_distance = half_max_aperture**2 / wavelength
    if propagation_distance < far_field_distance:
        print(
            "WARNING: Fraunhoffer diffraction valid for distances > > half_max_aperture^2/lambda = %f m (propagating at %4.1f)"
            % (far_field_distance, propagation_distance))
    #
    #compute Fourier transform
    #

    # frequency for axis 1
    shape = wavefront.size()
    delta = wavefront.delta()
    wavenumber = wavefront.get_wavenumber()

    pixelsize = delta[0]  # p_x[1] - p_x[0]
    npixels = shape[0]
    fft_scale = numpy.fft.fftfreq(npixels, d=pixelsize)
    fft_scale = numpy.fft.fftshift(fft_scale)
    x2 = fft_scale * propagation_distance * wavelength

    # frequency for axis 2
    pixelsize = delta[1]
    npixels = shape[1]
    fft_scale = numpy.fft.fftfreq(npixels, d=pixelsize)
    fft_scale = numpy.fft.fftshift(fft_scale)
    y2 = fft_scale * propagation_distance * wavelength

    f_x, f_y = numpy.meshgrid(x2, y2, indexing='ij')
    fsq = numpy.fft.fftshift(f_x**2 + f_y**2)

    P1 = numpy.exp(1.0j * wavenumber * propagation_distance)
    P2 = numpy.exp(1.0j * wavenumber / 2 / propagation_distance * fsq)
    P3 = 1.0j * wavelength * propagation_distance

    F1 = numpy.fft.fft2(wavefront.get_complex_amplitude()
                        )  # Take the fourier transform of the image.
    #  Now shift the quadrants around so that low spatial frequencies are in
    # the center of the 2D fourier transformed image.
    F1 *= P1
    F1 *= P2
    F1 /= P3
    F2 = numpy.fft.fftshift(F1)

    if shift_half_pixel:
        x2 = x2 - 0.5 * numpy.abs(x2[1] - x2[0])
        y2 = y2 - 0.5 * numpy.abs(y2[1] - y2[0])

    wf_propagated = Wavefront2D.initialize_wavefront_from_arrays(
        x2, y2, F2, wavelength=wavelength)
    return wf_propagated
Exemplo n.º 11
0
def propagate_2D_integral(wavefront,
                          propagation_distance,
                          shuffle_interval=0,
                          calculate_grid_only=1):
    """
    2D Fresnel-Kirchhoff propagator via simplified integral

    NOTE: this propagator is experimental and much less performant than the ones using Fourier Optics
          Therefore, it is not recommended to use.

    :param wavefront:
    :param propagation_distance: propagation distance
    :param shuffle_interval: it is known that this method replicates the central diffraction spot
                            The distace of the replica is proportional to 1/pixelsize
                            To avoid that, it is possible to change a bit (randomly) the coordinates
                            of the wavefront. shuffle_interval controls this shift: 0=No shift. A typical
                             value can be 1e5.
                             The result shows a diffraction pattern without replica but with much noise.
    :param calculate_grid_only: if set, it calculates only the horizontal and vertical profiles, but returns the
                             full image with the other pixels to zero. This is useful when calculating large arrays,
                             so it is set as the default.
    :return: a new 2D wavefront object with propagated wavefront
    """

    #
    # Fresnel-Kirchhoff integral (neglecting inclination factor)
    #

    if calculate_grid_only == 0:
        #
        # calculation over the whole detector area
        #
        p_x = wavefront.get_coordinate_x()
        p_y = wavefront.get_coordinate_y()
        wavelength = wavefront.get_wavelength()
        amplitude = wavefront.get_complex_amplitude()

        det_x = p_x.copy()
        det_y = p_y.copy()

        p_X = wavefront.get_mesh_x()
        p_Y = wavefront.get_mesh_y()

        det_X = p_X
        det_Y = p_Y

        amplitude_propagated = numpy.zeros_like(amplitude, dtype='complex')

        wavenumber = 2 * numpy.pi / wavelength

        for i in range(det_x.size):
            for j in range(det_y.size):
                if shuffle_interval == 0:
                    rd_x = 0.0
                    rd_y = 0.0
                else:
                    rd_x = (numpy.random.rand(p_x.size, p_y.size) -
                            0.5) * shuffle_interval
                    rd_y = (numpy.random.rand(p_x.size, p_y.size) -
                            0.5) * shuffle_interval

                r = numpy.sqrt(
                    numpy.power(p_X + rd_x - det_X[i, j], 2) +
                    numpy.power(p_Y + rd_y - det_Y[i, j], 2) +
                    numpy.power(propagation_distance, 2))

                amplitude_propagated[i, j] = (
                    amplitude / r * numpy.exp(1.j * wavenumber * r)).sum()

        wavefront2 = Wavefront2D.initialize_wavefront_from_arrays(
            det_x, det_y, amplitude_propagated)

    else:
        x = wavefront.get_coordinate_x()
        y = wavefront.get_coordinate_y()
        X = wavefront.get_mesh_x()
        Y = wavefront.get_mesh_y()
        wavenumber = 2 * numpy.pi / wavefront.get_wavelength()
        amplitude = wavefront.get_complex_amplitude()

        used_indices = wavefront.get_mask_grid(width_in_pixels=(1, 1),
                                               number_of_lines=(1, 1))
        indices_x = wavefront.get_mesh_indices_x()
        indices_y = wavefront.get_mesh_indices_y()

        indices_x_flatten = indices_x[numpy.where(used_indices == 1)].flatten()
        indices_y_flatten = indices_y[numpy.where(used_indices == 1)].flatten()
        X_flatten = X[numpy.where(used_indices == 1)].flatten()
        Y_flatten = Y[numpy.where(used_indices == 1)].flatten()
        complex_amplitude_propagated = amplitude * 0

        print(
            "propagate_2D_integral: Calculating %d points from a total of %d x %d = %d"
            % (X_flatten.size, amplitude.shape[0], amplitude.shape[1],
               amplitude.shape[0] * amplitude.shape[1]))

        for i in range(X_flatten.size):
            r = numpy.sqrt(
                numpy.power(wavefront.get_mesh_x() - X_flatten[i], 2) +
                numpy.power(wavefront.get_mesh_y() - Y_flatten[i], 2) +
                numpy.power(propagation_distance, 2))

            complex_amplitude_propagated[indices_x_flatten[i],
                                         indices_y_flatten[i]] = (
                                             amplitude / r * numpy.exp(
                                                 1.j * wavenumber * r)).sum()

        wavefront2 = Wavefront2D.initialize_wavefront_from_arrays(
            x, y, complex_amplitude_propagated, wavefront.get_wavelength())

    return wavefront2
Exemplo n.º 12
0
def propagator2d_fourier_rescaling_xy(wf,
                                      propagation_distance,
                                      shift_half_pixel=1,
                                      m_x=1,
                                      m_y=1):

    wavefront = wf.duplicate()

    wavenumber = wavefront.get_wavenumber()
    wavelength = wavefront.get_wavelength()

    # frequency for axis 1
    shape = wavefront.size()
    delta = wavefront.delta()

    pixelsize = delta[0]  # p_x[1] - p_x[0]
    npixels = shape[0]
    freq_nyquist = 0.5 / pixelsize
    freq_n = numpy.linspace(-1.0, 1.0, npixels)
    freq_x = freq_n * freq_nyquist

    # frequency for axis 2
    pixelsize = delta[1]
    npixels = shape[1]
    freq_nyquist = 0.5 / pixelsize
    freq_n = numpy.linspace(-1.0, 1.0, npixels)
    freq_y = freq_n * freq_nyquist

    if shift_half_pixel:
        freq_x = freq_x - 0.5 * numpy.abs(freq_x[1] - freq_x[0])
        freq_y = freq_y - 0.5 * numpy.abs(freq_y[1] - freq_y[0])

    f_x, f_y = numpy.meshgrid(freq_x, freq_y, indexing='ij')
    fsq = numpy.fft.fftshift(f_x**2 / m_x + f_y**2 / m_y)

    x = wavefront.get_mesh_x()
    y = wavefront.get_mesh_y()

    x_rescaling = wavefront.get_mesh_x() * m_x
    y_rescaling = wavefront.get_mesh_y() * m_y

    r1sq = x**2 * (1 - m_x) + y**2 * (1 - m_y)
    r2sq = x_rescaling**2 * (m_x - 1 / m_x) + y_rescaling**2 * (m_y - 1 / m_y)

    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)

    wavefront.add_phase_shift(Q1)

    fft = numpy.fft.fft2(wavefront.get_complex_amplitude())

    ifft = numpy.fft.ifft2(fft * Q2) * Q3 / numpy.sqrt(m_x * m_y)

    wf_propagated = Wavefront2D.initialize_wavefront_from_arrays(
        wavefront.get_coordinate_x() *
        m_x,  ####################NON SONO SICURO CHE SIA GIUSTO QUELLO CHE RETURN
        wavefront.get_coordinate_y() * m_y,
        ifft,
        wavelength=wavelength)

    return wf_propagated
Exemplo n.º 13
0
 def get_wavefront2d(self, i_mode, wavelength):
     return Wavefront2D.initialize_wavefront_from_arrays(
         self.x_coordinates(),
         self.y_coordinates(),
         self.mode(i_mode),
         wavelength=wavelength)
Exemplo n.º 14
0
    def test_polarization(self, do_plot=0):

        print("#                                                             ")
        print("# Tests polarization                                      ")
        print("#                                                             ")

        #
        # from steps
        #

        x = numpy.linspace(-10, 10, 100)
        y = numpy.linspace(-20, 20, 50)
        # XY = numpy.meshgrid(y,x)
        # sigma = 3.0
        # Z = numpy.exp(- (XY[0]**2+XY[1]**2)/2/sigma**2)

        xy = numpy.meshgrid(x, y)
        X = xy[0].T
        Y = xy[1].T
        sigma = 3.0
        Z = numpy.exp(-(X**2 + Y**2) / 2 / sigma**2)
        Zp = 0.5 * numpy.exp(-(X**2 + Y**2) / 2 / sigma**2)

        print("shape of Z", Z.shape)

        wf = Wavefront2D.initialize_wavefront_from_steps(x[0],
                                                         x[1] - x[0],
                                                         y[0],
                                                         y[1] - y[0],
                                                         number_of_points=(100,
                                                                           50))
        print("wf shape: ", wf.size())
        wf.set_complex_amplitude(Z, polarization=Polarization.SIGMA)
        wf.set_complex_amplitude(Zp, polarization=Polarization.PI)
        print("Total intensity: ",
              wf.get_intensity(polarization=Polarization.TOTAL).sum())
        print("Sigma intensity: ",
              wf.get_intensity(polarization=Polarization.SIGMA).sum())
        print("Pi intensity: ",
              wf.get_intensity(polarization=Polarization.PI).sum())

        self.assertAlmostEqual(wf.get_intensity(polarization=Polarization.TOTAL).sum(),
                            wf.get_intensity(polarization=Polarization.SIGMA).sum() +\
                            wf.get_intensity(polarization=Polarization.PI).sum())

        #
        # from range
        #

        x = numpy.linspace(-100, 100, 50)
        y = numpy.linspace(-50, 50, 200)
        X = numpy.outer(x, numpy.ones_like(y))
        Y = numpy.outer(numpy.ones_like(x), y)
        sigma = 10
        Z = numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) * 1j
        Zp = 0.3333 * numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) * 1j
        print("Shapes x,y,z: ", x.shape, y.shape, Z.shape)

        wf1 = Wavefront2D.initialize_wavefront_from_range(
            x[0],
            x[-1],
            y[0],
            y[-1],
            number_of_points=Z.shape,
            polarization=Polarization.SIGMA)
        wf1.set_complex_amplitude(Z, polarization=Polarization.SIGMA)
        wf1.set_complex_amplitude(Zp, polarization=Polarization.PI)

        print("Total intensity: ",
              wf1.get_intensity(polarization=Polarization.TOTAL).sum())
        print("Sigma intensity: ",
              wf1.get_intensity(polarization=Polarization.SIGMA).sum())
        print("Pi intensity: ",
              wf1.get_intensity(polarization=Polarization.PI).sum())

        self.assertAlmostEqual(wf1.get_intensity(polarization=Polarization.TOTAL).sum(),
                            wf1.get_intensity(polarization=Polarization.SIGMA).sum() +\
                            wf1.get_intensity(polarization=Polarization.PI).sum())

        #
        # from arrays
        #
        wf2 = Wavefront2D.initialize_wavefront_from_arrays(x, y, Z, Zp)

        self.assertAlmostEqual(wf2.get_intensity(polarization=Polarization.TOTAL).sum(),
                            wf2.get_intensity(polarization=Polarization.SIGMA).sum() +\
                            wf2.get_intensity(polarization=Polarization.PI).sum())
Exemplo n.º 15
0
    def test_initializers(self, do_plot=do_plot):

        print("#                                                             ")
        print("# Tests for initializars (2D)                                 ")
        print("#                                                             ")

        x = numpy.linspace(-100, 100, 50)
        y = numpy.linspace(-50, 50, 200)
        XY = numpy.meshgrid(x, y)
        X = XY[0].T
        Y = XY[1].T
        sigma = 10
        Z = numpy.exp(-(X**2 + Y**2) / 2 / sigma**2) * 1j
        print("Shapes x,y,z: ", x.shape, y.shape, Z.shape)

        wf0 = Wavefront2D.initialize_wavefront_from_steps(
            x[0],
            numpy.abs(x[1] - x[0]),
            y[0],
            numpy.abs(y[1] - y[0]),
            number_of_points=Z.shape)
        wf0.set_complex_amplitude(Z)

        wf1 = Wavefront2D.initialize_wavefront_from_range(
            x[0], x[-1], y[0], y[-1], number_of_points=Z.shape)
        wf1.set_complex_amplitude(Z)

        wf2 = Wavefront2D.initialize_wavefront_from_arrays(x, y, Z)

        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf0.get_intensity(),
                       wf0.get_coordinate_x(),
                       wf0.get_coordinate_y(),
                       title="initialize_wavefront_from_steps",
                       show=0)
            plot_image(wf1.get_intensity(),
                       wf1.get_coordinate_x(),
                       wf1.get_coordinate_y(),
                       title="initialize_wavefront_from_range",
                       show=0)
            plot_image(wf2.get_intensity(),
                       wf2.get_coordinate_x(),
                       wf2.get_coordinate_y(),
                       title="initialize_wavefront_from_arrays",
                       show=1)

        numpy.testing.assert_almost_equal(
            numpy.abs(Z)**2, wf0.get_intensity(), 11)
        numpy.testing.assert_almost_equal(
            numpy.abs(Z)**2, wf1.get_intensity(), 11)
        numpy.testing.assert_almost_equal(
            numpy.abs(Z)**2, wf2.get_intensity(), 11)

        numpy.testing.assert_almost_equal(x, wf0.get_coordinate_x(), 11)
        numpy.testing.assert_almost_equal(x, wf1.get_coordinate_x(), 11)
        numpy.testing.assert_almost_equal(x, wf2.get_coordinate_x(), 11)

        numpy.testing.assert_almost_equal(y, wf0.get_coordinate_y(), 11)
        numpy.testing.assert_almost_equal(y, wf1.get_coordinate_y(), 11)
        numpy.testing.assert_almost_equal(y, wf2.get_coordinate_y(), 11)