Beispiel #1
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)
Beispiel #2
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
Beispiel #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
Beispiel #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
Beispiel #5
0
    def undulator(self, method, npixels_x, npixels_y, pixelsize_x, pixelsize_y,
                  wavelength, sigma, m, m_x, m_y, propagation_distance, radius,
                  show, image_source, apply_lens):

        wavefront = Wavefront2D.initialize_wavefront_from_range(
            x_min=-pixelsize_x * npixels_x / 2,
            x_max=pixelsize_x * npixels_x / 2,
            y_min=-pixelsize_y * npixels_y / 2,
            y_max=pixelsize_y * npixels_y / 2,
            number_of_points=(npixels_x, npixels_y),
            wavelength=wavelength)

        wavefront.set_spherical_wave(radius=radius)

        if image_source == False:

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

            wavefront.rescale_amplitude(
                numpy.exp(-(X**2 + Y**2) / (2 * sigma**2))
            )  # applichiamo intensita' con profilo gaussiano

        print("Input intensity: ", wavefront.get_intensity().sum())

        if apply_lens == True:
            wavefront.apply_ideal_lens(focal_length_x=propagation_distance,
                                       focal_length_y=propagation_distance)

            print("Intensity after lens: ", wavefront.get_intensity().sum())

        if method == 'fft':
            output_wf = propagate_2D_fresnel(
                wavefront, propagation_distance=propagation_distance)
        elif method == 'rescaling':
            output_wf = propagator2d_fourier_rescaling(
                wavefront, propagation_distance=propagation_distance, m=m)
        elif method == 'rescaling_xy':
            output_wf = propagator2d_fourier_rescaling_xy(
                wavefront,
                propagation_distance=propagation_distance,
                m_x=m_x,
                m_y=m_y)

        plot_undulator(output_wf, method=method, show=show)

        horizontal_profile_wf = line_image(wavefront.get_intensity(),
                                           horizontal_or_vertical='H')

        vertical_profile_wf = line_image(wavefront.get_intensity(),
                                         horizontal_or_vertical='V')

        horizontal_phase_profile_wf = line_image(wavefront.get_phase(),
                                                 horizontal_or_vertical='H')

        if image_source == True:
            return wavefront.get_coordinate_x(
            ), horizontal_profile_wf, horizontal_phase_profile_wf
    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)
    def test_plane_wave(self,do_plot=do_plot):
        #
        # plane wave
        #
        print("#                                                             ")
        print("# Tests for a 2D plane wave                                      ")
        print("#                                                             ")

        wavelength        = 1.24e-10

        wavefront_length_x = 400e-6
        wavefront_length_y = wavefront_length_x

        npixels_x =  1024
        npixels_y =  npixels_x

        x = numpy.linspace(-0.5*wavefront_length_x,0.5*wavefront_length_x,npixels_x)
        y = numpy.linspace(-0.5*wavefront_length_y,0.5*wavefront_length_y,npixels_y)

        wavefront = Wavefront2D.initialize_wavefront_from_steps(
                        x_start=x[0],x_step=numpy.abs(x[1]-x[0]),
                        y_start=y[0],y_step=numpy.abs(y[1]-y[0]),
                        number_of_points=(npixels_x,npixels_y),wavelength=wavelength)

        # possible modifications

        wavefront.set_plane_wave_from_amplitude_and_phase(5.0,numpy.pi/2)
        numpy.testing.assert_almost_equal(wavefront.get_intensity(),25,5)

        wavefront.set_plane_wave_from_complex_amplitude(2.0+3j)
        numpy.testing.assert_almost_equal(wavefront.get_intensity(),13,5)

        phase_before = wavefront.get_phase()
        wavefront.add_phase_shift(numpy.pi/2)
        phase_after = wavefront.get_phase()
        numpy.testing.assert_almost_equal(phase_before+numpy.pi/2,phase_after,5)

        intensity_before = wavefront.get_intensity()
        wavefront.rescale_amplitude(10.0)
        intensity_after = wavefront.get_intensity()
        numpy.testing.assert_almost_equal(intensity_before*100,intensity_after,5)

        # interpolation

        wavefront.set_plane_wave_from_complex_amplitude(2.0+3j)
        test_value1 = wavefront.get_interpolated_complex_amplitude(0.01,1.3)
        self.assertAlmostEqual( (2.0+3j).real, test_value1.real, 5)
        self.assertAlmostEqual( (2.0+3j).imag, test_value1.imag, 5)


        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wavefront.get_intensity(),wavefront.get_coordinate_x(),wavefront.get_coordinate_y(),
                       title="Intensity (plane wave)",show=0)
            plot_image(wavefront.get_phase(),wavefront.get_coordinate_x(),wavefront.get_coordinate_y(),
                       title="Phase (plane wave)",show=1)
Beispiel #8
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
Beispiel #9
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
Beispiel #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
Beispiel #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
Beispiel #12
0
def propagate_2D_fresnel_srw(wavefront,
                             propagation_distance,
                             srw_autosetting=0):
    """
    2D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance:
    :param srw_autosetting:set to 1 for automatic SRW redimensionate wavefront
    :return:
    """

    #
    # convolving with the Fresnel kernel via SRW package
    #

    from srxraylib.waveoptics.NumpyToSRW import numpyArrayToSRWArray, SRWWavefrontFromElectricField, SRWEFieldAsNumpy

    import scipy.constants as codata
    angstroms_to_eV = codata.h * codata.c / codata.e * 1e10

    srw_wfr = SRWWavefrontFromElectricField(
        wavefront.get_coordinate_x()[0],
        wavefront.get_coordinate_x()[-1], wavefront.get_complex_amplitude(),
        wavefront.get_coordinate_y()[0],
        wavefront.get_coordinate_y()[-1],
        numpy.zeros_like(wavefront.get_complex_amplitude()),
        angstroms_to_eV / (wavefront.get_wavelength() * 1e10), 1.0, 1.0, 1e-3,
        1.0, 1e-3)
    #
    # propagation
    #
    optDrift = srwlib.SRWLOptD(propagation_distance)  #Drift space

    #Wavefront Propagation Parameters:
    #[0]: Auto-Resize (1) or not (0) Before propagation
    #[1]: Auto-Resize (1) or not (0) After propagation
    #[2]: Relative Precision for propagation with Auto-Resizing (1. is nominal)
    #[3]: Allow (1) or not (0) for semi-analytical treatment of the quadratic (leading) phase terms at the propagation
    #[4]: Do any Resizing on Fourier side, using FFT, (1) or not (0)
    #[5]: Horizontal Range modification factor at Resizing (1. means no modification)
    #[6]: Horizontal Resolution modification factor at Resizing
    #[7]: Vertical Range modification factor at Resizing
    #[8]: Vertical Resolution modification factor at Resizing
    #[9]: Type of wavefront Shift before Resizing (not yet implemented)
    #[10]: New Horizontal wavefront Center position after Shift (not yet implemented)
    #[11]: New Vertical wavefront Center position after Shift (not yet implemented)

    if srw_autosetting:
        #                 0  1  2   3  4  5   6   7   8   9 10 11
        propagParDrift = [1, 1, 1., 0, 0, 1., 1., 1., 1., 0, 0, 0]
    else:
        #                 0  1  2   3  4  5   6   7   8   9 10 11
        propagParDrift = [0, 0, 1., 0, 0, 1., 1., 1., 1., 0, 0, 0]

    optBL = srwlib.SRWLOptC(
        [optDrift], [propagParDrift]
    )  #"Beamline" - Container of Optical Elements (together with the corresponding wavefront propagation instructions)

    print('   Simulating Electric Field Wavefront Propagation by SRW ... ',
          end='\n')
    srwlib.srwl.PropagElecField(srw_wfr, optBL)

    wavefront2 = Wavefront2D.initialize_wavefront_from_range(
        srw_wfr.mesh.xStart,
        srw_wfr.mesh.xFin,
        srw_wfr.mesh.yStart,
        srw_wfr.mesh.yFin,
        number_of_points=(srw_wfr.mesh.nx, srw_wfr.mesh.ny),
        wavelength=wavefront.get_wavelength())
    amplitude2 = SRWEFieldAsNumpy(srw_wfr)
    amplitude2 = amplitude2[0, :, :, 0]
    wavefront2.set_complex_amplitude(amplitude2)

    return wavefront2
    def test_interpolator(self,do_plot=do_plot):
        #
        # interpolator
        #
        print("#                                                             ")
        print("# Tests for 2D interpolator                                   ")
        print("#                                                             ")

        x = numpy.linspace(-10,10,100)
        y = numpy.linspace(-20,20,50)

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

        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 )

        x1 = 3.2
        y1 = -2.5
        z1 = 3*numpy.exp(- (x1**2+y1**2)/2/sigma**2) + 4j
        print("complex ampl at (%g,%g): %g+%gi (exact=%g+%gi)"%(x1,y1,
                                                        wf.get_interpolated_complex_amplitude(x1,y1).real,
                                                        wf.get_interpolated_complex_amplitude(x1,y1).imag,
                                                        z1.real,z1.imag))
        self.assertAlmostEqual(wf.get_interpolated_complex_amplitude(x1,y1).real,z1.real,4)
        self.assertAlmostEqual(wf.get_interpolated_complex_amplitude(x1,y1).imag,z1.imag,4)
        #
        print("intensity  at (%g,%g):   %g (exact=%g)"%(x1,y1,wf.get_interpolated_intensity(x1,y1),numpy.abs(z1)**2))
        self.assertAlmostEqual(wf.get_interpolated_intensity(x1,y1),numpy.abs(z1)**2,4)

        # interpolate on same grid

        interpolated_complex_amplitude_on_same_grid = wf.get_interpolated_complex_amplitudes(X,Y)
        print("Shape interpolated at same grid: ",interpolated_complex_amplitude_on_same_grid.shape)

        numpy.testing.assert_array_almost_equal(wf.get_complex_amplitude(),interpolated_complex_amplitude_on_same_grid,4)

        print("Total intensity original wavefront: %g, interpolated on the same grid: %g"%
              (wf.get_intensity().sum(), (numpy.abs(interpolated_complex_amplitude_on_same_grid)**2).sum()))



        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf.get_intensity(),wf.get_coordinate_x(),wf.get_coordinate_y(),title="Original",show=0)
            plot_image(wf.get_interpolated_intensity(X,Y),wf.get_coordinate_x(),wf.get_coordinate_y(),
                       title="interpolated on same grid",show=1)


        # rebin wavefront

        # wf.set_plane_wave_from_complex_amplitude(3+4j)
        wf_rebin = wf.rebin(2.0,5.0,0.5,0.8,keep_the_same_intensity=1,set_extrapolation_to_zero=1)
        print("Shape before rebinning: ",wf.size())
        print("Shape after rebinning: ",wf_rebin.size())

        print("Total intensity original wavefront: %g, rebinned: %g"%
              (wf.get_intensity().sum(), wf_rebin.get_intensity().sum() ))

        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf.get_intensity(),wf.get_coordinate_x(),wf.get_coordinate_y(),title="BEFORE REBINNING",show=0)
            plot_image(wf_rebin.get_intensity(),wf_rebin.get_coordinate_x(),wf_rebin.get_coordinate_y(),
                       title="REBINNED",show=1)
Beispiel #14
0
    def propagate_2D_fresnel(self,
                             do_plot,
                             method='fft',
                             wavelength=1.24e-10,
                             aperture_type='square',
                             aperture_diameter=40e-6,
                             pixelsize_x=1e-6,
                             pixelsize_y=1e-6,
                             npixels_x=1024,
                             npixels_y=1024,
                             propagation_distance=30.0,
                             m=1,
                             m_x=1,
                             m_y=1,
                             show=0):

        method_label = "fresnel (%s)" % method
        print(
            "\n#                                                             ")
        print("# 2D near field fresnel (%s) diffraction from a %s aperture  " %
              (method_label, aperture_type))
        print("#                                                             ")

        # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2,
        #                                                         x_step=pixelsize_x,
        #                                                         y_start=-pixelsize_y*npixels_y/2,
        #                                                         y_step=pixelsize_y,
        #                                                         wavelength=wavelength,
        #                                                         number_of_points=(npixels_x,npixels_y))

        wf = Wavefront2D.initialize_wavefront_from_range(
            x_min=-pixelsize_x * npixels_x / 2,
            x_max=pixelsize_x * npixels_x / 2,
            y_min=-pixelsize_y * npixels_y / 2,
            y_max=pixelsize_y * npixels_y / 2,
            number_of_points=(npixels_x, npixels_y),
            wavelength=wavelength)

        wf.set_plane_wave_from_complex_amplitude((1.0 + 0j))

        if aperture_type == 'circle':
            wf.apply_pinhole(aperture_diameter / 2)
        elif aperture_type == 'square':
            wf.apply_slit(-aperture_diameter / 2, aperture_diameter / 2,
                          -aperture_diameter / 2, aperture_diameter / 2)
        else:
            raise Exception("Not implemented! (accepted: circle, square)")

        if method == 'fft':
            wf1 = propagate_2D_fresnel(wf, propagation_distance)
        elif method == 'rescaling':
            wf1 = propagator2d_fourier_rescaling(wf, propagation_distance, m=m)
        elif method == 'rescaling_xy':
            wf1 = propagator2d_fourier_rescaling_xy(wf,
                                                    propagation_distance,
                                                    m_x=m_x,
                                                    m_y=m_y)
        else:
            raise Exception("Not implemented method: %s" % method)

        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf.get_intensity(),
                       1e6 * wf.get_coordinate_x(),
                       1e6 * wf.get_coordinate_y(),
                       title="aperture intensity (%s), Diameter=%5.1f um" %
                       (aperture_type, 1e6 * aperture_diameter),
                       xtitle="X [um]",
                       ytitle="Y [um]",
                       show=0)

            plot_image(
                wf1.get_intensity(),
                1e6 * wf1.get_coordinate_x() / propagation_distance,
                1e6 * wf1.get_coordinate_y() / propagation_distance,
                title=
                "Diffracted intensity (%s) by a %s slit of aperture %3.1f um" %
                (aperture_type, method_label, 1e6 * aperture_diameter),
                xtitle="X [urad]",
                ytitle="Y [urad]",
                show=0)

        # get the theoretical value
        angle_x = wf.get_coordinate_x() / propagation_distance

        intensity_theory = get_theoretical_diffraction_pattern(
            angle_x,
            aperture_type=aperture_type,
            aperture_diameter=aperture_diameter,
            wavelength=wavelength,
            normalization=True)

        intensity_calculated = wf1.get_intensity()[:, int(wf1.size()[1] / 2)]
        intensity_calculated /= intensity_calculated.max()

        if do_plot:
            from srxraylib.plot.gol import plot
            plot(
                wf1.get_coordinate_x() * 1e6 / propagation_distance,
                intensity_calculated,
                angle_x * 1e6,
                intensity_theory,
                legend=[
                    "%s H profile" % method_label, "Theoretical (far field)"
                ],
                legend_position=(0.60, 0.95),
                title=
                "%s diffraction of a %s slit of %3.1f um at wavelength of %3.1f A"
                % (method_label, aperture_type, aperture_diameter * 1e6,
                   wavelength * 1e10),
                xtitle="X (urad)",
                ytitle="Intensity",
                xrange=[-20, 20],
                show=show)

        if method == 'rescaling_xy' and do_plot:
            angle_y = wf.get_coordinate_y() / propagation_distance
            intensity_calculated_v = wf1.get_intensity()[int(wf1.size()[1] /
                                                             2), :]
            intensity_calculated_v /= intensity_calculated_v.max()

            from srxraylib.plot.gol import plot
            plot(
                wf1.get_coordinate_y() * 1e6 / propagation_distance,
                intensity_calculated_v,
                angle_y * 1e6,
                intensity_theory,
                legend=[
                    "%s V profile" % method_label, "Theoretical (far field)"
                ],
                legend_position=(0.60, 0.95),
                title=
                "%s diffraction of a %s slit of %3.1f um at wavelength of %3.1f A"
                % (method_label, aperture_type, aperture_diameter * 1e6,
                   wavelength * 1e10),
                xtitle="Y (urad)",
                ytitle="Intensity",
                xrange=[-20, 20],
                show=show)

        return wf1.get_coordinate_x(
        ) / propagation_distance, intensity_calculated, angle_x, intensity_theory
Beispiel #15
0
def propagate_2D_fresnel_srw(wavefront, propagation_distance,
                             srw_autosetting=0):
    """
    2D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance:
    :param srw_autosetting:set to 1 for automatic SRW redimensionate wavefront
    :return:
    """

    #
    # convolving with the Fresnel kernel via SRW package
    #


    from srxraylib.waveoptics.NumpyToSRW import numpyArrayToSRWArray, SRWWavefrontFromElectricField, SRWEFieldAsNumpy

    import scipy.constants as codata
    angstroms_to_eV = codata.h*codata.c/codata.e*1e10


    srw_wfr = SRWWavefrontFromElectricField(
                    wavefront.get_coordinate_x()[0],wavefront.get_coordinate_x()[-1],wavefront.get_complex_amplitude(),
                    wavefront.get_coordinate_y()[0],wavefront.get_coordinate_y()[-1],numpy.zeros_like(wavefront.get_complex_amplitude()),
                    angstroms_to_eV/(wavefront.get_wavelength()*1e10), 1.0, 1.0, 1e-3, 1.0, 1e-3)
    #
    # propagation
    #
    optDrift = srwlib.SRWLOptD(propagation_distance) #Drift space


    #Wavefront Propagation Parameters:
    #[0]: Auto-Resize (1) or not (0) Before propagation
    #[1]: Auto-Resize (1) or not (0) After propagation
    #[2]: Relative Precision for propagation with Auto-Resizing (1. is nominal)
    #[3]: Allow (1) or not (0) for semi-analytical treatment of the quadratic (leading) phase terms at the propagation
    #[4]: Do any Resizing on Fourier side, using FFT, (1) or not (0)
    #[5]: Horizontal Range modification factor at Resizing (1. means no modification)
    #[6]: Horizontal Resolution modification factor at Resizing
    #[7]: Vertical Range modification factor at Resizing
    #[8]: Vertical Resolution modification factor at Resizing
    #[9]: Type of wavefront Shift before Resizing (not yet implemented)
    #[10]: New Horizontal wavefront Center position after Shift (not yet implemented)
    #[11]: New Vertical wavefront Center position after Shift (not yet implemented)

    if srw_autosetting:
        #                 0  1  2   3  4  5   6   7   8   9 10 11
        propagParDrift = [1, 1, 1., 0, 0, 1., 1., 1., 1., 0, 0, 0]
    else:
        #                 0  1  2   3  4  5   6   7   8   9 10 11
        propagParDrift = [0, 0, 1., 0, 0, 1., 1., 1., 1., 0, 0, 0]

    optBL = srwlib.SRWLOptC([optDrift], [propagParDrift]) #"Beamline" - Container of Optical Elements (together with the corresponding wavefront propagation instructions)

    print('   Simulating Electric Field Wavefront Propagation by SRW ... ', end='\n')
    srwlib.srwl.PropagElecField(srw_wfr, optBL)



    wavefront2 = Wavefront2D.initialize_wavefront_from_range(srw_wfr.mesh.xStart, srw_wfr.mesh.xFin,
                                                             srw_wfr.mesh.yStart, srw_wfr.mesh.yFin,
                                                             number_of_points=(srw_wfr.mesh.nx,srw_wfr.mesh.ny),
                                                             wavelength=wavefront.get_wavelength())
    amplitude2 = SRWEFieldAsNumpy(srw_wfr)
    amplitude2 = amplitude2[0,:,:,0]
    wavefront2.set_complex_amplitude(amplitude2)

    return wavefront2
    def test_propagate_2D_fraunhofer(self,do_plot=do_plot,aperture_type='square',aperture_diameter=40e-6,
                    pixelsize_x=1e-6,pixelsize_y=1e-6,npixels_x=1024,npixels_y=1024,wavelength=1.24e-10):
        """

        :param do_plot: 0=No plot, 1=Do plot
        :param aperture_type: 'circle' 'square' 'gaussian' (Gaussian sigma = aperture_diameter/2.35)
        :param aperture_diameter:
        :param pixelsize_x:
        :param pixelsize_y:
        :param npixels_x:
        :param npixels_y:
        :param wavelength:
        :return:
        """

        print("\n#                                                            ")
        print("# far field 2D (fraunhofer) diffraction from a square aperture  ")
        print("#                                                            ")

        method = "fraunhofer"

        print("Fraunhoffer diffraction valid for distances > > a^2/lambda = %f m"%((aperture_diameter/2)**2/wavelength))

        # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2,
        #                                                         x_step=pixelsize_x,
        #                                                         y_start=-pixelsize_y*npixels_y/2,
        #                                                         y_step=pixelsize_y,
        #                                                         wavelength=wavelength,
        #                                                         number_of_points=(npixels_x,npixels_y))
        wf = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                         y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                         number_of_points=(npixels_x,npixels_y),wavelength=wavelength)

        wf.set_plane_wave_from_complex_amplitude((1.0+0j))

        if aperture_type == 'circle':
            wf.apply_pinhole(aperture_diameter/2)
        elif aperture_type == 'square':
            wf.apply_slit(-aperture_diameter/2, aperture_diameter/2,-aperture_diameter/2, aperture_diameter/2)
        elif aperture_type == 'gaussian':
            X = wf.get_mesh_x()
            Y = wf.get_mesh_y()
            window = numpy.exp(- (X*X + Y*Y)/2/(aperture_diameter/2.35)**2)
            wf.rescale_amplitudes(window)
        else:
            raise Exception("Not implemented! (accepted: circle, square, gaussian)")



        wf1 = propagate_2D_fraunhofer(wf, propagation_distance=1.0) # propagating at 1 m means the result is like in angles

        if do_plot:
            plot_image(wf.get_intensity(),1e6*wf.get_coordinate_x(),1e6*wf.get_coordinate_y(),
                       title="aperture intensity (%s), Diameter=%5.1f um"%
                             (aperture_type,1e6*aperture_diameter),xtitle="X [um]",ytitle="Y [um]",
                       show=0)

            plot_image(wf1.get_intensity(),1e6*wf1.get_coordinate_x(),1e6*wf1.get_coordinate_y(),
                       title="2D Diffracted intensity (%s) by a %s slit of aperture %3.1f um"%
                             (aperture_type,method,1e6*aperture_diameter),
                       xtitle="X [urad]",ytitle="Y [urad]",
                       show=0)

        angle_x = wf1.get_coordinate_x() # + 0.5*wf1.delta()[0] # shifted of half-pixel!!!
        intensity_theory = get_theoretical_diffraction_pattern(angle_x,
                                            aperture_type=aperture_type,aperture_diameter=aperture_diameter,
                                            wavelength=wavelength,normalization=True)


        intensity_calculated =  wf1.get_intensity()[:,wf1.size()[1]/2]
        intensity_calculated /= intensity_calculated.max()

        if do_plot:
            plot(wf1.get_coordinate_x()*1e6,intensity_calculated,
                 angle_x*1e6,intensity_theory,
                 legend=["Calculated (FT) H profile","Theoretical"],legend_position=(0.95, 0.95),
                 title="2D Fraunhofer Diffraction of a %s slit of %3.1f um at wavelength of %3.1f A"%
                       (aperture_type,aperture_diameter*1e6,wavelength*1e10),
                 xtitle="X (urad)", ytitle="Intensity",xrange=[-80,80])

        numpy.testing.assert_almost_equal(intensity_calculated,intensity_theory,1)
Beispiel #17
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)
Beispiel #18
0
    pixelsize_y = 1e-7
    npixels_x = 2024
    npixels_y = 2024
    propagation_distance = 1.0
    show = 1

    method_label = "fresnel (fft)"
    print("\n#                                                             ")
    print("# 2D near field fresnel (%s) diffraction from a a circular stop  " %
          (method_label))
    print("#                                                             ")

    wf = Wavefront2D.initialize_wavefront_from_range(
        x_min=-pixelsize_x * npixels_x / 2,
        x_max=pixelsize_x * npixels_x / 2,
        y_min=-pixelsize_y * npixels_y / 2,
        y_max=pixelsize_y * npixels_y / 2,
        number_of_points=(npixels_x, npixels_y),
        wavelength=wavelength)

    wf.set_plane_wave_from_complex_amplitude((1.0 + 0j))

    wf.apply_pinhole(aperture_diameter / 2, negative=True)

    wf1 = propagate_2D_fresnel(wf, propagation_distance)

    plot_image(wf.get_intensity(),
               1e6 * wf.get_coordinate_x(),
               1e6 * wf.get_coordinate_y(),
               title="intensity at screen/aperture plane, Diameter=%5.1f um" %
               (1e6 * aperture_diameter),
def main(mode_wavefront_before_lens):

    lens_diameter = 0.002 # 0.001 # 0.002

    if mode_wavefront_before_lens == 'Undulator with lens':
        npixels_x = 512
    else:
        npixels_x = int(2048*1.5)

    pixelsize_x = lens_diameter / npixels_x
    print("pixelsize: ",pixelsize_x)


    pixelsize_y = pixelsize_x
    npixels_y = npixels_x

    wavelength = 1.24e-10
    propagation_distance = 30.0
    defocus_factor = 1.0 # 1.0 is at focus
    propagation_steps = 1

    # for Gaussian source
    sigma_x = lens_diameter / 400 # 5e-6
    sigma_y = sigma_x # 5e-6
    # for Hermite-Gauss, the H and V mode index (start from 0)
    hm = 3
    hn = 1

    #
    # initialize wavefronts of dimension equal to the lens
    #
    wf_fft = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                     y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                     number_of_points=(npixels_x,npixels_y),wavelength=wavelength)

    wf_convolution = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                     y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                     number_of_points=(npixels_x,npixels_y),wavelength=wavelength)
    if SRWLIB_AVAILABLE:
        wf_srw = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                     y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                     number_of_points=(npixels_x,npixels_y),wavelength=wavelength)

    #
    # calculate/define wavefront at zero distance downstream the lens
    #
    if mode_wavefront_before_lens == 'convergent spherical':
        # no need to propagate nor define lens
        wf_fft.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance)
        wf_convolution.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance)
        if SRWLIB_AVAILABLE: wf_srw.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance)

    elif mode_wavefront_before_lens == 'divergent spherical with lens':
        # define wavefront at zero distance upstream the lens and apply lens
        focal_length = propagation_distance / 2.

        wf_fft.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance)
        wf_fft.apply_ideal_lens(focal_length,focal_length)

        wf_convolution.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)

        if SRWLIB_AVAILABLE:
            wf_srw.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance)
            wf_srw.apply_ideal_lens(focal_length,focal_length)

    elif mode_wavefront_before_lens == 'plane with lens':
        # define wavefront at zero distance upstream the lens and apply lens
        focal_length = propagation_distance

        wf_fft.set_plane_wave_from_complex_amplitude(1.0+0j)
        wf_fft.apply_ideal_lens(focal_length,focal_length)

        wf_convolution.set_plane_wave_from_complex_amplitude(1.0+0j)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)

        if SRWLIB_AVAILABLE:
            wf_srw.set_plane_wave_from_complex_amplitude(1.0+0j)
            wf_srw.apply_ideal_lens(focal_length,focal_length)

    elif mode_wavefront_before_lens == 'Gaussian with lens':
        # define wavefront at source point, propagate to the lens and apply lens
        X = wf_fft.get_mesh_x()
        Y = wf_fft.get_mesh_y()

        intensity = numpy.exp( - X**2/(2*sigma_x**2)) * numpy.exp( - Y**2/(2*sigma_y**2))


        wf_fft.set_complex_amplitude( numpy.sqrt(intensity) )
        wf_convolution.set_complex_amplitude( numpy.sqrt(intensity) )
        if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( numpy.sqrt(intensity) )

        # plot

        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[1]),title="Gaussian source",show=1)

        wf_fft, tmp1, tmp2 = propagation_to_image(wf_fft,method='fft',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")
        wf_convolution, tmp1, tmp2 = propagation_to_image(wf_convolution,method='convolution',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")
        if SRWLIB_AVAILABLE:
            wf_srw, tmp1, tmp2 = propagation_to_image(wf_srw,method='srw',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")


        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um",title="Before lens fft",show=1)

        plot_image(wf_convolution.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um (%d pixels)"%(wf_convolution.size()[0]),ytitle="Y um",title="Before lens convolution",show=1)

        focal_length = propagation_distance / 2

        wf_fft.apply_ideal_lens(focal_length,focal_length)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)
        if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length)

    elif mode_wavefront_before_lens == 'Hermite with lens':
        # define wavefront at source point, propagate to the lens and apply lens
        X = wf_fft.get_mesh_x()
        Y = wf_fft.get_mesh_y()

        efield =     (hermite(hm)(numpy.sqrt(2)*X/sigma_x)*numpy.exp(-X**2/sigma_x**2))**2 \
                   * (hermite(hn)(numpy.sqrt(2)*Y/sigma_y)*numpy.exp(-Y**2/sigma_y**2))**2

        wf_fft.set_complex_amplitude( efield )
        wf_convolution.set_complex_amplitude( efield )
        if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( efield )

        # plot

        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),title="Hermite-Gauss source",show=1)

        wf_fft, tmp1, tmp2 = propagation_to_image(wf_fft,method='fft',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")
        wf_convolution, tmp1, tmp2 = propagation_to_image(wf_convolution,method='convolution',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")
        if SRWLIB_AVAILABLE:
            wf_srw, tmp1, tmp2 = propagation_to_image(wf_srw,method='srw',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")


        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),title="Before lens fft",show=1)

        plot_image(wf_convolution.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),title="Before lens convolution",show=1)

        focal_length = propagation_distance / 2

        wf_fft.apply_ideal_lens(focal_length,focal_length)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)
        if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length)

    elif mode_wavefront_before_lens == 'Undulator with lens':

        beamline = {}
        beamline['ElectronCurrent'] = 0.2
        beamline['ElectronEnergy']  = 6.0
        beamline['Kv']              = 1.68  # 1.87
        beamline['NPeriods']        = 111   # 14
        beamline['PeriodID']        = 0.018 # 0.035
        beamline['distance']        =   propagation_distance

        gamma = beamline['ElectronEnergy'] / (codata_mee * 1e-3)
        print ("Gamma: %f \n"%(gamma))

        resonance_wavelength = (1 + beamline['Kv']**2 / 2.0) / 2 / gamma**2 * beamline["PeriodID"]
        resonance_energy = m2ev / resonance_wavelength


        print ("Resonance wavelength [A]: %g \n"%(1e10*resonance_wavelength))
        print ("Resonance energy [eV]: %g \n"%(resonance_energy))

        # red shift 100 eV
        resonance_energy = resonance_energy - 100


        myBeam = ElectronBeam(Electron_energy=beamline['ElectronEnergy'], I_current=beamline['ElectronCurrent'])
        myUndulator = MagneticStructureUndulatorPlane(K=beamline['Kv'], period_length=beamline['PeriodID'],
                            length=beamline['PeriodID']*beamline['NPeriods'])


        XX = wf_fft.get_mesh_x()
        YY = wf_fft.get_mesh_y()
        X = wf_fft.get_coordinate_x()
        Y = wf_fft.get_coordinate_y()

        source = SourceUndulatorPlane(undulator=myUndulator,
                            electron_beam=myBeam, magnetic_field=None)
        omega = resonance_energy * codata.e / codata.hbar
        Nb_pts_trajectory = int(source.choose_nb_pts_trajectory(0.01,photon_frequency=omega))
        print("Number of trajectory points: ",Nb_pts_trajectory)


        traj_fact = TrajectoryFactory(Nb_pts=Nb_pts_trajectory,method=TRAJECTORY_METHOD_ODE,
                                      initial_condition=None)

        print("Number of trajectory points: ",traj_fact.Nb_pts)

        if (traj_fact.initial_condition == None):
            traj_fact.initial_condition = source.choose_initial_contidion_automatic()

        print("Number of trajectory points: ",traj_fact.Nb_pts,traj_fact.initial_condition)
        #print('step 2')

        rad_fact = RadiationFactory(method=RADIATION_METHOD_NEAR_FIELD, photon_frequency=omega)


        #print('step 3')
        trajectory = traj_fact.create_from_source(source=source)


        #print('step 4')
        radiation = rad_fact.create_for_one_relativistic_electron(trajectory=trajectory, source=source,
                            XY_are_list=False,distance=beamline['distance'], X=X, Y=Y)

        efield = rad_fact.calculate_electrical_field(trajectory=trajectory,source=source,
                            distance=beamline['distance'],X_array=XX,Y_array=YY)

        tmp = efield.electrical_field()[:,:,0]


        wf_fft.set_photon_energy(resonance_energy)
        wf_convolution.set_photon_energy(resonance_energy)
        if SRWLIB_AVAILABLE: wf_srw.set_photon_energy(resonance_energy)

        wf_fft.set_complex_amplitude( tmp )
        wf_convolution.set_complex_amplitude( numpy.sqrt(tmp) )
        if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( numpy.sqrt(tmp) )

        # plot

        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),title="UND source at lens plane",show=1)

        # apply lens

        focal_length = propagation_distance / 2

        wf_fft.apply_ideal_lens(focal_length,focal_length)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)
        if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length)

    else:
        raise Exception("Unknown mode")


    plot_image(wf_fft.get_phase(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
               title="Phase just after the lens",xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),show=1)

    wf_fft, x_fft, y_fft = propagation_to_image(wf_fft,do_plot=0,method='fft',
                            propagation_steps=propagation_steps,
                            propagation_distance = propagation_distance, defocus_factor=defocus_factor)

    wf_convolution, x_convolution, y_convolution = propagation_to_image(wf_convolution,do_plot=0,method='convolution',
                            propagation_steps=propagation_steps,
                            propagation_distance = propagation_distance, defocus_factor=defocus_factor)
    if SRWLIB_AVAILABLE:
        wf_srw, x_srw, y_srw = propagation_to_image(wf_srw,do_plot=0,method='srw',
                                propagation_steps=propagation_steps,
                                propagation_distance = propagation_distance, defocus_factor=defocus_factor)

    plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
               title="Intensity at image plane",xtitle="X um (%d pixels)"%(wf_fft.size()[0]),ytitle="Y um (%d pixels)"%(wf_fft.size()[0]),show=1)

    if do_plot:
        if SRWLIB_AVAILABLE:
            x = x_fft
            y = numpy.vstack((y_fft,y_srw,y_convolution))

            plot_table(1e6*x,y,legend=["fft","srw","convolution"],ytitle="Intensity",xtitle="x coordinate [um]",
                       title="Comparison 1:1 focusing "+mode_wavefront_before_lens)
        else:
            x = x_fft
            y = numpy.vstack((y_fft,y_convolution))

            plot_table(1e6*x,y,legend=["fft","convolution"],ytitle="Intensity",xtitle="x coordinate [um]",
                       title="Comparison 1:1 focusing "+mode_wavefront_before_lens)
Beispiel #20
0
def propagate_2D(calculation_parameters, input_parameters):
    shadow_oe = calculation_parameters.shadow_oe_end

    if calculation_parameters.do_ff_z and calculation_parameters.do_ff_x:
        global_phase_shift_profile = None

        if shadow_oe._oe.F_MOVE == 1 and shadow_oe._oe.X_ROT != 0.0:
            if input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4:
                global_phase_shift_profile = calculation_parameters.w_mirr_2D_values
            elif input_parameters.ghy_calcType == 2:
                global_phase_shift_profile = ScaledMatrix.initialize_from_range(numpy.zeros((3, 3)),
                                                                                shadow_oe._oe.RWIDX2, shadow_oe._oe.RWIDX1,
                                                                                shadow_oe._oe.RLEN2,  shadow_oe._oe.RLEN1)

            for x_index in range(global_phase_shift_profile.size_x()):
                global_phase_shift_profile.z_values[x_index, :] += global_phase_shift_profile.get_y_values()*numpy.sin(numpy.radians(-shadow_oe._oe.X_ROT))
        elif input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4:
            global_phase_shift_profile = calculation_parameters.w_mirr_2D_values

        # only tangential slopes
        if input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4:
            rms_slope = hy_findrmsslopefromheight(ScaledArray(np_array=global_phase_shift_profile.z_values[int(global_phase_shift_profile.size_x()/2), :],
                                                              scale=global_phase_shift_profile.get_y_values()))

            print("Using RMS slope = " + str(rms_slope))

        # ------------------------------------------
        # far field calculation
        # ------------------------------------------
        focallength_ff = calculate_focal_length_ff_2D(calculation_parameters.ghy_x_min,
                                                      calculation_parameters.ghy_x_max,
                                                      calculation_parameters.ghy_z_min,
                                                      calculation_parameters.ghy_z_max,
                                                      input_parameters.ghy_npeak,
                                                      calculation_parameters.gwavelength)

        if (input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4) and rms_slope != 0:
            focallength_ff = min(focallength_ff,(calculation_parameters.ghy_z_max-calculation_parameters.ghy_z_min) / 16 / rms_slope ) #xshi changed
        elif input_parameters.ghy_calcType == 2 and not global_phase_shift_profile is None:
            focallength_ff = min(focallength_ff, input_parameters.ghy_distance*4) #TODO: PATCH to be found with a formula

        print("FF: calculated focal length: " + str(focallength_ff))

        fftsize_x = int(calculate_fft_size(calculation_parameters.ghy_x_min,
                                           calculation_parameters.ghy_x_max,
                                           calculation_parameters.gwavelength,
                                           focallength_ff,
                                           input_parameters.ghy_fftnpts,
                                           factor=20))

        fftsize_z = int(calculate_fft_size(calculation_parameters.ghy_z_min,
                                        calculation_parameters.ghy_z_max,
                                        calculation_parameters.gwavelength,
                                        focallength_ff,
                                        input_parameters.ghy_fftnpts,
                                        factor=20))

        print("FF: creating plane wave begin, fftsize_x = " +  str(fftsize_x) + ", fftsize_z = " +  str(fftsize_z))

        wavefront = Wavefront2D.initialize_wavefront_from_range(wavelength=calculation_parameters.gwavelength,
                                                                number_of_points=(fftsize_x, fftsize_z),
                                                                x_min=calculation_parameters.ghy_x_min,
                                                                x_max=calculation_parameters.ghy_x_max,
                                                                y_min=calculation_parameters.ghy_z_min,
                                                                y_max=calculation_parameters.ghy_z_max)

        try:
            for i in range(0, len(wavefront.electric_field_array.x_coord)):
                for j in range(0, len(wavefront.electric_field_array.y_coord)):
                    interpolated = calculation_parameters.wIray_2d.interpolate_value(wavefront.electric_field_array.x_coord[i],
                                                                                     wavefront.electric_field_array.y_coord[j])
                    wavefront.electric_field_array.set_z_value(i, j, numpy.sqrt(0.0 if interpolated < 0 else interpolated))
        except IndexError:
            raise Exception("Unexpected Error during interpolation: try reduce Number of bins for I(Tangential) histogram")

        wavefront.apply_ideal_lens(focallength_ff, focallength_ff)

        shadow_oe = calculation_parameters.shadow_oe_end

        if input_parameters.ghy_calcType == 3 or \
                (input_parameters.ghy_calcType == 2 and not global_phase_shift_profile is None):
            print("FF: calculating phase shift due to Height Error Profile")

            phase_shifts = numpy.zeros(wavefront.size())

            for index in range(0, phase_shifts.shape[0]):
                np_array = numpy.zeros(global_phase_shift_profile.shape()[1])
                for j in range(0, len(np_array)):
                    np_array[j] = global_phase_shift_profile.interpolate_value(wavefront.get_coordinate_x()[index], calculation_parameters.w_mirr_2D_values.get_y_value(j))

                global_phase_shift_profile_z = ScaledArray.initialize_from_steps(np_array,
                                                                                 global_phase_shift_profile.y_coord[0],
                                                                                 global_phase_shift_profile.y_coord[1] - global_phase_shift_profile.y_coord[0])

                phase_shifts[index, :] = get_mirror_phase_shift(wavefront.get_coordinate_y(),
                                                                calculation_parameters.gwavelength,
                                                                calculation_parameters.wangle_z,
                                                                calculation_parameters.wl_z,
                                                                global_phase_shift_profile_z)
            wavefront.add_phase_shifts(phase_shifts)
        elif input_parameters.ghy_calcType == 4:
            print("FF: calculating phase shift due to Height Error Profile")

            phase_shifts = numpy.zeros(wavefront.size())

            for index in range(0, phase_shifts.shape[0]):
                global_phase_shift_profile_z = ScaledArray.initialize_from_steps(global_phase_shift_profile.z_values[index, :],
                                                                                 global_phase_shift_profile.y_coord[0],
                                                                                 global_phase_shift_profile.y_coord[1] - global_phase_shift_profile.y_coord[0])

                phase_shifts[index, :] = get_grating_phase_shift(wavefront.get_coordinate_y(),
                                                                 calculation_parameters.gwavelength,
                                                                 calculation_parameters.wangle_z,
                                                                 calculation_parameters.wangle_ref_z,
                                                                 calculation_parameters.wl_z,
                                                                 global_phase_shift_profile_z)
            wavefront.add_phase_shifts(phase_shifts)
        elif input_parameters.ghy_calcType == 6:
            for w_mirr_2D_values in calculation_parameters.w_mirr_2D_values:
                phase_shift = get_crl_phase_shift(w_mirr_2D_values,
                                                  input_parameters,
                                                  calculation_parameters,
                                                  [wavefront.get_coordinate_x(), wavefront.get_coordinate_y()])

                wavefront.add_phase_shift(phase_shift)

        print("calculated plane wave: begin FF propagation (distance = " +  str(focallength_ff) + ")")

        propagated_wavefront = propagator2D.propagate_2D_fresnel(wavefront, focallength_ff)

        print("dif_zp: begin calculation")

        imagesize_x = min(abs(calculation_parameters.ghy_x_max), abs(calculation_parameters.ghy_x_min)) * 2
        imagesize_x = min(imagesize_x,
                          input_parameters.ghy_npeak*2*0.88*calculation_parameters.gwavelength*focallength_ff/abs(calculation_parameters.ghy_x_max-calculation_parameters.ghy_x_min))

        # TODO: this is a patch: to be rewritten
        if shadow_oe._oe.F_MOVE==1 and not shadow_oe._oe.Y_ROT==0:
            imagesize_x = max(imagesize_x, 8*(focallength_ff*numpy.tan(numpy.radians(numpy.abs(shadow_oe._oe.Y_ROT))) + numpy.abs(shadow_oe._oe.OFFX)))

        delta_x = propagated_wavefront.delta()[0]
        imagenpts_x = int(round(imagesize_x/delta_x/2) * 2 + 1)

        imagesize_z = min(abs(calculation_parameters.ghy_z_max), abs(calculation_parameters.ghy_z_min)) * 2
        imagesize_z = min(imagesize_z,
                          input_parameters.ghy_npeak*2*0.88*calculation_parameters.gwavelength*focallength_ff/abs(calculation_parameters.ghy_z_max-calculation_parameters.ghy_z_min))

        # TODO: this is a patch: to be rewritten
        if shadow_oe._oe.F_MOVE==1 and not shadow_oe._oe.X_ROT==0:
            imagesize_z = max(imagesize_z, 8*(focallength_ff*numpy.tan(numpy.radians(numpy.abs(shadow_oe._oe.X_ROT))) + numpy.abs(shadow_oe._oe.OFFZ)))

        delta_z = propagated_wavefront.delta()[1]
        imagenpts_z = int(round(imagesize_z/delta_z/2) * 2 + 1)

        dif_xpzp = ScaledMatrix.initialize_from_range(numpy.ones((imagenpts_x, imagenpts_z)),
                                                      min_scale_value_x = -(imagenpts_x - 1) / 2 * delta_x,
                                                      max_scale_value_x =(imagenpts_x - 1) / 2 * delta_x,
                                                      min_scale_value_y = -(imagenpts_z - 1) / 2 * delta_z,
                                                      max_scale_value_y =(imagenpts_z - 1) / 2 * delta_z)

        for i in range(0, dif_xpzp.shape()[0]):
            for j in range(0, dif_xpzp.shape()[1]):
                dif_xpzp.set_z_value(i, j, numpy.absolute(propagated_wavefront.get_interpolated_complex_amplitude(
                                                               dif_xpzp.x_coord[i],
                                                               dif_xpzp.y_coord[j]))**2
                                                           )

        dif_xpzp.set_scale_from_range(0,
                                      -(imagenpts_x - 1) / 2 * delta_x / focallength_ff,
                                      (imagenpts_x - 1) / 2 * delta_x / focallength_ff)

        dif_xpzp.set_scale_from_range(1,
                                      -(imagenpts_z - 1) / 2 * delta_z / focallength_ff,
                                      (imagenpts_z - 1) / 2 * delta_z / focallength_ff)

        calculation_parameters.dif_xpzp = dif_xpzp
def main(mode_wavefront_before_lens):

    lens_diameter = 0.002 # 0.001 # 0.002

    if mode_wavefront_before_lens == 'Undulator with lens':
        npixels_x = 512
    else:
        npixels_x = 2048*1.5

    pixelsize_x = lens_diameter / npixels_x
    print("pixelsize: ",pixelsize_x)


    pixelsize_y = pixelsize_x
    npixels_y = npixels_x

    wavelength = 1.24e-10
    propagation_distance = 30.0
    defocus_factor = 1.0 # 1.0 is at focus
    propagation_steps = 1

    # for Gaussian source
    sigma_x = lens_diameter / 400 # 5e-6
    sigma_y = sigma_x # 5e-6
    # for Hermite-Gauss, the H and V mode index (start from 0)
    hm = 3
    hn = 1

    #
    # initialize wavefronts of dimension equal to the lens
    #
    wf_fft = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                     y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                     number_of_points=(npixels_x,npixels_y),wavelength=wavelength)

    wf_convolution = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                     y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                     number_of_points=(npixels_x,npixels_y),wavelength=wavelength)
    if SRWLIB_AVAILABLE:
        wf_srw = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                     y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                     number_of_points=(npixels_x,npixels_y),wavelength=wavelength)

    #
    # calculate/define wavefront at zero distance downstream the lens
    #
    if mode_wavefront_before_lens == 'convergent spherical':
        # no need to propagate nor define lens
        wf_fft.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance)
        wf_convolution.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance)
        if SRWLIB_AVAILABLE: wf_srw.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance)

    elif mode_wavefront_before_lens == 'divergent spherical with lens':
        # define wavefront at zero distance upstream the lens and apply lens
        focal_length = propagation_distance / 2.

        wf_fft.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance)
        wf_fft.apply_ideal_lens(focal_length,focal_length)

        wf_convolution.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)

        if SRWLIB_AVAILABLE:
            wf_srw.set_spherical_wave(complex_amplitude=1.0,radius=propagation_distance)
            wf_srw.apply_ideal_lens(focal_length,focal_length)

    elif mode_wavefront_before_lens == 'plane with lens':
        # define wavefront at zero distance upstream the lens and apply lens
        focal_length = propagation_distance

        wf_fft.set_plane_wave_from_complex_amplitude(1.0+0j)
        wf_fft.apply_ideal_lens(focal_length,focal_length)

        wf_convolution.set_plane_wave_from_complex_amplitude(1.0+0j)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)

        if SRWLIB_AVAILABLE:
            wf_srw.set_plane_wave_from_complex_amplitude(1.0+0j)
            wf_srw.apply_ideal_lens(focal_length,focal_length)

    elif mode_wavefront_before_lens == 'Gaussian with lens':
        # define wavefront at source point, propagate to the lens and apply lens
        X = wf_fft.get_mesh_x()
        Y = wf_fft.get_mesh_y()

        intensity = numpy.exp( - X**2/(2*sigma_x**2)) * numpy.exp( - Y**2/(2*sigma_y**2))


        wf_fft.set_complex_amplitude( numpy.sqrt(intensity) )
        wf_convolution.set_complex_amplitude( numpy.sqrt(intensity) )
        if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( numpy.sqrt(intensity) )

        # plot

        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um",ytitle="Y um",title="Gaussian source",show=1)

        wf_fft, tmp1, tmp2 = propagation_to_image(wf_fft,method='fft',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")
        wf_convolution, tmp1, tmp2 = propagation_to_image(wf_convolution,method='convolution',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")
        if SRWLIB_AVAILABLE:
            wf_srw, tmp1, tmp2 = propagation_to_image(wf_srw,method='srw',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")


        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um",ytitle="Y um",title="Before lens fft",show=1)

        plot_image(wf_convolution.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um",ytitle="Y um",title="Before lens convolution",show=1)

        focal_length = propagation_distance / 2

        wf_fft.apply_ideal_lens(focal_length,focal_length)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)
        if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length)

    elif mode_wavefront_before_lens == 'Hermite with lens':
        # define wavefront at source point, propagate to the lens and apply lens
        X = wf_fft.get_mesh_x()
        Y = wf_fft.get_mesh_y()

        efield =     (hermite(hm)(numpy.sqrt(2)*X/sigma_x)*numpy.exp(-X**2/sigma_x**2))**2 \
                   * (hermite(hn)(numpy.sqrt(2)*Y/sigma_y)*numpy.exp(-Y**2/sigma_y**2))**2

        wf_fft.set_complex_amplitude( efield )
        wf_convolution.set_complex_amplitude( efield )
        if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( efield )

        # plot

        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um",ytitle="Y um",title="Hermite-Gauss source",show=1)

        wf_fft, tmp1, tmp2 = propagation_to_image(wf_fft,method='fft',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")
        wf_convolution, tmp1, tmp2 = propagation_to_image(wf_convolution,method='convolution',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")
        if SRWLIB_AVAILABLE:
            wf_srw, tmp1, tmp2 = propagation_to_image(wf_srw,method='srw',propagation_distance=propagation_distance,
                                              do_plot=0,plot_title="Before lens")


        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um",ytitle="Y um",title="Before lens fft",show=1)

        plot_image(wf_convolution.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um",ytitle="Y um",title="Before lens convolution",show=1)

        focal_length = propagation_distance / 2

        wf_fft.apply_ideal_lens(focal_length,focal_length)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)
        if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length)

    elif mode_wavefront_before_lens == 'Undulator with lens':

        beamline = {}
        # beamline['name'] = "ESRF_NEW_OB"
        # beamline['ElectronBeamDivergenceH'] = 5.2e-6    # these values are not used (zero emittance)
        # beamline['ElectronBeamDivergenceV'] = 1.4e-6    # these values are not used (zero emittance)
        # beamline['ElectronBeamSizeH'] = 27.2e-6         # these values are not used (zero emittance)
        # beamline['ElectronBeamSizeV'] = 3.4e-6          # these values are not used (zero emittance)
        # beamline['ElectronEnergySpread'] = 0.001        # these values are not used (zero emittance)
        beamline['ElectronCurrent'] = 0.2
        beamline['ElectronEnergy']  = 6.0
        beamline['Kv']              = 1.68  # 1.87
        beamline['NPeriods']        = 111   # 14
        beamline['PeriodID']        = 0.018 # 0.035
        beamline['distance']        =   propagation_distance
        # beamline['gapH']      = pixelsize_x*npixels_x
        # beamline['gapV']      = pixelsize_x*npixels_x

        gamma = beamline['ElectronEnergy'] / (codata_mee * 1e-3)
        print ("Gamma: %f \n"%(gamma))

        resonance_wavelength = (1 + beamline['Kv']**2 / 2.0) / 2 / gamma**2 * beamline["PeriodID"]
        resonance_energy = m2ev / resonance_wavelength



        print ("Resonance wavelength [A]: %g \n"%(1e10*resonance_wavelength))
        print ("Resonance energy [eV]: %g \n"%(resonance_energy))

        # red shift 100 eV
        resonance_energy = resonance_energy - 100


        myBeam = ElectronBeam(Electron_energy=beamline['ElectronEnergy'], I_current=beamline['ElectronCurrent'])
        myUndulator = MagneticStructureUndulatorPlane(K=beamline['Kv'], period_length=beamline['PeriodID'],
                            length=beamline['PeriodID']*beamline['NPeriods'])


        XX = wf_fft.get_mesh_x()
        YY = wf_fft.get_mesh_y()
        X = wf_fft.get_coordinate_x()
        Y = wf_fft.get_coordinate_y()

        source = SourceUndulatorPlane(undulator=myUndulator,
                            electron_beam=myBeam, magnetic_field=None)
        omega = resonance_energy * codata.e / codata.hbar
        Nb_pts_trajectory = int(source.choose_nb_pts_trajectory(0.01,photon_frequency=omega))
        print("Number of trajectory points: ",Nb_pts_trajectory)


        traj_fact = TrajectoryFactory(Nb_pts=Nb_pts_trajectory,method=TRAJECTORY_METHOD_ODE,
                                      initial_condition=None)

        print("Number of trajectory points: ",traj_fact.Nb_pts)

        if (traj_fact.initial_condition == None):
            traj_fact.initial_condition = source.choose_initial_contidion_automatic()

        print("Number of trajectory points: ",traj_fact.Nb_pts,traj_fact.initial_condition)
        #print('step 2')

        rad_fact = RadiationFactory(method=RADIATION_METHOD_NEAR_FIELD, photon_frequency=omega)


        #print('step 3')
        trajectory = traj_fact.create_from_source(source=source)


        #print('step 4')
        radiation = rad_fact.create_for_one_relativistic_electron(trajectory=trajectory, source=source,
                            XY_are_list=False,distance=beamline['distance'], X=X, Y=Y)

        efield = rad_fact.calculate_electrical_field(trajectory=trajectory,source=source,
                            distance=beamline['distance'],X_array=XX,Y_array=YY)

        tmp = efield.electrical_field()[:,:,0]


        wf_fft.set_photon_energy(resonance_energy)
        wf_convolution.set_photon_energy(resonance_energy)
        if SRWLIB_AVAILABLE: wf_srw.set_photon_energy(resonance_energy)

        wf_fft.set_complex_amplitude( tmp )
        wf_convolution.set_complex_amplitude( numpy.sqrt(tmp) )
        if SRWLIB_AVAILABLE: wf_srw.set_complex_amplitude( numpy.sqrt(tmp) )

        # plot

        plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
                   xtitle="X um",ytitle="Y um",title="UND source at lens plane",show=1)

        # apply lens

        focal_length = propagation_distance / 2

        wf_fft.apply_ideal_lens(focal_length,focal_length)
        wf_convolution.apply_ideal_lens(focal_length,focal_length)
        if SRWLIB_AVAILABLE: wf_srw.apply_ideal_lens(focal_length,focal_length)

    else:
        raise Exception("Unknown mode")


    plot_image(wf_fft.get_phase(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
               title="Phase just after the lens",xtitle="X um",ytitle="Y um",show=1)

    wf_fft, x_fft, y_fft = propagation_to_image(wf_fft,do_plot=0,method='fft',
                            propagation_steps=propagation_steps,
                            propagation_distance = propagation_distance, defocus_factor=defocus_factor)

    wf_convolution, x_convolution, y_convolution = propagation_to_image(wf_convolution,do_plot=0,method='convolution',
                            propagation_steps=propagation_steps,
                            propagation_distance = propagation_distance, defocus_factor=defocus_factor)
    if SRWLIB_AVAILABLE:
        wf_srw, x_srw, y_srw = propagation_to_image(wf_srw,do_plot=0,method='srw',
                                propagation_steps=propagation_steps,
                                propagation_distance = propagation_distance, defocus_factor=defocus_factor)

    plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
               title="Intensity at image plane",xtitle="X um",ytitle="Y um",show=1)

    if do_plot:
        if SRWLIB_AVAILABLE:
            x = x_fft
            y = numpy.vstack((y_fft,y_srw,y_convolution))

            plot_table(1e6*x,y,legend=["fft","srw","convolution"],ytitle="Intensity",xtitle="x coordinate [um]",
                       title="Comparison 1:1 focusing "+mode_wavefront_before_lens)
        else:
            x = x_fft
            y = numpy.vstack((y_fft,y_convolution))

            plot_table(1e6*x,y,legend=["fft","convolution"],ytitle="Intensity",xtitle="x coordinate [um]",
                       title="Comparison 1:1 focusing "+mode_wavefront_before_lens)
    def propagate_2D_fresnel(self,do_plot=do_plot,method='fft',
                                wavelength=1.24e-10,aperture_type='square',aperture_diameter=40e-6,
                                pixelsize_x=1e-6,pixelsize_y=1e-6,npixels_x=1024,npixels_y=1024,
                                propagation_distance = 30.0,show=1):


        method_label = "fresnel (%s)"%method
        print("\n#                                                             ")
        print("# 2D near field fresnel (%s) diffraction from a %s aperture  "%(method_label,aperture_type))
        print("#                                                             ")


        # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2,
        #                                                         x_step=pixelsize_x,
        #                                                         y_start=-pixelsize_y*npixels_y/2,
        #                                                         y_step=pixelsize_y,
        #                                                         wavelength=wavelength,
        #                                                         number_of_points=(npixels_x,npixels_y))

        wf = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                         y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                         number_of_points=(npixels_x,npixels_y),wavelength=wavelength)

        wf.set_plane_wave_from_complex_amplitude((1.0+0j))

        if aperture_type == 'circle':
            wf.apply_pinhole(aperture_diameter/2)
        elif aperture_type == 'square':
            wf.apply_slit(-aperture_diameter/2, aperture_diameter/2,-aperture_diameter/2, aperture_diameter/2)
        elif aperture_type == 'gaussian':
            X = wf.get_mesh_x()
            Y = wf.get_mesh_y()
            window = numpy.exp(- (X*X + Y*Y)/2/(aperture_diameter/2.35)**2)
            wf.rescale_amplitudes(window)
        else:
            raise Exception("Not implemented! (accepted: circle, square, gaussian)")


        if method == 'fft':
            wf1 = propagate_2D_fresnel(wf, propagation_distance)
        elif method == 'convolution':
            wf1 = propagate_2D_fresnel_convolution(wf, propagation_distance)
        elif method == 'srw':
            wf1 = propagate_2D_fresnel_srw(wf, propagation_distance)
        elif method == 'integral':
            wf1 = propagate_2D_integral(wf, propagation_distance)
        else:
            raise Exception("Not implemented method: %s"%method)


        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf.get_intensity(),1e6*wf.get_coordinate_x(),1e6*wf.get_coordinate_y(),
                       title="aperture intensity (%s), Diameter=%5.1f um"%
                             (aperture_type,1e6*aperture_diameter),xtitle="X [um]",ytitle="Y [um]",
                       show=0)

            plot_image(wf1.get_intensity(),
                       1e6*wf1.get_coordinate_x()/propagation_distance,
                       1e6*wf1.get_coordinate_y()/propagation_distance,
                       title="Diffracted intensity (%s) by a %s slit of aperture %3.1f um"%
                             (aperture_type,method_label,1e6*aperture_diameter),
                       xtitle="X [urad]",ytitle="Y [urad]",
                       show=0)

        # get the theoretical value
        angle_x = wf1.get_coordinate_x() / propagation_distance

        intensity_theory = get_theoretical_diffraction_pattern(angle_x,aperture_type=aperture_type,aperture_diameter=aperture_diameter,
                                            wavelength=wavelength,normalization=True)

        intensity_calculated =  wf1.get_intensity()[:,wf1.size()[1]/2]
        intensity_calculated /= intensity_calculated.max()

        if do_plot:
            from srxraylib.plot.gol import plot
            plot(wf1.get_coordinate_x()*1e6/propagation_distance,intensity_calculated,
                 angle_x*1e6,intensity_theory,
                 legend=["%s H profile"%method_label,"Theoretical (far field)"],
                 legend_position=(0.95, 0.95),
                 title="%s diffraction of a %s slit of %3.1f um at wavelength of %3.1f A"%
                       (method_label,aperture_type,aperture_diameter*1e6,wavelength*1e10),
                 xtitle="X (urad)", ytitle="Intensity",xrange=[-20,20],
                 show=show)

        return wf1.get_coordinate_x()/propagation_distance,intensity_calculated,angle_x,intensity_theory
Beispiel #23
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())
    def propagation_with_lens(self,do_plot=do_plot,method='fft',
                                wavelength=1.24e-10,
                                pixelsize_x=1e-6,npixels_x=2000,pixelsize_y=1e-6,npixels_y=2000,
                                propagation_distance=30.0,defocus_factor=1.0,propagation_steps=1,show=1):


        method_label = "fresnel (%s)"%method
        print("\n#                                                             ")
        print("# near field fresnel (%s) diffraction and focusing  "%(method_label))
        print("#                                                             ")

        #                               \ |  /
        #   *                           | | |                      *
        #                               / | \
        #   <-------    d  ---------------><---------   d   ------->
        #   d is propagation_distance

        # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2,
        #                                                         x_step=pixelsize_x,
        #                                                         y_start=-pixelsize_y*npixels_y/2,
        #                                                         y_step=pixelsize_y,
        #                                                         wavelength=wavelength,
        #                                                         number_of_points=(npixels_x,npixels_y))

        wf = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                         y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                         number_of_points=(npixels_x,npixels_y),wavelength=wavelength)

        spherical_or_plane_and_lens = 0
        if spherical_or_plane_and_lens == 0:
            # set spherical wave at the lens entrance (radius=distance)
            wf.set_spherical_wave(complex_amplitude=1.0,radius=-propagation_distance)
        else:
            # apply lens that will focus at propagation_distance downstream the lens.
            # Note that the vertical is a bit defocused
            wf.set_plane_wave_from_complex_amplitude(1.0+0j)
            focal_length = propagation_distance # / 2
            wf.apply_ideal_lens(focal_length,focal_length)

        print("Incident intensity: ",wf.get_intensity().sum())

        # propagation downstream the lens to image plane
        for i in range(propagation_steps):
            if propagation_steps > 1:
                print(">>> Propagating step %d of %d; propagation_distance=%g m"%(i+1,propagation_steps,
                                                    propagation_distance*defocus_factor/propagation_steps))
            if method == 'fft':
                wf = propagate_2D_fresnel(wf, propagation_distance*defocus_factor/propagation_steps)
            elif method == 'convolution':
                wf = propagate_2D_fresnel_convolution(wf, propagation_distance*defocus_factor/propagation_steps)
            elif method == 'srw':
                wf = propagate_2D_fresnel_srw(wf, propagation_distance*defocus_factor/propagation_steps)
            elif method == 'fraunhofer':
                wf = propagate_2D_fraunhofer(wf, propagation_distance*defocus_factor/propagation_steps)
            else:
                raise Exception("Not implemented method: %s"%method)




        horizontal_profile = wf.get_intensity()[:,wf.size()[1]/2]
        horizontal_profile /= horizontal_profile.max()
        print("FWHM of the horizontal profile: %g um"%(1e6*line_fwhm(horizontal_profile)*wf.delta()[0]))
        vertical_profile = wf.get_intensity()[wf.size()[0]/2,:]
        vertical_profile /= vertical_profile.max()
        print("FWHM of the vertical profile: %g um"%(1e6*line_fwhm(vertical_profile)*wf.delta()[1]))

        if do_plot:
            from srxraylib.plot.gol import plot,plot_image
            plot_image(wf.get_intensity(),wf.get_coordinate_x(),wf.get_coordinate_y(),title='intensity (%s)'%method,show=0)
            # plot_image(wf.get_amplitude(),wf.get_coordinate_x(),wf.get_coordinate_y(),title='amplitude (%s)'%method,show=0)
            plot_image(wf.get_phase(),wf.get_coordinate_x(),wf.get_coordinate_y(),title='phase (%s)'%method,show=0)

            plot(wf.get_coordinate_x(),horizontal_profile,
                 wf.get_coordinate_y(),vertical_profile,
                 legend=['Horizontal profile','Vertical profile'],title="%s"%method,show=show)

        print("Output intensity: ",wf.get_intensity().sum())
        return wf.get_coordinate_x(),horizontal_profile
Beispiel #25
0
    def test_plane_wave(self, do_plot=do_plot):
        #
        # plane wave
        #
        print("#                                                             ")
        print(
            "# Tests for a 2D plane wave                                      "
        )
        print("#                                                             ")

        wavelength = 1.24e-10

        wavefront_length_x = 400e-6
        wavefront_length_y = wavefront_length_x

        npixels_x = 1024
        npixels_y = npixels_x

        x = numpy.linspace(-0.5 * wavefront_length_x, 0.5 * wavefront_length_x,
                           npixels_x)
        y = numpy.linspace(-0.5 * wavefront_length_y, 0.5 * wavefront_length_y,
                           npixels_y)

        wavefront = Wavefront2D.initialize_wavefront_from_steps(
            x_start=x[0],
            x_step=numpy.abs(x[1] - x[0]),
            y_start=y[0],
            y_step=numpy.abs(y[1] - y[0]),
            number_of_points=(npixels_x, npixels_y),
            wavelength=wavelength)

        # possible modifications

        wavefront.set_plane_wave_from_amplitude_and_phase(5.0, numpy.pi / 2)
        numpy.testing.assert_almost_equal(wavefront.get_intensity(), 25, 5)

        wavefront.set_plane_wave_from_complex_amplitude(2.0 + 3j)
        numpy.testing.assert_almost_equal(wavefront.get_intensity(), 13, 5)

        phase_before = wavefront.get_phase()
        wavefront.add_phase_shift(numpy.pi / 2)
        phase_after = wavefront.get_phase()
        numpy.testing.assert_almost_equal(phase_before + numpy.pi / 2,
                                          phase_after, 5)

        intensity_before = wavefront.get_intensity()
        wavefront.rescale_amplitude(10.0)
        intensity_after = wavefront.get_intensity()
        numpy.testing.assert_almost_equal(intensity_before * 100,
                                          intensity_after, 5)

        # interpolation

        wavefront.set_plane_wave_from_complex_amplitude(2.0 + 3j)
        test_value1 = wavefront.get_interpolated_complex_amplitude(0.01, 1.3)
        self.assertAlmostEqual((2.0 + 3j).real, test_value1.real, 5)
        self.assertAlmostEqual((2.0 + 3j).imag, test_value1.imag, 5)

        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wavefront.get_intensity(),
                       wavefront.get_coordinate_x(),
                       wavefront.get_coordinate_y(),
                       title="Intensity (plane wave)",
                       show=0)
            plot_image(wavefront.get_phase(),
                       wavefront.get_coordinate_x(),
                       wavefront.get_coordinate_y(),
                       title="Phase (plane wave)",
                       show=1)
def main(beamline,pixels=100):

    npixels_x = pixels
    npixels_y = npixels_x


    pixelsize_x = beamline['gapH'] / npixels_x
    pixelsize_y = beamline['gapV'] / npixels_y

    print("pixelsize X=%f,Y=%f: "%(pixelsize_x,pixelsize_y))

    propagation_distance = beamline['distance']

    #
    # initialize wavefronts of dimension equal to the lens
    #
    wf_fft = Wavefront2D.initialize_wavefront_from_range(x_min=-pixelsize_x*npixels_x/2,x_max=pixelsize_x*npixels_x/2,
                                                     y_min=-pixelsize_y*npixels_y/2,y_max=pixelsize_y*npixels_y/2,
                                                     number_of_points=(npixels_x,npixels_y),wavelength=1e-10)


    gamma = beamline['ElectronEnergy'] / (codata_mee * 1e-3)
    print ("Gamma: %f \n"%(gamma))


    # photon_wavelength = (1 + beamline['Kv']**2 / 2.0) / 2 / gamma**2 * beamline["PeriodID"] / beamline['harmonicID']

    photon_wavelength = m2ev / beamline["photonEnergy"]


    print ("Photon wavelength [A]: %g \n"%(1e10*photon_wavelength))
    print ("Photon energy [eV]: %g \n"%(beamline["photonEnergy"]))


    myBeam = ElectronBeam(Electron_energy=beamline['ElectronEnergy'], I_current=beamline['ElectronCurrent'])
    myUndulator = MagneticStructureUndulatorPlane(K=beamline['Kv'], period_length=beamline['PeriodID'],
                        length=beamline['PeriodID']*beamline['NPeriods'])


    XX = wf_fft.get_mesh_x()
    YY = wf_fft.get_mesh_y()
    X = wf_fft.get_coordinate_x()
    Y = wf_fft.get_coordinate_y()

    source = SourceUndulatorPlane(undulator=myUndulator,
                        electron_beam=myBeam, magnetic_field=None)


    omega = beamline["photonEnergy"] * codata.e / codata.hbar
    Nb_pts_trajectory = int(source.choose_nb_pts_trajectory(0.01,photon_frequency=omega))
    print("Number of trajectory points: ",Nb_pts_trajectory)


    traj_fact = TrajectoryFactory(Nb_pts=Nb_pts_trajectory,method=TRAJECTORY_METHOD_ODE,
                                  initial_condition=None)

    print("Number of trajectory points: ",traj_fact.Nb_pts)

    if (traj_fact.initial_condition == None):
        traj_fact.initial_condition = source.choose_initial_contidion_automatic()

    print("Number of trajectory points: ",traj_fact.Nb_pts,traj_fact.initial_condition)
    #print('step 2')

    rad_fact = RadiationFactory(method=RADIATION_METHOD_NEAR_FIELD, photon_frequency=omega)


    #print('step 3')
    trajectory = traj_fact.create_from_source(source=source)


    #print('step 4')
    radiation = rad_fact.create_for_one_relativistic_electron(trajectory=trajectory, source=source,
                        XY_are_list=False,distance=beamline['distance'], X=X, Y=Y)

    efield = rad_fact.calculate_electrical_field(trajectory=trajectory,source=source,
                        distance=beamline['distance'],X_array=XX,Y_array=YY)

    tmp = efield.electrical_field()[:,:,0]


    wf_fft.set_photon_energy(beamline["photonEnergy"])

    wf_fft.set_complex_amplitude( tmp )

    # plot

    plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
               xtitle="X um",ytitle="Y um",title="UND source at lens plane",show=1)

    # apply lens

    focal_length = propagation_distance / 2

    wf_fft.apply_ideal_lens(focal_length,focal_length)



    plot_image(wf_fft.get_phase(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
               title="Phase just after the lens",xtitle="X um",ytitle="Y um",show=1)

    wf_fft, x_fft, y_fft = propagation_to_image(wf_fft,do_plot=0,method='fft',
                            propagation_steps=1,
                            propagation_distance = propagation_distance, defocus_factor=1.0)


    plot_image(wf_fft.get_intensity(),1e6*wf_fft.get_coordinate_x(),1e6*wf_fft.get_coordinate_y(),
               title="Intensity at image plane",xtitle="X um",ytitle="Y um",show=1)

    if do_plot:
        plot_table(1e6*x_fft,y_fft,ytitle="Intensity",xtitle="x coordinate [um]",
                   title="Comparison 1:1 focusing ")
Beispiel #27
0
    def test_interpolator(self, do_plot=do_plot):
        #
        # interpolator
        #
        print("#                                                             ")
        print("# Tests for 2D interpolator                                   ")
        print("#                                                             ")

        x = numpy.linspace(-10, 10, 100)
        y = numpy.linspace(-20, 20, 50)

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

        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)

        x1 = 3.2
        y1 = -2.5
        z1 = 3 * numpy.exp(-(x1**2 + y1**2) / 2 / sigma**2) + 4j
        print("complex ampl at (%g,%g): %g+%gi (exact=%g+%gi)" %
              (x1, y1, wf.get_interpolated_complex_amplitude(
                  x1, y1).real, wf.get_interpolated_complex_amplitude(
                      x1, y1).imag, z1.real, z1.imag))
        self.assertAlmostEqual(
            wf.get_interpolated_complex_amplitude(x1, y1).real, z1.real, 4)
        self.assertAlmostEqual(
            wf.get_interpolated_complex_amplitude(x1, y1).imag, z1.imag, 4)
        #
        print(
            "intensity  at (%g,%g):   %g (exact=%g)" %
            (x1, y1, wf.get_interpolated_intensity(x1, y1), numpy.abs(z1)**2))
        self.assertAlmostEqual(wf.get_interpolated_intensity(x1, y1),
                               numpy.abs(z1)**2, 4)

        # interpolate on same grid

        interpolated_complex_amplitude_on_same_grid = wf.get_interpolated_complex_amplitudes(
            X, Y)
        print("Shape interpolated at same grid: ",
              interpolated_complex_amplitude_on_same_grid.shape)

        numpy.testing.assert_array_almost_equal(
            wf.get_complex_amplitude(),
            interpolated_complex_amplitude_on_same_grid, 4)

        print(
            "Total intensity original wavefront: %g, interpolated on the same grid: %g"
            % (wf.get_intensity().sum(),
               (numpy.abs(interpolated_complex_amplitude_on_same_grid)**
                2).sum()))

        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf.get_intensity(),
                       wf.get_coordinate_x(),
                       wf.get_coordinate_y(),
                       title="Original",
                       show=0)
            plot_image(wf.get_interpolated_intensity(X, Y),
                       wf.get_coordinate_x(),
                       wf.get_coordinate_y(),
                       title="interpolated on same grid",
                       show=1)

        # rebin wavefront

        # wf.set_plane_wave_from_complex_amplitude(3+4j)
        wf_rebin = wf.rebin(2.0,
                            5.0,
                            0.5,
                            0.8,
                            keep_the_same_intensity=1,
                            set_extrapolation_to_zero=1)
        print("Shape before rebinning: ", wf.size())
        print("Shape after rebinning: ", wf_rebin.size())

        print("Total intensity original wavefront: %g, rebinned: %g" %
              (wf.get_intensity().sum(), wf_rebin.get_intensity().sum()))

        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf.get_intensity(),
                       wf.get_coordinate_x(),
                       wf.get_coordinate_y(),
                       title="BEFORE REBINNING",
                       show=0)
            plot_image(wf_rebin.get_intensity(),
                       wf_rebin.get_coordinate_x(),
                       wf_rebin.get_coordinate_y(),
                       title="REBINNED",
                       show=1)
Beispiel #28
0
    def test_spherical_wave(self, do_plot=do_plot):
        #
        # plane wave
        #
        print("#                                                             ")
        print("# Tests for a 2D spherical wave                               ")
        print("#                                                             ")

        wavelength = 1.24e-10

        wavefront_length_x = 400e-6
        wavefront_length_y = wavefront_length_x

        npixels_x = 1024
        npixels_y = npixels_x

        x = numpy.linspace(-0.5 * wavefront_length_x, 0.5 * wavefront_length_x,
                           npixels_x)
        y = numpy.linspace(-0.5 * wavefront_length_y, 0.5 * wavefront_length_y,
                           npixels_y)

        wf1 = Wavefront2D.initialize_wavefront_from_steps(
            x_start=x[0],
            x_step=numpy.abs(x[1] - x[0]),
            y_start=y[0],
            y_step=numpy.abs(y[1] - y[0]),
            number_of_points=(npixels_x, npixels_y),
            wavelength=wavelength)

        numpy.testing.assert_almost_equal(x, wf1.get_coordinate_x(), 9)
        numpy.testing.assert_almost_equal(y, wf1.get_coordinate_y(), 9)

        wf2 = Wavefront2D.initialize_wavefront_from_steps(
            x_start=x[0],
            x_step=numpy.abs(x[1] - x[0]),
            y_start=y[0],
            y_step=numpy.abs(y[1] - y[0]),
            number_of_points=(npixels_x, npixels_y),
            wavelength=wavelength)

        numpy.testing.assert_almost_equal(x, wf2.get_coordinate_x(), 9)
        numpy.testing.assert_almost_equal(y, wf2.get_coordinate_y(), 9)
        # an spherical wavefront is obtained 1) by creation, 2) focusing a planewave

        wf1.set_spherical_wave(-5.0, 3 + 0j)
        wf1.apply_slit(-50e-6, 10e-6, -20e-6, 40e-6)

        wf2.set_plane_wave_from_complex_amplitude(3 + 0j)
        wf2.apply_ideal_lens(5.0, 5.0)
        wf2.apply_slit(-50e-6, 10e-6, -20e-6, 40e-6)

        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf1.get_phase(),
                       wf2.get_coordinate_x(),
                       wf2.get_coordinate_y(),
                       title="Phase of spherical wavefront",
                       show=0)
            plot_image(wf2.get_phase(),
                       wf2.get_coordinate_x(),
                       wf2.get_coordinate_y(),
                       title="Phase of focused plane wavefront",
                       show=0)
            plot_image(
                wf1.get_phase(from_minimum_intensity=0.1),
                wf2.get_coordinate_x(),
                wf2.get_coordinate_y(),
                title="Phase of spherical wavefront (for intensity > 0.1)",
                show=0)
            plot_image(
                wf2.get_phase(from_minimum_intensity=0.1),
                wf2.get_coordinate_x(),
                wf2.get_coordinate_y(),
                title="Phase of focused plane wavefront (for intensity > 0.1)",
                show=1)

        numpy.testing.assert_almost_equal(wf1.get_phase(), wf2.get_phase(), 5)
Beispiel #29
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
Beispiel #30
0
    def propagation_with_lens(self,
                              do_plot=do_plot,
                              method='fft',
                              wavelength=1.24e-10,
                              pixelsize_x=1e-6,
                              npixels_x=2000,
                              pixelsize_y=1e-6,
                              npixels_y=2000,
                              propagation_distance=30.0,
                              defocus_factor=1.0,
                              propagation_steps=1,
                              show=1):

        method_label = "fresnel (%s)" % method
        print(
            "\n#                                                             ")
        print("# near field fresnel (%s) diffraction and focusing  " %
              (method_label))
        print("#                                                             ")

        #                              \  |  /
        #   *                           | | |                      *
        #                              /  |  \
        #   <-------    d  ---------------><---------   d   ------->
        #   d is propagation_distance

        # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2,
        #                                                         x_step=pixelsize_x,
        #                                                         y_start=-pixelsize_y*npixels_y/2,
        #                                                         y_step=pixelsize_y,
        #                                                         wavelength=wavelength,
        #                                                         number_of_points=(npixels_x,npixels_y))

        wf = Wavefront2D.initialize_wavefront_from_range(
            x_min=-pixelsize_x * npixels_x / 2,
            x_max=pixelsize_x * npixels_x / 2,
            y_min=-pixelsize_y * npixels_y / 2,
            y_max=pixelsize_y * npixels_y / 2,
            number_of_points=(npixels_x, npixels_y),
            wavelength=wavelength)

        spherical_or_plane_and_lens = 0
        if spherical_or_plane_and_lens == 0:
            # set spherical wave at the lens entrance (radius=distance)
            wf.set_spherical_wave(complex_amplitude=1.0,
                                  radius=-propagation_distance)
        else:
            # apply lens that will focus at propagation_distance downstream the lens.
            # Note that the vertical is a bit defocused
            wf.set_plane_wave_from_complex_amplitude(1.0 + 0j)
            focal_length = propagation_distance  # / 2
            wf.apply_ideal_lens(focal_length, focal_length)

        print("Incident intensity: ", wf.get_intensity().sum())

        # propagation downstream the lens to image plane
        for i in range(propagation_steps):
            if propagation_steps > 1:
                print(
                    ">>> Propagating step %d of %d; propagation_distance=%g m"
                    % (i + 1, propagation_steps, propagation_distance *
                       defocus_factor / propagation_steps))
            if method == 'fft':
                wf = propagate_2D_fresnel(
                    wf,
                    propagation_distance * defocus_factor / propagation_steps)
            elif method == 'convolution':
                wf = propagate_2D_fresnel_convolution(
                    wf,
                    propagation_distance * defocus_factor / propagation_steps)
            elif method == 'srw':
                wf = propagate_2D_fresnel_srw(
                    wf,
                    propagation_distance * defocus_factor / propagation_steps)
            elif method == 'fraunhofer':
                wf = propagate_2D_fraunhofer(
                    wf,
                    propagation_distance * defocus_factor / propagation_steps)
            else:
                raise Exception("Not implemented method: %s" % method)

        horizontal_profile = wf.get_intensity()[:, int(wf.size()[1] / 2)]
        horizontal_profile /= horizontal_profile.max()
        print("FWHM of the horizontal profile: %g um" %
              (1e6 * line_fwhm(horizontal_profile) * wf.delta()[0]))
        vertical_profile = wf.get_intensity()[int(wf.size()[0] / 2), :]
        vertical_profile /= vertical_profile.max()
        print("FWHM of the vertical profile: %g um" %
              (1e6 * line_fwhm(vertical_profile) * wf.delta()[1]))

        if do_plot:
            from srxraylib.plot.gol import plot, plot_image
            plot_image(wf.get_intensity(),
                       wf.get_coordinate_x(),
                       wf.get_coordinate_y(),
                       title='intensity (%s)' % method,
                       show=0)
            # plot_image(wf.get_amplitude(),wf.get_coordinate_x(),wf.get_coordinate_y(),title='amplitude (%s)'%method,show=0)
            plot_image(wf.get_phase(),
                       wf.get_coordinate_x(),
                       wf.get_coordinate_y(),
                       title='phase (%s)' % method,
                       show=0)

            plot(wf.get_coordinate_x(),
                 horizontal_profile,
                 wf.get_coordinate_y(),
                 vertical_profile,
                 legend=['Horizontal profile', 'Vertical profile'],
                 title="%s" % method,
                 show=show)

        print("Output intensity: ", wf.get_intensity().sum())
        return wf.get_coordinate_x(), horizontal_profile
    def test_spherical_wave(self,do_plot=do_plot):
        #
        # plane wave
        #
        print("#                                                             ")
        print("# Tests for a 2D spherical wave                               ")
        print("#                                                             ")

        wavelength        = 1.24e-10

        wavefront_length_x = 400e-6
        wavefront_length_y = wavefront_length_x

        npixels_x =  1024
        npixels_y =  npixels_x

        x = numpy.linspace(-0.5*wavefront_length_x,0.5*wavefront_length_x,npixels_x)
        y = numpy.linspace(-0.5*wavefront_length_y,0.5*wavefront_length_y,npixels_y)



        wf1 = Wavefront2D.initialize_wavefront_from_steps(
                        x_start=x[0],x_step=numpy.abs(x[1]-x[0]),
                        y_start=y[0],y_step=numpy.abs(y[1]-y[0]),
                        number_of_points=(npixels_x,npixels_y),wavelength=wavelength)

        numpy.testing.assert_almost_equal(x,wf1.get_coordinate_x(),9)
        numpy.testing.assert_almost_equal(y,wf1.get_coordinate_y(),9)

        wf2 = Wavefront2D.initialize_wavefront_from_steps(
                        x_start=x[0],x_step=numpy.abs(x[1]-x[0]),
                        y_start=y[0],y_step=numpy.abs(y[1]-y[0]),
                        number_of_points=(npixels_x,npixels_y),wavelength=wavelength)


        numpy.testing.assert_almost_equal(x,wf2.get_coordinate_x(),9)
        numpy.testing.assert_almost_equal(y,wf2.get_coordinate_y(),9)
        # an spherical wavefront is obtained 1) by creation, 2) focusing a planewave

        wf1.set_spherical_wave(-5.0, 3+0j)
        wf1.apply_slit(-50e-6,10e-6,-20e-6,40e-6)

        wf2.set_plane_wave_from_complex_amplitude(3+0j)
        wf2.apply_ideal_lens(5.0,5.0)
        wf2.apply_slit(-50e-6,10e-6,-20e-6,40e-6)



        if do_plot:
            from srxraylib.plot.gol import plot_image
            plot_image(wf1.get_phase(),wf2.get_coordinate_x(),wf2.get_coordinate_y(),
                       title="Phase of spherical wavefront",show=0)
            plot_image(wf2.get_phase(),wf2.get_coordinate_x(),wf2.get_coordinate_y(),
                       title="Phase of focused plane wavefront",show=0)
            plot_image(wf1.get_phase(from_minimum_intensity=0.1),wf2.get_coordinate_x(),wf2.get_coordinate_y(),
                       title="Phase of spherical wavefront (for intensity > 0.1)",show=0)
            plot_image(wf2.get_phase(from_minimum_intensity=0.1),wf2.get_coordinate_x(),wf2.get_coordinate_y(),
                       title="Phase of focused plane wavefront (for intensity > 0.1)",show=1)


        numpy.testing.assert_almost_equal(wf1.get_phase(),wf2.get_phase(),5)
Beispiel #32
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
Beispiel #33
0
    def test_propagate_2D_fraunhofer(self,
                                     do_plot=do_plot,
                                     aperture_type='square',
                                     aperture_diameter=40e-6,
                                     pixelsize_x=1e-6,
                                     pixelsize_y=1e-6,
                                     npixels_x=1024,
                                     npixels_y=1024,
                                     wavelength=1.24e-10):
        """

        :param do_plot: 0=No plot, 1=Do plot
        :param aperture_type: 'circle' 'square' 'gaussian' (Gaussian sigma = aperture_diameter/2.35)
        :param aperture_diameter:
        :param pixelsize_x:
        :param pixelsize_y:
        :param npixels_x:
        :param npixels_y:
        :param wavelength:
        :return:
        """

        print(
            "\n#                                                            ")
        print(
            "# far field 2D (fraunhofer) diffraction from a square aperture  ")
        print("#                                                            ")

        method = "fraunhofer"

        print(
            "Fraunhoffer diffraction valid for distances > > a^2/lambda = %f m"
            % ((aperture_diameter / 2)**2 / wavelength))

        # wf = Wavefront2D.initialize_wavefront_from_steps(x_start=-pixelsize_x*npixels_x/2,
        #                                                         x_step=pixelsize_x,
        #                                                         y_start=-pixelsize_y*npixels_y/2,
        #                                                         y_step=pixelsize_y,
        #                                                         wavelength=wavelength,
        #                                                         number_of_points=(npixels_x,npixels_y))
        wf = Wavefront2D.initialize_wavefront_from_range(
            x_min=-pixelsize_x * npixels_x / 2,
            x_max=pixelsize_x * npixels_x / 2,
            y_min=-pixelsize_y * npixels_y / 2,
            y_max=pixelsize_y * npixels_y / 2,
            number_of_points=(npixels_x, npixels_y),
            wavelength=wavelength)

        wf.set_plane_wave_from_complex_amplitude((1.0 + 0j))

        if aperture_type == 'circle':
            wf.apply_pinhole(aperture_diameter / 2)
        elif aperture_type == 'square':
            wf.apply_slit(-aperture_diameter / 2, aperture_diameter / 2,
                          -aperture_diameter / 2, aperture_diameter / 2)
        elif aperture_type == 'gaussian':
            X = wf.get_mesh_x()
            Y = wf.get_mesh_y()
            window = numpy.exp(-(X * X + Y * Y) / 2 /
                               (aperture_diameter / 2.35)**2)
            wf.rescale_amplitudes(window)
        else:
            raise Exception(
                "Not implemented! (accepted: circle, square, gaussian)")

        wf1 = propagate_2D_fraunhofer(
            wf, propagation_distance=1.0
        )  # propagating at 1 m means the result is like in angles

        if do_plot:
            plot_image(wf.get_intensity(),
                       1e6 * wf.get_coordinate_x(),
                       1e6 * wf.get_coordinate_y(),
                       title="aperture intensity (%s), Diameter=%5.1f um" %
                       (aperture_type, 1e6 * aperture_diameter),
                       xtitle="X [um]",
                       ytitle="Y [um]",
                       show=0)

            plot_image(
                wf1.get_intensity(),
                1e6 * wf1.get_coordinate_x(),
                1e6 * wf1.get_coordinate_y(),
                title=
                "2D Diffracted intensity (%s) by a %s slit of aperture %3.1f um"
                % (aperture_type, method, 1e6 * aperture_diameter),
                xtitle="X [urad]",
                ytitle="Y [urad]",
                show=0)

        angle_x = wf1.get_coordinate_x(
        )  # + 0.5*wf1.delta()[0] # shifted of half-pixel!!!
        intensity_theory = get_theoretical_diffraction_pattern(
            angle_x,
            aperture_type=aperture_type,
            aperture_diameter=aperture_diameter,
            wavelength=wavelength,
            normalization=True)

        intensity_calculated = wf1.get_intensity()[:, int(wf1.size()[1] / 2)]
        intensity_calculated /= intensity_calculated.max()

        if do_plot:
            plot(
                wf1.get_coordinate_x() * 1e6,
                intensity_calculated,
                angle_x * 1e6,
                intensity_theory,
                legend=["Calculated (FT) H profile", "Theoretical"],
                legend_position=(0.95, 0.95),
                title=
                "2D Fraunhofer Diffraction of a %s slit of %3.1f um at wavelength of %3.1f A"
                % (aperture_type, aperture_diameter * 1e6, wavelength * 1e10),
                xtitle="X (urad)",
                ytitle="Intensity",
                xrange=[-80, 80])

        numpy.testing.assert_almost_equal(intensity_calculated,
                                          intensity_theory, 1)
 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)
Beispiel #35
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)