コード例 #1
0
ファイル: propagator.py プロジェクト: lucarebuffi/SR-xraylib
def propagate_1D_fraunhofer(wavefront, propagation_distance=0.0, shift_half_pixel=1):
    """
    1D 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)
    :return: a new 1D wavefront object with propagated wavefront
    """

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

    # frequency for axis 1

    freq_nyquist = 0.5/wavefront.delta()
    freq_n = numpy.linspace(-1.0,1.0,wavefront.size())
    freq_x = freq_n * freq_nyquist
    freq_x *= wavefront.get_wavelength()


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

    if propagation_distance == 0:
        wf = Wavefront1D.initialize_wavefront_from_arrays(freq_x,fft2,wavelength=wavefront.get_wavelength())
        return wf
    else:
        wf = Wavefront1D.initialize_wavefront_from_arrays(freq_x*propagation_distance,fft2,wavelength=wavefront.get_wavelength())
        return wf
コード例 #2
0
    def test_initializers(self,do_plot=do_plot):

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

        x = numpy.linspace(-100,100,50)
        y = numpy.abs(x)**1.5 +  1j*numpy.abs(x)**1.8



        wf0 = Wavefront1D.initialize_wavefront_from_steps(x[0],numpy.abs(x[1]-x[0]),y.size)
        wf0.set_complex_amplitude(y)

        wf1 = Wavefront1D.initialize_wavefront_from_range(x[0],x[-1],y.size)
        wf1.set_complex_amplitude(y)

        wf2 = Wavefront1D.initialize_wavefront_from_arrays(x,y)

        print("wavefront sizes: ",wf1.size(),wf1.size(),wf2.size())

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

        numpy.testing.assert_almost_equal(wf0.get_intensity(),numpy.abs(y)**2,5)
        numpy.testing.assert_almost_equal(wf1.get_intensity(),numpy.abs(y)**2,5)

        numpy.testing.assert_almost_equal(x,wf1.get_abscissas(),11)
        numpy.testing.assert_almost_equal(x,wf2.get_abscissas(),11)
コード例 #3
0
    def test_spherical_wave(self, do_plot=do_plot):
        #
        # plane wave
        #
        print("#                                                             ")
        print("# Tests for a 1D spherical wave                               ")
        print("#                                                             ")

        wavelength = 1.24e-10

        wavefront_length_x = 400e-6

        npixels_x = 1024

        wavefront_x = numpy.linspace(-0.5 * wavefront_length_x,
                                     0.5 * wavefront_length_x, npixels_x)

        wf1 = Wavefront1D.initialize_wavefront_from_steps(
            x_start=wavefront_x[0],
            x_step=numpy.abs(wavefront_x[1] - wavefront_x[0]),
            number_of_points=npixels_x,
            wavelength=wavelength)

        wf2 = Wavefront1D.initialize_wavefront_from_steps(
            x_start=wavefront_x[0],
            x_step=numpy.abs(wavefront_x[1] - wavefront_x[0]),
            number_of_points=npixels_x,
            wavelength=wavelength)

        # 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)

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

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

        numpy.testing.assert_almost_equal(wf1.get_phase(), wf2.get_phase(), 5)
コード例 #4
0
    def propagate_1D(self,do_plot=do_plot,method='fft',
                                wavelength=1.24e-10,aperture_type='square',aperture_diameter=40e-6,
                                wavefront_length=100e-6,npoints=500,
                                propagation_distance = 30.0,show=1):


        print("\n#                                                            ")
        print("# far field 1D (fraunhofer) diffraction from a %s aperture  "%aperture_type)
        print("#                                                            ")

        wf = Wavefront1D.initialize_wavefront_from_range(x_min=-wavefront_length/2, x_max=wavefront_length/2,
                                                                number_of_points=npoints,wavelength=wavelength)

        wf.set_plane_wave_from_complex_amplitude((2.0+1.0j)) # an arbitraty value



        if aperture_type == 'square':
            wf.apply_slit(-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_1D_fresnel(wf, propagation_distance)
        elif method == 'convolution':
            wf1 = propagate_1D_fresnel_convolution(wf, propagation_distance)
        elif method == 'integral':
            wf1 = propagate_1D_integral(wf, propagation_distance)
        elif method == 'fraunhofer':
            wf1 = propagate_1D_fraunhofer(wf, propagation_distance)
        else:
            raise Exception("Not implemented method: %s"%method)

        # get the theoretical value
        angle_x = wf1.get_abscissas() / 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()
        intensity_calculated /= intensity_calculated.max()

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

        return wf1.get_abscissas()/propagation_distance,intensity_calculated,intensity_theory
コード例 #5
0
    def propagate_1D(self,do_plot=do_plot,method='fft',
                                wavelength=1.24e-10,aperture_type='square',aperture_diameter=40e-6,
                                wavefront_length=100e-6,npoints=500,
                                propagation_distance = 30.0,show=1):


        print("\n#                                                            ")
        print("# far field 1D (fraunhofer) diffraction from a %s aperture  "%aperture_type)
        print("#                                                            ")

        wf = Wavefront1D.initialize_wavefront_from_range(x_min=-wavefront_length/2, x_max=wavefront_length/2,
                                                                number_of_points=npoints,wavelength=wavelength)

        wf.set_plane_wave_from_complex_amplitude((2.0+1.0j)) # an arbitraty value



        if aperture_type == 'square':
            wf.apply_slit(-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_1D_fresnel(wf, propagation_distance)
        elif method == 'convolution':
            wf1 = propagate_1D_fresnel_convolution(wf, propagation_distance)
        elif method == 'integral':
            wf1 = propagate_1D_integral(wf, propagation_distance)
        elif method == 'fraunhofer':
            wf1 = propagate_1D_fraunhofer(wf, propagation_distance)
        else:
            raise Exception("Not implemented method: %s"%method)

        # get the theoretical value
        angle_x = wf1.get_abscissas() / 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()
        intensity_calculated /= intensity_calculated.max()

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

        return wf1.get_abscissas()/propagation_distance,intensity_calculated,intensity_theory
コード例 #6
0
ファイル: propagator.py プロジェクト: mkeilman/SR-xraylib
def propagate_1D_fresnel_radius(wavefront, propagation_distance, eta):
    """
    1D Fresnel propagator using convolution via Fourier transform
    :param wavefront:
    :param propagation_distance: propagation distance
    :return: a new 1D wavefront object with propagated wavefront
    """
    fft_scale = numpy.fft.fftfreq(wavefront.size()) / wavefront.delta()

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

    return Wavefront1D(
        wavefront.get_wavelength(),
        ScaledArray.initialize_from_steps(ifft, wavefront.offset(),
                                          wavefront.delta()))
コード例 #7
0
ファイル: propagator.py プロジェクト: mkeilman/SR-xraylib
def propagator1d_fourier_rescaling(wavefront, propagation_distance, m=1):

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

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

    x = wf.get_abscissas()

    x_rescaling = wf.get_abscissas() * m

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

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

    wf.add_phase_shift(Q1)

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

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

    return Wavefront1D(
        wf.get_wavelength(),
        ScaledArray.initialize_from_steps(ifft, m * wf.offset(),
                                          m * wf.delta()))
コード例 #8
0
    def schmidt(self, pixelsize, npixels, wavelength, m, propagation_distance):
        wavefront = Wavefront1D.initialize_wavefront_from_range(
            x_min=-pixelsize * npixels / 2,
            x_max=pixelsize * npixels / 2,
            number_of_points=npixels,
            wavelength=wavelength)

        # wavefront.set_spherical_wave(radius=radius)
        wavefront.set_plane_wave_from_amplitude_and_phase()

        wavefront.apply_slit(-1e-3, 1e-3)

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

        wavefront_propagated = propagator1d_fourier_rescaling(
            wavefront, propagation_distance=propagation_distance, m=m)

        print('Intensity after propagation: ',
              wavefront_propagated.get_intensity().sum())

        intensity_theory = fresnel_prop_square_aperture_analitical(
            x2=wavefront_propagated.get_abscissas(),
            y2=0,
            aperture_diameter=2e-3,
            wavelength=wavelength,
            propagation_distance=propagation_distance)

        return wavefront_propagated, intensity_theory
コード例 #9
0
    def test_spherical_wave(self,do_plot=do_plot):
        #
        # plane wave
        #
        print("#                                                             ")
        print("# Tests for a 1D spherical wave                               ")
        print("#                                                             ")

        wavelength        = 1.24e-10

        wavefront_length_x = 400e-6

        npixels_x =  1024

        wavefront_x = numpy.linspace(-0.5*wavefront_length_x,0.5*wavefront_length_x,npixels_x)



        wf1 = Wavefront1D.initialize_wavefront_from_steps(
                        x_start=wavefront_x[0],x_step=numpy.abs(wavefront_x[1]-wavefront_x[0]),
                        number_of_points=npixels_x,wavelength=wavelength)

        wf2 = Wavefront1D.initialize_wavefront_from_steps(
                        x_start=wavefront_x[0],x_step=numpy.abs(wavefront_x[1]-wavefront_x[0]),
                        number_of_points=npixels_x,wavelength=wavelength)

        # 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)

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



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


        numpy.testing.assert_almost_equal(wf1.get_phase(),wf2.get_phase(),5)
コード例 #10
0
    def test_initializers(self, do_plot=do_plot):

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

        x = numpy.linspace(-100, 100, 50)
        y = numpy.abs(x)**1.5 + 1j * numpy.abs(x)**1.8

        wf0 = Wavefront1D.initialize_wavefront_from_steps(
            x[0], numpy.abs(x[1] - x[0]), y.size)
        wf0.set_complex_amplitude(y)

        wf1 = Wavefront1D.initialize_wavefront_from_range(x[0], x[-1], y.size)
        wf1.set_complex_amplitude(y)

        wf2 = Wavefront1D.initialize_wavefront_from_arrays(x, y)

        print("wavefront sizes: ", wf1.size(), wf1.size(), wf2.size())

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

        numpy.testing.assert_almost_equal(wf0.get_intensity(),
                                          numpy.abs(y)**2, 5)
        numpy.testing.assert_almost_equal(wf1.get_intensity(),
                                          numpy.abs(y)**2, 5)

        numpy.testing.assert_almost_equal(x, wf1.get_abscissas(), 11)
        numpy.testing.assert_almost_equal(x, wf2.get_abscissas(), 11)
コード例 #11
0
ファイル: propagator.py プロジェクト: mkeilman/SR-xraylib
def propagate_1D_integral(wavefront,
                          propagation_distance,
                          detector_abscissas=[None],
                          method=0,
                          magnification=1.0,
                          npoints_exit=None):
    """
    1D Fresnel-Kirchhoff propagator via integral implemented as sum
    :param wavefront:
    :param propagation_distance: propagation distance
    :param detector_abscissas: a numpy array with the abscissas at the image position. If undefined ([None])
                            it uses the same abscissas present in input wavefront.
    :param method: 0 (default_ makes a loop over detector coordinates, 1: makes matrices (outer products) so
                            it is more memory hungry.
    :param magnification: if detector_abscissas is [None], the detector abscissas range is the input
                            wavefront range times this magnification factor. Default =1
    :param npoints_exit: if detector_abscissas is [None], the number of points of detector abscissas.
                            Default=None meaning that the same number of points than wavefront are used.
    :return: a new 1D wavefront object with propagated wavefront
    """

    if detector_abscissas[0] == None:

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

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

    return Wavefront1D(wavefront.get_wavelength(), ScaledArray.initialize_from_steps(fieldComplexAmplitude, \
                            detector_abscissas[0], detector_abscissas[1]-detector_abscissas[0] ))
コード例 #12
0
    def test_plane_wave(self,do_plot=do_plot):
        #
        # plane wave
        #
        print("#                                                             ")
        print("# Tests for a 1D plane wave                                   ")
        print("#                                                             ")

        wavelength        = 1.24e-10

        wavefront_length_x = 400e-6

        npixels_x =  1024

        wavefront_x = numpy.linspace(-0.5*wavefront_length_x,0.5*wavefront_length_x,npixels_x)


        wavefront = Wavefront1D.initialize_wavefront_from_steps(
                        x_start=wavefront_x[0],x_step=numpy.abs(wavefront_x[1]-wavefront_x[0]),
                        number_of_points=npixels_x,wavelength=wavelength)

        numpy.testing.assert_almost_equal(wavefront_x,wavefront.get_abscissas(),9)

        # 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)
        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
            plot(wavefront.get_abscissas(),wavefront.get_intensity(),title="Intensity (plane wave)",show=0)
            plot(wavefront.get_abscissas(),wavefront.get_phase(),title="Phase (plane wave)",show=1)
コード例 #13
0
ファイル: propagator.py プロジェクト: mkeilman/SR-xraylib
def propagate_1D_fraunhofer(
        wavefront,
        propagation_distance=0.0,
        shift_half_pixel=0):  # todo: modificato da giovanni
    """
    1D Fraunhofer propagator using convolution via Fourier transform
    :param shift_half_pixel:
    :param shift_half_pixel:
    :param wavefront:
    :param propagation_distance: propagation distance. If set to zero, the abscissas
                                 of the returned wavefront are in angle (rad)
    :return: a new 1D wavefront object with propagated wavefront
    """

    shape = wavefront.size()
    delta = wavefront.delta()
    wavenumber = wavefront.get_wavenumber()
    wavelength = wavefront.get_wavelength()
    fft_scale = numpy.fft.fftfreq(shape, d=delta)
    fft_scale = numpy.fft.fftshift(fft_scale)
    x2 = fft_scale * propagation_distance * wavelength

    # freq_nyquist = 0.5 / delta
    # freq_n = numpy.linspace(-1.0, 1.0, shape)
    # freq_x = freq_n * freq_nyquist
    # freq_x *= wavelength * propagation_distance
    # x2 = freq_x

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

    fft = numpy.fft.fft(wavefront.get_complex_amplitude())
    fft *= P1
    fft *= P2
    fft /= P3
    # fft *= P4
    fft2 = numpy.fft.fftshift(fft)

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

    return Wavefront1D.initialize_wavefront_from_arrays(
        x2, fft2, wavelength=wavefront.get_wavelength())
コード例 #14
0
    def test_interpolator(self, do_plot=do_plot):
        #
        # interpolator
        #
        print("#                                                             ")
        print("# Tests for 1D interpolator                                   ")
        print("#                                                             ")

        x = numpy.linspace(-10, 10, 100)

        sigma = 3.0
        Z = numpy.exp(-1.0 * x**2 / 2 / sigma**2)

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

        wf = Wavefront1D.initialize_wavefront_from_steps(x[0],
                                                         numpy.abs(x[1] -
                                                                   x[0]),
                                                         number_of_points=100)
        print("wf shape: ", wf.size())
        wf.set_complex_amplitude(Z)

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

        print("intensity  at (%g):   %g (exact=%g)" %
              (x1, wf.get_interpolated_intensity(x1), z1**2))
        self.assertAlmostEqual(wf.get_interpolated_intensity(x1), z1**2, 4)

        if do_plot:
            from srxraylib.plot.gol import plot
            plot(wf.get_abscissas(),
                 wf.get_intensity(),
                 title="Original",
                 show=1)
            xx = wf.get_abscissas()
            yy = wf.get_interpolated_intensities(wf.get_abscissas() - 1e-5)
            plot(xx, yy, title="interpolated on same grid", show=1)
コード例 #15
0
    def test_interpolator(self,do_plot=do_plot):
        #
        # interpolator
        #
        print("#                                                             ")
        print("# Tests for 1D interpolator                                   ")
        print("#                                                             ")

        x = numpy.linspace(-10,10,100)

        sigma = 3.0
        Z = numpy.exp(-1.0*x**2/2/sigma**2)

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

        wf = Wavefront1D.initialize_wavefront_from_steps(x[0],numpy.abs(x[1]-x[0]),number_of_points=100)
        print("wf shape: ",wf.size())
        wf.set_complex_amplitude( Z )

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

        print("intensity  at (%g):   %g (exact=%g)"%(x1,wf.get_interpolated_intensity(x1),z1**2))
        self.assertAlmostEqual(wf.get_interpolated_intensity(x1),z1**2,4)


        if do_plot:
            from srxraylib.plot.gol import plot
            plot(wf.get_abscissas(),wf.get_intensity(),title="Original",show=1)
            xx = wf.get_abscissas()
            yy = wf.get_interpolated_intensities(wf.get_abscissas()-1e-5)
            plot(xx,yy,title="interpolated on same grid",show=1)
コード例 #16
0
ファイル: propagator.py プロジェクト: mkeilman/SR-xraylib
def propagate_1D_fresnel_convolution(wavefront, propagation_distance):
    """
    1D Fresnel propagator using direct convolution
    :param wavefront:
    :param propagation_distance:
    :return:
    """

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

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

    return Wavefront1D(
        wavefront.get_wavelength(),
        ScaledArray.initialize_from_steps(tmp, wavefront.offset(),
                                          wavefront.delta()))
コード例 #17
0
def propagate_1D_x_direction(calculation_parameters, input_parameters):

    scale_factor = 1.0

    shadow_oe = calculation_parameters.shadow_oe_end

    global_phase_shift_profile = None

    if shadow_oe._oe.F_MOVE == 1 and shadow_oe._oe.Y_ROT != 0.0:
        if input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4:
            global_phase_shift_profile = calculation_parameters.w_mirror_lx
        elif input_parameters.ghy_calcType == 2:
            global_phase_shift_profile = ScaledArray.initialize_from_range(numpy.zeros(3), shadow_oe._oe.RWIDX2, shadow_oe._oe.RWIDX1)

        global_phase_shift_profile.set_values(global_phase_shift_profile.get_values() +
                                              global_phase_shift_profile.get_abscissas()*numpy.sin(numpy.radians(-shadow_oe._oe.Y_ROT)))
    elif input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4:
        global_phase_shift_profile = calculation_parameters.w_mirror_lx

    if input_parameters.ghy_calcType == 3 or input_parameters.ghy_calcType == 4:
        rms_slope = hy_findrmsslopefromheight(global_phase_shift_profile)

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

        average_incident_angle = numpy.radians(90-calculation_parameters.shadow_oe_end._oe.T_INCIDENCE)*1e3
        average_reflection_angle = numpy.radians(90-calculation_parameters.shadow_oe_end._oe.T_REFLECTION)*1e3

        if calculation_parameters.beam_not_cut_in_x:
            dp_image = numpy.std(calculation_parameters.xx_focal_ray)/input_parameters.ghy_focallength
            dp_se = 2 * rms_slope * numpy.sin(average_incident_angle/1e3)	# different in x and z
            dp_error = calculation_parameters.gwavelength/2/(calculation_parameters.ghy_x_max-calculation_parameters.ghy_x_min)

            scale_factor = max(1, 5*min(dp_error/dp_image, dp_error/dp_se))

    # ------------------------------------------
    # far field calculation
    # ------------------------------------------
    if calculation_parameters.do_ff_x:
        focallength_ff = calculate_focal_length_ff(calculation_parameters.ghy_x_min,
                                                   calculation_parameters.ghy_x_max,
                                                   input_parameters.ghy_npeak,
                                                   calculation_parameters.gwavelength)

        if input_parameters.ghy_calcType == 3:
            if not (rms_slope == 0.0 or average_incident_angle == 0.0):
                focallength_ff = min(focallength_ff,(calculation_parameters.ghy_x_max-calculation_parameters.ghy_x_min) / 16 / rms_slope / numpy.sin(average_incident_angle / 1e3))#xshi changed
        elif input_parameters.ghy_calcType == 4:
            if not (rms_slope == 0.0 or average_incident_angle == 0.0):
                focallength_ff = min(focallength_ff,(calculation_parameters.ghy_x_max-calculation_parameters.ghy_x_min) / 8 / rms_slope / (numpy.sin(average_incident_angle / 1e3) + numpy.sin(average_reflection_angle / 1e3)))#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

        fftsize = int(scale_factor * calculate_fft_size(calculation_parameters.ghy_x_min,
                                                        calculation_parameters.ghy_x_max,
                                                        calculation_parameters.gwavelength,
                                                        focallength_ff,
                                                        input_parameters.ghy_fftnpts))
        
        print("FF: creating plane wave begin, fftsize = " +  str(fftsize))

        wavefront = Wavefront1D.initialize_wavefront_from_range(wavelength=calculation_parameters.gwavelength,
                                                                number_of_points=fftsize,
                                                                x_min=scale_factor * calculation_parameters.ghy_x_min,
                                                                x_max=scale_factor * calculation_parameters.ghy_x_max)

        if scale_factor == 1.0:
            try:
                wavefront.set_plane_wave_from_complex_amplitude(numpy.sqrt(calculation_parameters.wIray_x.interpolate_values(wavefront.get_abscissas())))
            except IndexError:
                raise Exception("Unexpected Error during interpolation: try reduce Number of bins for I(Sagittal) histogram")

        wavefront.apply_ideal_lens(focallength_ff)

        if input_parameters.ghy_calcType == 3 or \
                (input_parameters.ghy_calcType == 2 and not global_phase_shift_profile is None):
           wavefront.add_phase_shifts(get_mirror_phase_shift(wavefront.get_abscissas(),
                                                             calculation_parameters.gwavelength,
                                                             calculation_parameters.wangle_x,
                                                             calculation_parameters.wl_x,
                                                             global_phase_shift_profile))
        elif input_parameters.ghy_calcType == 4:
           wavefront.add_phase_shifts(get_grating_phase_shift(wavefront.get_abscissas(),
                                                              calculation_parameters.gwavelength,
                                                              calculation_parameters.wangle_x,
                                                              calculation_parameters.wangle_ref_x,
                                                              calculation_parameters.wl_x,
                                                              global_phase_shift_profile))

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

        propagated_wavefront = propagator.propagate_1D_fresnel(wavefront, focallength_ff)

        print("dif_xp: begin calculation")

        shadow_oe = calculation_parameters.shadow_oe_end

        imagesize = min(abs(calculation_parameters.ghy_x_max), abs(calculation_parameters.ghy_x_min)) * 2
        # 2017-01 Luca Rebuffi
        imagesize = min(imagesize,
                        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 = max(imagesize, 8*(focallength_ff*numpy.tan(numpy.radians(numpy.abs(shadow_oe._oe.Y_ROT))) + numpy.abs(shadow_oe._oe.OFFX)))

        imagenpts = int(round(imagesize / propagated_wavefront.delta() / 2) * 2 + 1)

        dif_xp = ScaledArray.initialize_from_range(numpy.ones(propagated_wavefront.size()),
                                                   -(imagenpts - 1) / 2 * propagated_wavefront.delta(),
                                                   (imagenpts - 1) / 2 * propagated_wavefront.delta())


        dif_xp.np_array = numpy.absolute(propagated_wavefront.get_interpolated_complex_amplitudes(dif_xp.scale))**2

        dif_xp.set_scale_from_range(-(imagenpts - 1) / 2 * propagated_wavefront.delta() / focallength_ff,
                                    (imagenpts - 1) / 2 * propagated_wavefront.delta() / focallength_ff)

        calculation_parameters.dif_xp = dif_xp

    # ------------------------------------------
    # near field calculation
    # ------------------------------------------
    if input_parameters.ghy_nf >= 1 and input_parameters.ghy_calcType > 1:  # near field calculation
        focallength_nf = input_parameters.ghy_focallength

        fftsize = int(scale_factor * calculate_fft_size(calculation_parameters.ghy_x_min,
                                                        calculation_parameters.ghy_x_max,
                                                        calculation_parameters.gwavelength,
                                                        numpy.abs(focallength_nf),
                                                        input_parameters.ghy_fftnpts))

        print("NF: creating plane wave begin, fftsize = " +  str(fftsize))

        wavefront = Wavefront1D.initialize_wavefront_from_range(wavelength=calculation_parameters.gwavelength,
                                                                number_of_points=fftsize,
                                                                x_min=scale_factor*calculation_parameters.ghy_x_min,
                                                                x_max=scale_factor*calculation_parameters.ghy_x_max)

        if scale_factor == 1.0:
            try:
                wavefront.set_plane_wave_from_complex_amplitude(numpy.sqrt(calculation_parameters.wIray_x.interpolate_values(wavefront.get_abscissas())))
            except IndexError:
                raise Exception("Unexpected Error during interpolation: try reduce Number of bins for I(Sagittal) histogram")

        wavefront.apply_ideal_lens(focallength_nf)

        if input_parameters.ghy_calcType == 3 or \
                (input_parameters.ghy_calcType == 2 and not global_phase_shift_profile is None):
           wavefront.add_phase_shifts(get_mirror_phase_shift(wavefront.get_abscissas(),
                                                             calculation_parameters.gwavelength,
                                                             calculation_parameters.wangle_x,
                                                             calculation_parameters.wl_x,
                                                             global_phase_shift_profile))
        elif input_parameters.ghy_calcType == 4:
           wavefront.add_phase_shifts(get_grating_phase_shift(wavefront.get_abscissas(),
                                                              calculation_parameters.gwavelength,
                                                              calculation_parameters.wangle_x,
                                                              calculation_parameters.wangle_ref_x,
                                                              calculation_parameters.wl_x,
                                                              global_phase_shift_profile))

        print("calculated plane wave: begin NF propagation (distance = " + str(input_parameters.ghy_distance) + ")")

        propagated_wavefront = propagator.propagate_1D_fresnel(wavefront, input_parameters.ghy_distance)

        # ghy_npeak in the wavefront propagation image
        imagesize = (input_parameters.ghy_npeak * 2 * 0.88 * calculation_parameters.gwavelength * numpy.abs(focallength_nf) / abs(calculation_parameters.ghy_x_max - calculation_parameters.ghy_x_min))
        imagesize = max(imagesize,
                        2 * abs((calculation_parameters.ghy_x_max - calculation_parameters.ghy_x_min) * (input_parameters.ghy_distance - numpy.abs(focallength_nf))) / numpy.abs(focallength_nf))

        if input_parameters.ghy_calcType == 3:
            imagesize = max(imagesize,
                            16 * rms_slope * numpy.abs(focallength_nf) * numpy.sin(average_incident_angle / 1e3))
        elif input_parameters.ghy_calcType == 4:
            imagesize = max(imagesize,
                            8 * rms_slope * numpy.abs(focallength_nf) * (numpy.sin(average_incident_angle / 1e3) + numpy.sin(average_reflection_angle / 1e3)))

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

        imagenpts = int(round(imagesize / propagated_wavefront.delta() / 2) * 2 + 1)

        print("dif_x: begin calculation")

        dif_x = ScaledArray.initialize_from_range(numpy.ones(imagenpts),
                                                  -(imagenpts - 1) / 2 * propagated_wavefront.delta(),
                                                  (imagenpts - 1) / 2 * propagated_wavefront.delta())

        dif_x.np_array *= numpy.absolute(propagated_wavefront.get_interpolated_complex_amplitudes(dif_x.scale))**2

        calculation_parameters.dif_x = dif_x
コード例 #18
0
    def test_plane_wave(self, do_plot=do_plot):
        #
        # plane wave
        #
        print("#                                                             ")
        print("# Tests for a 1D plane wave                                   ")
        print("#                                                             ")

        wavelength = 1.24e-10

        wavefront_length_x = 400e-6

        npixels_x = 1024

        wavefront_x = numpy.linspace(-0.5 * wavefront_length_x,
                                     0.5 * wavefront_length_x, npixels_x)

        wavefront = Wavefront1D.initialize_wavefront_from_steps(
            x_start=wavefront_x[0],
            x_step=numpy.abs(wavefront_x[1] - wavefront_x[0]),
            number_of_points=npixels_x,
            wavelength=wavelength)

        numpy.testing.assert_almost_equal(wavefront_x,
                                          wavefront.get_abscissas(), 9)

        # 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)
        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
            plot(wavefront.get_abscissas(),
                 wavefront.get_intensity(),
                 title="Intensity (plane wave)",
                 show=0)
            plot(wavefront.get_abscissas(),
                 wavefront.get_phase(),
                 title="Phase (plane wave)",
                 show=1)