Beispiel #1
0
    def propagate_wavefront(cls,
                            wavefront1,
                            propagation_distance,
                            magnification_x=1.0):

        wavefront = wavefront1.duplicate()
        shape = wavefront.size()
        delta = wavefront.delta()
        wavenumber = wavefront.get_wavenumber()
        wavelength = wavefront.get_wavelength()

        fft_scale = numpy.fft.fftfreq(shape) / delta

        x = wavefront.get_abscissas()

        x_rescaling = wavefront.get_abscissas() * magnification_x

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

        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.fft(wavefront.get_complex_amplitude())
        ifft = numpy.fft.ifft(fft * Q2) * Q3 / numpy.sqrt(magnification_x)

        wf_propagated = GenericWavefront1D.initialize_wavefront_from_arrays(
            x_rescaling, ifft, wavelength=wavelength)

        return wf_propagated
Beispiel #2
0
    def propagate_wavefront(cls,
                            wavefront,
                            propagation_distance,
                            shift_half_pixel=False):

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

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

        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 = fft * p1 * p2 / p3
        fft2 = numpy.fft.fftshift(fft)

        wavefront_out = GenericWavefront1D.initialize_wavefront_from_arrays(
            x2, fft2, wavelength=wavefront.get_wavelength())

        # added [email protected] 2018-03-23 to conserve energy - TODO: review method!
        wavefront_out.rescale_amplitude(
            numpy.sqrt(wavefront.get_intensity().sum() /
                       wavefront_out.get_intensity().sum()))

        return wavefront_out
 def get_eigenvector_wavefront(self, mode):
     complex_amplitude = self.get_eigenvectors()[mode, :] * np.sqrt(
         self.get_eigenvalue(mode))
     wf = GenericWavefront1D.initialize_wavefront_from_arrays(
         self.abscissas, complex_amplitude)
     wf.set_photon_energy(self.photon_energy)
     return wf
    def _calculate_far_field(self):
        #
        # undulator emission
        #
        out = self.calculate_undulator_emission(
            electron_energy=self.electron_energy,
            electron_current=self.electron_current,
            undulator_period=self.undulator_period,
            undulator_nperiods=self.undulator_nperiods,
            K=self.K,
            photon_energy=self.photon_energy,
            abscissas_interval_in_far_field=self.
            _abscissas_interval_in_far_field,
            number_of_points=self.number_of_points,
            distance_to_screen=self.distance_to_screen,
            scan_direction=self.scan_direction,
        )

        #
        #
        #
        from wofry.propagator.wavefront1D.generic_wavefront import GenericWavefront1D

        input_wavefront = GenericWavefront1D.initialize_wavefront_from_arrays(
            out["abscissas"], out["electric_field"][:, 0])
        input_wavefront.set_photon_energy(photon_energy=self.photon_energy)

        self.far_field_wavefront = input_wavefront
Beispiel #5
0
def propagator1D_offaxis(input_wavefront, x2_oe, y2_oe, p, q, theta_grazing_in, theta_grazing_out=None,
                         zoom_factor=1.0, normalize_intensities=False):

    from wofry.propagator.wavefront1D.generic_wavefront import GenericWavefront1D

    if theta_grazing_out is None:
        theta_grazing_out = theta_grazing_in

    x1 = input_wavefront.get_abscissas()
    field1 = input_wavefront.get_complex_amplitude()
    wavelength = input_wavefront.get_wavelength()

    x1_oe = -p * numpy.cos(theta_grazing_in) + x1 * numpy.sin(theta_grazing_in)
    y1_oe = p * numpy.sin(theta_grazing_in) + x1 * numpy.cos(theta_grazing_in)

    # field2 is the electric field in the mirror
    field2 = goFromToSequential(field1, x1_oe, y1_oe, x2_oe, y2_oe,
                                wavelength=wavelength, normalize_intensities=normalize_intensities)

    x3 = x1 * zoom_factor

    x3_oe = q * numpy.cos(theta_grazing_out) + x3 * numpy.sin(theta_grazing_out)
    y3_oe = q * numpy.sin(theta_grazing_out) + x3 * numpy.cos(theta_grazing_out)

    # field2 is the electric field in the image plane
    field3 = goFromToSequential(field2, x2_oe, y2_oe, x3_oe, y3_oe,
                                wavelength=wavelength, normalize_intensities=normalize_intensities)

    output_wavefront = GenericWavefront1D.initialize_wavefront_from_arrays(x3, field3  / numpy.sqrt(zoom_factor), wavelength=wavelength)

    return output_wavefront
    def toGenericWavefront(self):
        wavelength = self.wise_computation_result.Lambda
        position = self.wise_computation_result.S
        electric_field = numpy.real(
            self.wise_computation_result.Field) + 1j * numpy.imag(
                self.wise_computation_result.Field)

        return GenericWavefront1D.initialize_wavefront_from_arrays(
            x_array=position, y_array=electric_field, wavelength=wavelength)
Beispiel #7
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 = GenericWavefront1D.initialize_wavefront_from_steps(
            x[0], numpy.abs(x[1] - x[0]), y.size)
        wf0.set_complex_amplitude(y)

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

        wf2 = GenericWavefront1D.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)
Beispiel #8
0
    def propagate_wavefront(cls,
                            wavefront1,
                            propagation_distance1,
                            magnification_x=1.0,
                            radius=1e6):
        wavefront = wavefront1.duplicate()
        shape = wavefront.size()
        delta = wavefront.delta()
        wavenumber = wavefront.get_wavenumber()
        wavelength = wavefront.get_wavelength()

        # radius = -50.0
        magnification = (propagation_distance1 + radius) / radius
        propagation_distance = propagation_distance1 / magnification

        #
        # make plane wave by adding a spherical wavefront with radius -R
        #
        new_phase = 1.0 * wavefront.get_wavenumber() * (
            wavefront.get_abscissas()**2) / (-2 * radius)
        wavefront.add_phase_shifts(new_phase)

        #
        # main 2 FFT block
        #
        fft_scale = numpy.fft.fftfreq(shape) / delta

        x = wavefront.get_abscissas()

        x_rescaling = wavefront.get_abscissas() * magnification_x

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

        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.fft(wavefront.get_complex_amplitude())
        ifft = numpy.fft.ifft(fft * Q2) * Q3 / numpy.sqrt(magnification_x)
        #
        #
        #

        #
        # calculate new phase term and scale coordinates
        #
        k = wavefront.get_wavenumber()

        PHASE1 = numpy.ones(
            wavefront.get_abscissas().size) * (k * propagation_distance *
                                               (1 - 1 / magnification))
        PHASE2 = k / 2 / propagation_distance * (
            magnification - 1) / magnification * (wavefront.get_abscissas() *
                                                  magnification)**2
        PHASE = PHASE2 + PHASE1

        wf_propagated = GenericWavefront1D.initialize_wavefront_from_arrays(
            x_rescaling * magnification,
            ifft / numpy.sqrt(magnification) * numpy.exp(1j * PHASE),
            wavelength=wavelength)

        return wf_propagated
Beispiel #9
0
    def propagate_wavefront_new(
            cls,
            wavefront,
            propagation_distance,
            fraunhofer_kernel=True,  # set to False for far field propagator
            shift_half_pixel=None,  # not more used, kept for version compatibility
    ):
        #
        # check validity
        #
        x = wavefront.get_abscissas()
        deltax = wavefront.delta()

        #
        # compute Fourier transform
        #

        # frequency for axis 1
        npixels = wavefront.size()
        pixelsize = wavefront.delta()
        wavenumber = wavefront.get_wavenumber()
        wavelength = wavefront.get_wavelength()

        freq_nyquist = 0.5 / pixelsize
        if numpy.mod(npixels, 2) == 0:
            freq_n = numpy.arange(-npixels // 2, npixels // 2,
                                  1) / (npixels // 2)
        else:
            freq_n = numpy.arange(-(npixels - 1) // 2,
                                  (npixels + 1) // 2, 1) / ((npixels - 1) // 2)

        freq_x = freq_n * freq_nyquist

        x2 = freq_x * propagation_distance * wavelength

        P1 = numpy.exp(1.0j * wavenumber * propagation_distance)

        # fsq = freq_x ** 2
        # P2 = numpy.exp(-1.0j * wavenumber / 2 / propagation_distance * fsq)

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

        if fraunhofer_kernel:
            exponential = 1.0 + 0j
        else:
            exponential = numpy.exp(1j * wavenumber / 2 /
                                    propagation_distance * x**2)

        F1 = numpy.fft.fft(exponential * 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 /= numpy.sqrt(P3)  # this is 1D -> no sqrt for 2D
        F2 = numpy.fft.fftshift(F1)
        F2 *= deltax  # why??

        wavefront_out = GenericWavefront1D.initialize_wavefront_from_arrays(
            x_array=x2, y_array=F2, wavelength=wavelength)

        # added [email protected] 2018-03-23 to conserve energy - TODO: review method!
        # wavefront_out.rescale_amplitude(numpy.sqrt(wavefront.get_intensity().sum() /
        #                                            wavefront_out.get_intensity().sum()))

        return wavefront_out
Beispiel #10
0
def calculate_output_wavefront_after_GSM_1D(input_wavefront,
                                            shape=1,
                                            radius=10000.0,
                                            wavy_amplitude=1e-9,
                                            wavy_ripples=1.0,
                                            grazing_angle=1.5e-3,
                                            grazing_angle_out=1.5e-3,
                                            lines_per_meter=None,
                                            error_flag=0,
                                            error_file="",
                                            error_edge_management=0,
                                            write_profile=""):

    import numpy
    from scipy import interpolate

    abscissas = input_wavefront.get_abscissas().copy()
    abscissas_on_mirror = abscissas / numpy.sin(grazing_angle)
    abscissas_on_output_plane = abscissas_on_mirror * numpy.sin(
        grazing_angle_out)
    output_wavefront = GenericWavefront1D.initialize_wavefront_from_arrays(
        abscissas_on_output_plane,
        input_wavefront.get_complex_amplitude(),
        wavelength=input_wavefront.get_wavelength(),
    )

    # )input_wavefront.duplicate()

    if shape == 0:
        height = numpy.zeros_like(abscissas_on_mirror)
    elif shape == 1:
        if radius >= 0:
            height = radius - numpy.sqrt(radius**2 - abscissas_on_mirror**2)
        else:
            height = radius + numpy.sqrt(radius**2 - abscissas_on_mirror**2)
    elif shape > 1:
        if wavy_ripples == 0.0:
            height = numpy.zeros_like(abscissas_on_mirror)
        else:
            period = (abscissas_on_mirror[-1] -
                      abscissas_on_mirror[0]) / wavy_ripples
            if shape == 2:
                y = numpy.cos(2 * numpy.pi * abscissas_on_mirror / period)
            elif shape == 3:
                y = numpy.sin(2 * numpy.pi * abscissas_on_mirror / period)
            y -= y.min()
            y /= y.max()
            y *= wavy_amplitude
            height = y
    else:
        raise Exception("Wrong shape")

    if error_flag:
        a = numpy.loadtxt(error_file)  # extrapolation
        if error_edge_management == 0:
            finterpolate = interpolate.interp1d(
                a[:, 0], a[:, 1], fill_value="extrapolate"
            )  # fill_value=(0,0),bounds_error=False)
        elif error_edge_management == 1:
            finterpolate = interpolate.interp1d(a[:, 0],
                                                a[:, 1],
                                                fill_value=(0, 0),
                                                bounds_error=False)
        else:  # crop
            raise Exception("Bad value of error_edge_management")
        height_interpolated = finterpolate(abscissas_on_mirror)
        height += height_interpolated

    #>>>>>>>>>>>>>>>>>>>
    # phi = -2 * output_wavefront.get_wavenumber() * height * numpy.sin(grazing_angle)
    # Ken's Eq. 7
    if lines_per_meter is None:
        delta_grating = 0
    else:
        order = 1
        grating_period = 1.0 / lines_per_meter
        delta_grating = order * output_wavefront.get_wavelength(
        ) / grating_period * abscissas_on_mirror

    delta_s = abscissas_on_mirror * (numpy.cos(grazing_angle) - numpy.cos(grazing_angle_out)) \
              - height * (numpy.sin(grazing_angle) + numpy.sin(grazing_angle_out))

    phi = output_wavefront.get_wavenumber() * (delta_s + delta_grating)
    #>>>>>>>>>>>>>>>>>>>

    output_wavefront.add_phase_shifts(phi)

    if error_flag:
        profile_limits = a[-1, 0] - a[0, 0]
        profile_limits_projected = (a[-1, 0] -
                                    a[0, 0]) * numpy.sin(grazing_angle)
        wavefront_dimension = output_wavefront.get_abscissas(
        )[-1] - output_wavefront.get_abscissas()[0]
        print("profile deformation dimension: %f m" % (profile_limits))
        print(
            "profile deformation projected perpendicular to optical axis: %f um"
            % (1e6 * profile_limits_projected))
        print("wavefront window dimension: %f um" %
              (1e6 * wavefront_dimension))

        if wavefront_dimension <= profile_limits_projected:
            print(
                "\nWavefront window inside error profile domain: no action needed"
            )
        else:
            if error_edge_management == 0:
                print(
                    "\nProfile deformation extrapolated to fit wavefront dimensions"
                )
            else:
                output_wavefront.clip(a[0, 0] * numpy.sin(grazing_angle),
                                      a[-1, 0] * numpy.sin(grazing_angle))
                print(
                    "\nWavefront clipped to projected limits of profile deformation"
                )

    # output files
    if write_profile != "":
        f = open(write_profile, "w")
        for i in range(height.size):
            f.write("%g %g\n" % (abscissas_on_mirror[i], height[i]))
        f.close()
        print("File %s written to disk." % write_profile)

    return output_wavefront, abscissas_on_mirror, height