def from_shadow_beam_to_photon_bunch(self):

        vx = self.incoming_shadow_beam._beam.getshcol(4, nolost=1)
        vy = self.incoming_shadow_beam._beam.getshcol(5, nolost=1)
        vz = self.incoming_shadow_beam._beam.getshcol(6, nolost=1)

        s0 = self.incoming_shadow_beam._beam.getshcol(30, nolost=1)
        s1 = self.incoming_shadow_beam._beam.getshcol(31, nolost=1)
        s2 = self.incoming_shadow_beam._beam.getshcol(32, nolost=1)
        s3 = self.incoming_shadow_beam._beam.getshcol(33, nolost=1)
        energies = self.incoming_shadow_beam._beam.getshcol(11, nolost=1)

        photon_bunch = PolarizedPhotonBunch([])
        photons_list = list()
        for i, energy in enumerate(energies):
            photon = PolarizedPhoton(
                energy_in_ev=energy,
                direction_vector=Vector(vx[i], vy[i], vz[i]),
                stokes_vector=StokesVector([s0[i], s1[i], s2[i], s3[i]]))
            #photon_bunch.add(photon)
            # print("<><> appending photon",i)
            photons_list.append(photon)

        photon_bunch.addPhotonsFromList(photons_list)

        return photon_bunch
Пример #2
0
    def calculate_IdealPhaseRetarder(self):
        print("Inside calculate_IdealPhaseRetarder. ")

        if self._input_available:
            photon_bunch = self.incoming_bunch
            if self.TYPE == 0:
                mm = MuellerMatrix.initialize_as_general_linear_retarder(
                    theta=self.THETA * np.pi / 180,
                    delta=self.DELTA * np.pi / 180)
            elif self.TYPE == 1:
                mm = MuellerMatrix.initialize_as_quarter_wave_plate_fast_horizontal(
                )
            elif self.TYPE == 2:
                mm = MuellerMatrix.initialize_as_quarter_wave_plate_fast_vertical(
                )
            elif self.TYPE == 3:
                mm = MuellerMatrix.initialize_as_half_wave_plate()

            # print(mm.matrix)

            photon_bunch_out = PolarizedPhotonBunch()

            for index in range(photon_bunch.getNumberOfPhotons()):
                polarized_photon = photon_bunch.getPhotonIndex(
                    index).duplicate()
                polarized_photon.applyMuellerMatrix(mm)
                photon_bunch_out.addPhoton(polarized_photon)

            # Dump data to file if requested.
            if self.DUMP_TO_FILE == 1:

                print("CrystalPassive: Writing data in {file}...\n".format(
                    file=self.FILE_NAME))

                with open(self.FILE_NAME, "w") as file:
                    try:
                        file.write(
                            "#S 1 photon bunch\n"
                            "#N 9\n"
                            "#L  Energy [eV]  Vx  Vy  Vz  S0  S1  S2  S3  circular polarization\n"
                        )

                        tmp = photon_bunch_out.toString()
                        file.write(tmp)
                        file.close()
                        print("File written to disk: %s" % self.FILE_NAME)
                    except:
                        raise Exception(
                            "IdealPhaseRetarder: The data could not be dumped onto the specified file!\n"
                        )

            self.send("photon bunch", photon_bunch_out)

        else:
            raise Exception("No photon beam available")
    def testChangePhotonValue(self):
        nphotons = 10

        from crystalpy.util.Vector import Vector
        from crystalpy.util.StokesVector import StokesVector

        bunch = PolarizedPhotonBunch([])
        for i in range(nphotons):
            polarized_photon = PolarizedPhoton(
                energy_in_ev=1000.0 + i,
                direction_vector=Vector(0, 1.0, 0),
                stokes_vector=StokesVector([1.0, 0, 1.0, 0]))
            bunch.addPhoton(polarized_photon)

        # photon5_stokes = bunch.get_photon_index(5).stokesVector().get_array(numpy=True)
        # print("photon 5 stokes ",photon5_stokes)

        photon5 = bunch.getPhotonIndex(5)

        photon5.setStokesVector(StokesVector([1, 0, 0, 0]))
        photon5_stokes_new = bunch.getPhotonIndex(
            5).stokesVector().components()

        # print("photon 5 stokes new ",photon5_stokes_new)

        assert_almost_equal(photon5_stokes_new, numpy.array([1.0, 0, 0, 0]))
Пример #4
0
    def calculateDiffractedPolarizedPhotonBunch(self, diffraction_setup,
                                                incoming_bunch,
                                                inclination_angle):
        """
        Calculates the diffraction/transmission given by the setup.
        :param diffraction_setup: The diffraction setup.
        :return: PhotonBunch object made up of diffracted/transmitted photons.
        """
        # Create PhotonBunch instance.
        outgoing_bunch = PolarizedPhotonBunch([])

        # Retrieve the photon bunch from the diffraction setup.
        # incoming_bunch = diffraction_setup.incomingPhotons()

        # Check that photon_bunch is indeed a PhotonBunch object.
        if not isinstance(incoming_bunch, PolarizedPhotonBunch):
            raise Exception(
                "The incoming photon bunch must be a PolarizedPhotonBunch object!"
            )

        # Raise calculation start.
        self._onCalculationStart()

        for index, polarized_photon in enumerate(incoming_bunch):

            # Raise OnProgress event if progressed by 10 percent.
            self._onProgressEveryTenPercent(index, len(incoming_bunch))

            outgoing_polarized_photon = self.calculateDiffractedPolarizedPhoton(
                diffraction_setup, polarized_photon, inclination_angle)
            # Add result of current deviation.
            outgoing_bunch.addPhoton(outgoing_polarized_photon)

        # Raise calculation end.
        self._onCalculationEnd()

        # Return diffraction results.
        return outgoing_bunch
    def testFromArray(self):

        npoint = 1000
        vx = numpy.zeros(npoint) + 0.0
        vy = numpy.zeros(npoint) + 1.0
        vz = numpy.zeros(npoint) + 0.0

        s0 = numpy.zeros(npoint) + 1
        s1 = numpy.zeros(npoint) + 0
        s2 = numpy.zeros(npoint) + 1
        s3 = numpy.zeros(npoint) + 0

        energy = numpy.zeros(npoint) + 3000.0

        photon_bunch = PolarizedPhotonBunch([])

        photons_list = list()
        for i in range(npoint):

            photon = PolarizedPhoton(
                energy_in_ev=energy[i],
                direction_vector=Vector(vx[i], vy[i], vz[i]),
                stokes_vector=StokesVector([s0[i], s1[i], s2[i], s3[i]]))
            photons_list.append(photon)

        photon_bunch.addPhotonsFromList(photons_list)

        # print("<><><>",photon_bunch.toString())
        # print("<><><>",photon_bunch.toDictionary())

        self.assertTrue(1.0 == any(photon_bunch.getArrayByKey("s0")))
        self.assertTrue(0.0 == any(photon_bunch.getArrayByKey("s1")))
        self.assertTrue(1.0 == any(photon_bunch.getArrayByKey("s2")))
        self.assertTrue(0.0 == any(photon_bunch.getArrayByKey("s3")))

        energies = photon_bunch.getArrayByKey("energies")
        for energy in energies:
            self.assertAlmostEqual(energy, 3000.0)
Пример #6
0
if __name__ == '__main__':
    from PyQt5.QtWidgets import QApplication

    from crystalpy.util.Vector import Vector
    from crystalpy.util.StokesVector import StokesVector
    from crystalpy.util.PolarizedPhoton import PolarizedPhoton
    from crystalpy.util.PolarizedPhotonBunch import PolarizedPhotonBunch

    app = QApplication([])
    ow = OWPhotonViewer()

    nphotons = 10

    from crystalpy.util.Vector import Vector
    from crystalpy.util.StokesVector import StokesVector

    bunch = PolarizedPhotonBunch([])
    for i in range(nphotons):
        polarized_photon = PolarizedPhoton(energy_in_ev=1000.0 + i,
                                           direction_vector=Vector(0, 1.0, 0),
                                           stokes_vector=StokesVector(
                                               [1.0, 0, 1.0, 0]))
        bunch.addPhoton(polarized_photon)

    ow._set_input(bunch)
    ow.do_plot()
    ow.show()

    app.exec_()
    ow.saveSettings()
Пример #7
0
    def generate(self):

        if self.figure_canvas is not None:
            self.mainArea.layout().removeWidget(self.figure_canvas)

        #
        # Calculating the critical energy in eV following Green pag.3.
        #
        gamma = self.ELECTRON_ENERGY * 1e3 / codata_mee  # the electron energy is given in GeV.
        critical_wavelength = 4.0 * np.pi * self.MAGNETIC_RADIUS / 3.0 / np.power(
            gamma, 3)  # wavelength in m.
        ec_ev = m2ev / critical_wavelength  # critical energy in eV.

        #
        # Constructing the angle and energy grids.
        #
        if self.ENERGY_POINTS == 1:
            # monochromatic bunch.
            ENERGY_MIN = ENERGY_MAX = self.ENERGY

        else:
            ENERGY_MIN = self.ENERGY_MIN
            ENERGY_MAX = self.ENERGY_MAX

        energies = np.linspace(start=ENERGY_MIN,
                               stop=ENERGY_MAX,
                               num=self.ENERGY_POINTS)

        if self.ANGLE_DEVIATION_POINTS == 1:
            # unidirectional bunch.
            ANGLE_DEVIATION_MIN = ANGLE_DEVIATION_MAX = self.ANGLE_DEVIATION * 1e-6  # urad --> rad

        else:
            ANGLE_DEVIATION_MIN = self.ANGLE_DEVIATION_MIN * 1e-6  # urad --> rad
            ANGLE_DEVIATION_MAX = self.ANGLE_DEVIATION_MAX * 1e-6  # urad --> rad

        deviations = np.linspace(start=ANGLE_DEVIATION_MIN,
                                 stop=ANGLE_DEVIATION_MAX,
                                 num=self.ANGLE_DEVIATION_POINTS)

        sync_ang_deviations = np.multiply(
            deviations,
            1e3)  # sync_ang takes as an input angles in mrad, not urad.
        photon_bunch = PolarizedPhotonBunch([])

        for energy in energies:

            photon_bunch_to_add = stokes_calculator(energy,
                                                    sync_ang_deviations,
                                                    self.ELECTRON_ENERGY,
                                                    self.ELECTRON_CURRENT,
                                                    self.HORIZONTAL_DIVERGENCE,
                                                    float(ec_ev))
            photon_bunch.addBunch(photon_bunch_to_add)

        #
        # Dump data to file if requested.
        #
        if self.DUMP_TO_FILE:

            print("BendingMagnet: Writing data in {file}...\n".format(
                file=self.FILE_NAME))

            with open(self.FILE_NAME, "w") as file:
                try:
                    file.write("#S 1 photon bunch\n"
                               "#N 9\n"
                               "#L  Energy [eV]  Vx  Vy  Vz  S0  S1  S2  S3\n")
                    file.write(photon_bunch.toString())
                    file.close()
                    print("File written to disk: %s" % self.FILE_NAME)
                except:
                    raise Exception(
                        "BendingMagnet: The data could not be dumped onto the specified file!\n"
                    )

        #
        # Plotting the emission profiles according to user input if requested.
        #
        if self.VIEW_EMISSION_PROFILE == 1:

            self.fig.clf()  # clear the current Figure.
            self.figure_canvas.draw()

        elif self.VIEW_EMISSION_PROFILE == 0:

            self.fig.clf()  # clear the current Figure.
            ax = self.fig.add_subplot(111)

            toptitle = "Bending Magnet angular emission"
            xtitle = "Psi[mrad]"
            ytitle = "Power density[Watts/mrad]"

            if self.ENERGY_POINTS == 1:
                flux = sync_ang(1,
                                sync_ang_deviations,
                                polarization=0,
                                e_gev=self.ELECTRON_ENERGY,
                                i_a=self.ELECTRON_CURRENT,
                                hdiv_mrad=1.0,
                                energy=self.ENERGY,
                                ec_ev=ec_ev)

                ax.plot(sync_ang_deviations,
                        flux,
                        'g',
                        label="E={} keV".format(self.ENERGY * 1e-3))

            else:
                flux_Emin = sync_ang(
                    1,
                    sync_ang_deviations,
                    polarization=0,  # energy = lower limit.
                    e_gev=self.ELECTRON_ENERGY,
                    i_a=self.ELECTRON_CURRENT,
                    hdiv_mrad=1.0,
                    energy=self.ENERGY_MIN,
                    ec_ev=ec_ev)

                flux_Emax = sync_ang(
                    1,
                    sync_ang_deviations,
                    polarization=0,  # energy = upper limit.
                    e_gev=self.ELECTRON_ENERGY,
                    i_a=self.ELECTRON_CURRENT,
                    hdiv_mrad=1.0,
                    energy=self.ENERGY_MAX,
                    ec_ev=ec_ev)

                ax.plot(sync_ang_deviations,
                        flux_Emin,
                        'r',
                        label="E min={} keV".format(self.ENERGY_MIN * 1e-3))
                ax.plot(sync_ang_deviations,
                        flux_Emax,
                        'b',
                        label="E max={} keV".format(self.ENERGY_MAX * 1e-3))

            ax.set_title(toptitle)
            ax.set_xlabel(xtitle)
            ax.set_ylabel(ytitle)
            ax.set_xlim(sync_ang_deviations.min(), sync_ang_deviations.max())
            ax.legend(bbox_to_anchor=(1.1, 1.05))

            self.figure_canvas.draw()

            print("BendingMagnet: Photon bunch generated.\n")
            self.send("photon bunch", photon_bunch)
Пример #8
0
def stokes_calculator(energy,
                      deviations,
                      e_gev=6.04,
                      i_a=0.2,
                      hdiv_mrad=1.0,
                      ec_ev=19551.88):
    """
    Calculates the Stokes vectors for each PolarizedPhoton according to the theory of the BM emission.
    It does this by use of a modified version of the sync_ang function that allows the computation of the
    power densities for the RCP and LCP components on top of the linear components.
    The dW_+1 and dW_-1 values are obtained by setting respectively:

        l2 = l3 = 1/sqrt(2) for RCP and
        l2 = -l3 = 1/sqrt(2) for LCP.

    The computation of dW_-1 (LCP), dW_1 (RCP), dW_2 (sigma) and dW_3 (pi) makes it possible to use
    the formula 3.23 from Sokolov & Ternov for the phase difference delta = phi_3 - phi_2.
    This in turn lead to the Stokes parameters as defined in Jackson, 7.27.

    The default values for the parameters are the typical ESRF values.
    :param energy: desired photon energy in eV.
    :type energy: float
    :param deviations: array of angle deviations in milliradians.
    :type deviations: numpy.ndarray
    :param e_gev: energy of the electrons in GeV.
    :type e_gev: float
    :param i_a: beam current in A.
    :type i_a: float
    :param hdiv_mrad: horizontal divergence of the beam in milliradians.
    :type hdiv_mrad; float
    :param ec_ev: critical energy as in Green, pag.3.
    :type ec_ev: float
    :return: list of StokesVector objects.
    :rtype: PolarizedPhotonBunch
    """
    #
    # Calculate some parameters needed by sync_f (copied from sync_ang by Manuel Sanchez del Rio).
    # a8 = 1.3264d13
    #
    deviations = np.array(deviations)
    a8 = codata_ec / np.power(codata_mee, 2) / codata_h * (9e-2 / 2 / np.pi)
    energy = float(energy)
    eene = energy / ec_ev
    gamma = e_gev * 1e3 / codata_mee

    #
    # Calculate the power densities for the 4 cases:
    #
    #    -1 --> left circularly polarized       l2 = -l3 = 1/sqrt(2)
    #     1 --> right circularly polarized      l2 = l3 = 1/sqrt(2)
    #     2 --> linear sigma component          l2 = 1 & l3 = 0
    #     3 --> linear pi component             l3 = 1 & l2 = 0
    #
    left_circular = modified_sync_f(deviations * gamma / 1e3, eene, polarization=-1) * \
        np.power(eene, 2) * \
        a8 * i_a * hdiv_mrad * np.power(e_gev, 2)  # -1

    right_circular = modified_sync_f(deviations * gamma / 1e3, eene, polarization=1) * \
        np.power(eene, 2) * \
        a8 * i_a * hdiv_mrad * np.power(e_gev, 2)  # 1

    sigma_linear = modified_sync_f(deviations * gamma / 1e3, eene, polarization=2) * \
        np.power(eene, 2) * \
        a8 * i_a * hdiv_mrad * np.power(e_gev, 2)  # 2

    pi_linear = modified_sync_f(deviations * gamma / 1e3, eene, polarization=3) * \
        np.power(eene, 2) * \
        a8 * i_a * hdiv_mrad * np.power(e_gev, 2)  # 3

    #
    # Calculate the phase difference delta according to Sokolov, formula 3.23.
    #
    delta = (left_circular - right_circular) / \
        (2 * np.sqrt(sigma_linear * pi_linear))

    delta = np.arcsin(delta)

    #
    # Calculate the Stokes parameters.
    #
    s_0 = sigma_linear + pi_linear
    s_1 = sigma_linear - pi_linear
    s_2 = np.sqrt(sigma_linear) * np.sqrt(pi_linear) * np.cos(delta)
    s_3 = np.sqrt(sigma_linear) * np.sqrt(pi_linear) * np.sin(delta)
    s_2 *= 2  # TODO: try to understand why if I multiply by 2 in the line above I get a warning.
    s_3 *= 2

    #
    # Normalize the Stokes parameters.
    #
    # modulus = np.sqrt(s_0 ** 2 + s_1 ** 2 + s_2 ** 2 + s_3 ** 2)
    #
    # if np.any(modulus != 0):
    #     s_0 /= modulus
    #     s_1 /= modulus
    #     s_2 /= modulus
    #     s_3 /= modulus
    #
    # else:
    #     raise Exception("BendingMagnet.stokes_calculator: Stokes vector is null vector!\n")

    maximum = np.max(s_0)
    s_0 /= maximum
    s_1 /= maximum
    s_2 /= maximum
    s_3 /= maximum

    # Following XOP conventions, the photon bunch travels along the y axis in the lab frame of reference.
    base_direction = Vector(0, 1, 0)
    rotation_axis = Vector(1, 0, 0)

    #
    # Create the PolarizedPhotonBunch.
    #
    # To match the deviation sign conventions with those adopted in the crystal diffraction part,
    # I have to define a positive deviation as a clockwise rotation from the y axis,
    # and consequently a negative deviation as a counterclockwise rotation from the y axis.
    #
    polarized_photons = list()
    deviations = np.multiply(deviations, 1e-3)  # mrad --> rad

    for i in range(len(deviations)):
        stokes_vector = StokesVector([s_0[i], s_1[i], s_2[i], s_3[i]])
        direction = base_direction.rotateAroundAxis(rotation_axis,
                                                    deviations[i])
        incoming_photon = PolarizedPhoton(energy, direction, stokes_vector)
        polarized_photons.append(incoming_photon)

    photon_bunch = PolarizedPhotonBunch(polarized_photons)

    return photon_bunch
Пример #9
0
def calculate_with_polarized_photon(method=0):

    # Create a diffraction setup.

    print("\nCreating a diffraction setup...")
    diffraction_setup = DiffractionSetup(
        geometry_type=BraggDiffraction(),  # GeometryType object
        crystal_name="Si",  # string
        thickness=1e-2,  # meters
        miller_h=1,  # int
        miller_k=1,  # int
        miller_l=1,  # int
        asymmetry_angle=
        0,  #10.0*numpy.pi/180.,                              # radians
        azimuthal_angle=0.0)  # radians                            # int

    energy = 8000.0  # eV
    angle_deviation_min = -100e-6  # radians
    angle_deviation_max = 100e-6  # radians
    angle_deviation_points = 500

    angle_step = (angle_deviation_max -
                  angle_deviation_min) / angle_deviation_points

    bunch_in = PolarizedPhotonBunch()

    bragg_angle = diffraction_setup.angleBragg(energy)

    print("Bragg angle for E=%f eV is %f deg" %
          (energy, bragg_angle * 180.0 / numpy.pi))

    # Create a Diffraction object.
    diffraction = Diffraction()

    #
    # get wavevector with incident direction matching Bragg angle
    #
    K0 = diffraction_setup.getK0(energy)
    K0unitary = K0.getNormalizedVector()

    print("K0", K0.components())

    # method = 0 # diffraction for individual photons
    # method = 1 # diffraction for bunch
    ZZ = numpy.zeros(angle_deviation_points)

    if method == 0:
        bunch_out = PolarizedPhotonBunch()

        for ia in range(angle_deviation_points):
            deviation = angle_deviation_min + ia * angle_step

            # angle =  deviation + bragg_angle
            # yy = numpy.cos(angle)
            # zz = - numpy.abs(numpy.sin(angle))
            # photon = PolarizedPhoton(energy_in_ev=energy,direction_vector=Vector(0.0,yy,zz),
            #                          stokes_vector=StokesVector([1,0,1,0]))

            # minus sign in angle is to perform cw rotation when deviation increses
            Vin = K0unitary.rotateAroundAxis(Vector(1, 0, 0), -deviation)
            photon = PolarizedPhoton(energy_in_ev=energy,
                                     direction_vector=Vin,
                                     stokes_vector=StokesVector([1, 0, 1, 0]))

            photon_out = diffraction.calculateDiffractedPolarizedPhoton(
                diffraction_setup,
                incoming_polarized_photon=photon,
                inclination_angle=0.0)
            bunch_out.addPhoton(photon_out)
            ZZ[ia] = angle_deviation_min + ia * angle_step

    elif method == 1:  # diffraction for bunch
        for ia in range(angle_deviation_points):
            deviation = angle_deviation_min + ia * angle_step

            # angle = deviation + bragg_angle
            # yy = numpy.cos(angle)
            # zz = - numpy.abs(numpy.sin(angle))
            # photon = PolarizedPhoton(energy_in_ev=energy,direction_vector=Vector(0.0,yy,zz),
            #                          stokes_vector=StokesVector([1,0,1,0]))

            # minus sign in angle is to perform cw rotation when deviation increses
            Vin = K0unitary.rotateAroundAxis(Vector(1, 0, 0), -deviation)
            photon = PolarizedPhoton(energy_in_ev=energy,
                                     direction_vector=Vin,
                                     stokes_vector=StokesVector([1, 0, 1, 0]))

            bunch_in.addPhoton(photon)
            ZZ[ia] = angle_deviation_min + ia * angle_step

        bunch_out = diffraction.calculateDiffractedPolarizedPhotonBunch(
            diffraction_setup, bunch_in, 0.0)

    bunch_out_dict = bunch_out.toDictionary()

    plot(1e6 * ZZ,
         bunch_out_dict["s0"],
         1e6 * ZZ,
         bunch_out_dict["s1"],
         legend=["S0", "S1"],
         xtitle="theta - thetaB [urad]",
         title="Polarized reflectivity calculation using method %d" % method)
Пример #10
0
    def generate(self):

        if self.ENERGY_POINTS == 1:
            # monochromatic bunch.
            self.ENERGY_MIN = self.ENERGY_MAX = self.ENERGY

        energies = np.linspace(self.ENERGY_MIN, self.ENERGY_MAX,
                               self.ENERGY_POINTS)

        if self.ANGLE_DEVIATION_POINTS == 1:
            # unidirectional bunch.
            ANGLE_DEVIATION_MIN = ANGLE_DEVIATION_MAX = self.ANGLE_DEVIATION * 1e-6  # urad

        else:
            ANGLE_DEVIATION_MIN = self.ANGLE_DEVIATION_MIN * 1e-6  # urad
            ANGLE_DEVIATION_MAX = self.ANGLE_DEVIATION_MAX * 1e-6  # urad

        deviations = np.linspace(ANGLE_DEVIATION_MIN, ANGLE_DEVIATION_MAX,
                                 self.ANGLE_DEVIATION_POINTS)

        stokes_vector = StokesVector(
            [self.STOKES_S0, self.STOKES_S1, self.STOKES_S2, self.STOKES_S3])

        # Following XOP conventions, the photon bunch travels along the y axis in the lab frame of reference.
        base_direction = Vector(0, 1, 0)
        # TODO: check this sign and possibly change it.
        # Setting (-1,0,0) means that negative deviation correspond to positive vz and after rotation
        # to match the crystal correspond to theta_bragg -  delta, so deviation has the same sign of delta

        rotation_axis = Vector(-1, 0, 0)

        # To match the deviation sign conventions with those adopted in the crystal diffraction part,
        # I have to define a positive deviation as a clockwise rotation from the y axis,
        # and consequently a negative deviation as a counterclockwise rotation from the y axis.

        polarized_photons = list()
        for energy in energies:
            for deviation in deviations:
                direction = base_direction.rotateAroundAxis(
                    rotation_axis, deviation)
                incoming_photon = PolarizedPhoton(energy, direction,
                                                  stokes_vector)
                polarized_photons.append(incoming_photon)

        photon_bunch = PolarizedPhotonBunch(polarized_photons)

        # Dump data to file if requested.
        if self.DUMP_TO_FILE:

            print("PhotonSource: Writing data in {file}...\n".format(
                file=self.FILE_NAME))

            with open(self.FILE_NAME, "w") as file:
                try:
                    file.write(
                        "#S 1 photon bunch\n"
                        "#N 9\n"
                        "#L  Energy [eV]  Vx  Vy  Vz  S0  S1  S2  S3  CircularPolarizationDregree\n"
                    )
                    file.write(photon_bunch.toString())
                    file.close()
                    print("File written to disk: %s \n" % self.FILE_NAME)
                except:
                    raise Exception(
                        "PhotonSource: The data could not be dumped onto the specified file!\n"
                    )

        self.send("photon bunch", photon_bunch)
        print("PhotonSource: Photon bunch generated.\n")
Пример #11
0
    def apply(self):

        if not self._input_available:
            raise Exception("AlignmentTool: Input data not available!\n")

        energy_in_kev = self.BASE_ENERGY / 1000.0

        outgoing_bunch = PolarizedPhotonBunch([])

        x_axis = Vector(1, 0, 0)
        neg_x_axis = Vector(-1, 0, 0)

        # Retrieve Bragg angle from xraylib.
        angle_bragg = xraylib.Bragg_angle(self.CRYSTAL, energy_in_kev,
                                          self.MILLER_H, self.MILLER_K,
                                          self.MILLER_L)

        # TODO: change rotation using the crystalpy tool to get full alignment.
        for i in range(self.incoming_bunch.getNumberOfPhotons()):
            polarized_photon = self.incoming_bunch.getPhotonIndex(i)

            if self.MODE == 0:  # ray-to-crystal
                rotated_vector = polarized_photon.unitDirectionVector().\
                    rotateAroundAxis(neg_x_axis, angle_bragg + self.ALPHA_X*np.pi/180)

            elif self.MODE == 1:  # crystal-to-ray
                rotated_vector = polarized_photon.unitDirectionVector(). \
                    rotateAroundAxis(neg_x_axis, angle_bragg - self.ALPHA_X*np.pi/180)

            else:
                raise Exception(
                    "AlignmentTool: The alignment mode could not be interpreted correctly!\n"
                )

            polarized_photon.setUnitDirectionVector(rotated_vector)
            outgoing_bunch.addPhoton(polarized_photon)

        # Dump data to file if requested.
        if self.DUMP_TO_FILE:

            print("AlignmentTool: Writing data in {file}...\n".format(
                file=self.FILE_NAME))

            with open(self.FILE_NAME, "w") as file:
                try:
                    file.write(
                        "#S 1 photon bunch\n"
                        "#N 9\n"
                        "#L  Energy [eV]  Vx  Vy  Vz  S0  S1  S2  S3  CircularPolarizationDegree\n"
                    )
                    file.write(outgoing_bunch.toString())
                    file.close()
                    print("File written to disk: %s \n" % self.FILE_NAME)

                except:
                    raise Exception(
                        "AlignmentTool: The data could not be dumped onto the specified file!\n"
                    )

        self.send("photon bunch", outgoing_bunch)
        print("AlignmentTool: Photon bunch aligned.\n")