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]))
    def testDuplicate(self):
        v1 = StokesVector([1, 2, 3, 4])
        v2 = v1.duplicate()

        self.assertTrue(v1 == v2)

        v1.setFromValues(0, 2, 3, 4)

        self.assertFalse(v1 == v2)
    def testConstructor(self):
        photon = PolarizedPhoton(energy_in_ev=8000,
                                 direction_vector=Vector(0.0, 1.0, 0.0),
                                 stokes_vector=StokesVector(
                                     [1.0, 0.0, 1.0, 0.0]))

        self.assertIsInstance(photon, PolarizedPhoton)
        self.assertTrue(photon.unitDirectionVector() == Vector(0.0, 1.0, 0.0))
        self.assertTrue(
            photon.stokesVector() == StokesVector([1.0, 0.0, 1.0, 0.0]))
 def test_operator_not_equal(self):
     stokes_vector1 = self.stokes_vector
     stokes_vector2 = StokesVector([
         0.7817796945787793, 0.22595711869558588, 0.2879756775648755,
         0.585518610609899
     ])  # without final zeros
     stokes_vector3 = StokesVector([
         round(0.78177969457877930, 6),
         round(0.22595711869558588, 6),
         round(0.28797567756487550, 6),
         round(0.58551861060989900, 6)
     ])  # rounded float
     self.assertFalse(stokes_vector1 != stokes_vector1)
     self.assertFalse(stokes_vector1 != stokes_vector2)
     self.assertTrue(stokes_vector1 != stokes_vector3)
Beispiel #5
0
    def test_create_matrix1(self):
        # phase plate 1

        element_list = [1, 1, 0, 0]
        incoming_stokes_vector = StokesVector(element_list)
        intensity_sigma = 0.5366453389170862
        phase_sigma = 1.9718541179322164  # radians
        intensity_pi = 0.9685465109320982
        phase_pi = -2.8903921744707217  # radians
        inclination_angle = 45.0 * np.pi / 180  # radians

        phase_plate = CrystalPhasePlate(  #incoming_stokes_vector=incoming_stokes_vector,
            intensity_sigma=intensity_sigma,
            phase_sigma=phase_sigma,
            intensity_pi=intensity_pi,
            phase_pi=phase_pi,
            inclination_angle=inclination_angle)

        phase_plate_matrix = phase_plate.matrix

        self.assertIsInstance(phase_plate_matrix, np.ndarray)
        candidate = np.array(
            [[0.7525959249245922, 0.0, -0.215950586007506, 0.0],
             [-0.215950586007506, 0.0, 0.7525959249245922, 0.0],
             [0.0, -0.10763540116609252, 0.0, -0.7128678636549213],
             [0.0, -0.7128678636549213, 0.0, 0.10763540116609252]])
        # default precision: 6 decimal places.
        np.testing.assert_array_almost_equal(candidate, phase_plate_matrix)
Beispiel #6
0
    def test_calculate_stokes_vector(self):
        # phase plate 1
        # outgoing_stokes_vector = self.phase_plate1.calculate_stokes_vector()

        element_list = [1, 1, 0, 0]
        incoming_stokes_vector = StokesVector(element_list)
        intensity_sigma = 0.5366453389170862
        phase_sigma = 1.9718541179322164  # radians
        intensity_pi = 0.9685465109320982
        phase_pi = -2.8903921744707217  # radians
        inclination_angle = 45.0 * np.pi / 180  # radians

        phase_plate = CrystalPhasePlate(  #incoming_stokes_vector=incoming_stokes_vector,
            intensity_sigma=intensity_sigma,
            phase_sigma=phase_sigma,
            intensity_pi=intensity_pi,
            phase_pi=phase_pi,
            inclination_angle=inclination_angle)

        outgoing_stokes_vector = phase_plate.calculate_stokes_vector(
            incoming_stokes_vector)

        self.assertIsInstance(outgoing_stokes_vector, StokesVector)
        candidate = np.array([
            0.7525959249245922, -0.215950586007506, -0.10763540116609252,
            -0.7128678636549213
        ])
        # default precision: 6 decimal places.
        np.testing.assert_array_almost_equal(
            candidate, outgoing_stokes_vector.components())
Beispiel #7
0
    def _use_default(self):
        """
        Use the default diffraction parameters.
        """
        # diffraction part
        self.geometry_type = GeometryType.BraggDiffraction()
        self.crystal_name = "Si"
        self.thickness = 0.01  # centimetres
        self.miller_h = 1  # int
        self.miller_k = 1  # int
        self.miller_l = 1  # int
        self.asymmetry_angle = 0.0  # degrees
        self.azimuthal_angle = 90.0  # degrees
        self.energy_min = 8.0  # keV
        self.energy_max = 8.0  # keV
        self.energy_points = 1  # int
        self.angle_deviation_min = -100  # micro radians
        self.angle_deviation_max = 100  # micro radians
        self.angle_deviation_points = 200  # int
        self.deg = True  # phase results in degrees by default.
        self.inclination_angle = 45.0  # degrees
        self.phase_inf_limit = -180  # degrees
        self.phase_sup_limit = 180  # degrees

        # polarization part
        self.incoming_stokes_vector = StokesVector([1, 1, 0, 0])
    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
    def testDuplicate(self):
        ph1 = PolarizedPhoton(8000.0, Vector(2, 4, 5),
                              StokesVector([1, 2, 3, 4]))
        ph2 = ph1.duplicate()

        assert_array_almost_equal(ph1.stokesVector().components(),
                                  ph2.stokesVector().components())

        assert_array_almost_equal(ph1.unitDirectionVector().components(),
                                  ph2.unitDirectionVector().components())
Beispiel #10
0
    def calculate_stokes_vector(self, incoming_stokes_vector):
        """
        Takes an incoming Stokes vector, multiplies it by a Mueller matrix
        and gives an outgoing Stokes vector as a result.
        :return: StokesVector object.
        """
        # incoming_stokes_vector = self.incoming_stokes_vector.get_array()  # Stokes vector.
        element_list = self.matrix_by_vector(incoming_stokes_vector.getList())
        outgoing_stokes_vector = StokesVector(element_list)

        return outgoing_stokes_vector
    def testInheritatedMethods(self):
        ph1 = PolarizedPhoton(8000.0, Vector(2, 4, 5),
                              StokesVector([1, 2, 3, 4]))

        ph1.setUnitDirectionVector(Vector(1, 0, 0))
        ph1.setEnergy(9000)

        self.assertTrue(ph1.unitDirectionVector().components()[0] == 1)
        self.assertTrue(ph1.unitDirectionVector().components()[1] == 0)
        self.assertTrue(ph1.unitDirectionVector().components()[2] == 0)

        self.assertTrue(ph1.energy() == 9000.0)
Beispiel #12
0
def calculate_standard_interface():

    # Create a diffraction setup.

    print("\nCreating a diffraction setup...")
    diffraction_setup = DiffractionSetupSweeps(
        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
        energy_min=8000.0,  # eV
        energy_max=8000.0,  # eV
        energy_points=1,  # int
        angle_deviation_min=-100e-6,  # radians
        angle_deviation_max=100e-6,  # radians
        angle_deviation_points=500)  # int

    # Create a Diffraction object.
    diffraction = Diffraction()

    # Create a DiffractionResult object holding the results of the diffraction calculations.
    print("\nCalculating the diffraction results...")
    diffraction_result = diffraction.calculateDiffraction(diffraction_setup)

    #
    # Now the Mueller/Stokes calculation from the diffraction results
    #

    mueller_diffraction = MuellerDiffraction(
        diffraction_result, StokesVector([1, 0, 1, 0]),
        inclination_angle=0.0)  #np.pi*45/180)

    # Create a MullerResult object.
    print("\nCalculating the Stokes vector...")
    mueller_result = mueller_diffraction.calculate_stokes()

    return mueller_result
    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)
 def testEnergy(self):
     photon = PolarizedPhoton(4000, Vector(0, 0, 1),
                              StokesVector([1.0, 0.0, 1.0, 0.0]))
     self.assertEqual(photon.energy(), 4000)
Beispiel #15
0
    def _use_hirano(self):
        """
        Use the settings for the figures in the Hirano et al. article.
        """
        print(
            "\n----------\nUse the settings specified in the figures from\n"
            "K.Hirano et al., 'Perfect crystal X-ray phase retarders'\n----------\n"
        )
        figure_number = int(
            input(
                "Which figure do you want to reproduce? [e.g. for 'Fig.4' write '4'] "
            ))

        # I call the files where I store the parameters "Fig_$_Hirano.dat", where $ = figure_number.
        file_name = "Fig_{}_Hirano.dat".format(figure_number)

        # Open file.
        file = open(file_name, "r")

        # Read file.
        file_data = list()
        for line in file:
            file_data.append(line.partition("  #")[0])

        self.geometry_type = str(file_data[0])

        if self.geometry_type == "BraggDiffraction":
            self.geometry_type = GeometryType.BraggDiffraction()

        elif self.geometry_type == "BraggTransmission":
            self.geometry_type = GeometryType.BraggTransmission()

        elif self.geometry_type == "LaueDiffraction":
            self.geometry_type = GeometryType.LaueDiffraction()

        elif self.geometry_type == "LaueTransmission":
            self.geometry_type = GeometryType.LaueTransmission()

        else:
            raise Exception("The file content couldn't be read.")

        try:
            self.crystal_name = str(file_data[1])
            self.thickness = float(file_data[2])
            self.miller_h = int(file_data[3])
            self.miller_k = int(file_data[4])
            self.miller_l = int(file_data[5])
            self.asymmetry_angle = float(file_data[6])
            self.energy_min = float(file_data[7])
            self.energy_max = float(file_data[8])
            self.energy_points = int(file_data[9])
            self.angle_deviation_min = float(file_data[10])
            self.angle_deviation_max = float(file_data[11])
            self.angle_deviation_points = int(file_data[12])
            self.inclination_angle = float(file_data[13])
            self.deg = bool(file_data[14])
            self._stokes_parameters = list()

            for i in range(4):
                new_element = float(file_data[15 + i])
                self._stokes_parameters.append(new_element)
            self.incoming_stokes_vector = StokesVector(self._stokes_parameters)

            # read the phase limitations.
            self.phase_inf_limit = float(file_data[19])
            self.phase_sup_limit = float(file_data[20])

            # read the intervals to set to zero.
            self.intervals_number = int(file_data[21])  # number of intervals.
            self.intervals = list()

            # if there are no intervals to set to zero close the file and return.
            if self.intervals_number == 0:
                file.close()
                return

            # else start reading the intervals.
            else:
                for i in range(self.intervals_number):

                    interval = Interval(float(file_data[22 + i * 2]),
                                        float(file_data[23 + i * 2]))
                    self.intervals.append(interval)

        except ValueError:
            raise Exception("The file content couldn't be read.")

        finally:
            file.close()
Beispiel #16
0
    def _set_values(self):
        """
        Set values for the diffraction parameters.
        """
        while True:

            self.geometry_type = int(
                input(
                    "\nBragg diffraction [0]\nBragg transmission [1]\n"
                    "Laue diffraction [2]\nLaue transmission [3]\n\nChoose one type: "
                ))
            if self.geometry_type == 0:
                self.geometry_type = GeometryType.BraggDiffraction()
                break
            elif self.geometry_type == 1:
                self.geometry_type = GeometryType.BraggTransmission()
                break
            elif self.geometry_type == 2:
                self.geometry_type = GeometryType.LaueDiffraction()
                break
            elif self.geometry_type == 3:
                self.geometry_type = GeometryType.LaueTransmission()
                break
            else:
                print("The input could not be interpreted. Try again.\n")

        while True:
            try:
                self.crystal_name = str(input("\nCrystal name: "))
                self.thickness = float(input("\nCrystal thickness [cm]: "))
                self.miller_h = int(input("\nMiller H: "))
                self.miller_k = int(input("\nMiller K: "))
                self.miller_l = int(input("\nMiller L: "))
                self.asymmetry_angle = float(
                    input("\nAsymmetry angle [degrees]: "))
                self.azimuthal_angle = float(
                    input("\nAzimuthal angle [degrees]: "))
                self.energy_min = float(input("\nMinimum energy [keV]: "))
                self.energy_max = float(input("\nMaximum energy [keV]: "))
                self.energy_points = int(input("\nNumber of energy points: "))
                self.angle_deviation_min = float(
                    input(
                        "\nMinimum deviation from Bragg angle [micro radians]: "
                    ))
                self.angle_deviation_max = float(
                    input(
                        "\nMaximum deviation from Bragg angle [micro radians]: "
                    ))
                self.angle_deviation_points = int(
                    input("\nNumber of deviation points: "))
                self.inclination_angle = float(
                    input("\nInclination angle [degrees]: "))
                self.deg = bool(
                    int(
                        input(
                            "\nShould the phase be represented in:\nradians[0]?\ndegrees[1]?"
                        )))
                self._stokes_parameters = list()
                self.phase_inf_limit = -180  # degrees
                self.phase_sup_limit = 180  # degrees

                for i in range(4):
                    new_element = float(
                        input("\nStokes parameter S{}: ".format(i)))
                    self._stokes_parameters.append(new_element)
                self.incoming_stokes_vector = StokesVector(
                    self._stokes_parameters)

                break

            except ValueError:
                print("\nAn error occurred. Try again.")
    def calculate_external_CrystalCalculator(GEOMETRY_TYPE,
                                             CRYSTAL_NAME,
                                             THICKNESS,
                                             MILLER_H,
                                             MILLER_K,
                                             MILLER_L,
                                             ASYMMETRY_ANGLE,
                                             AZIMUTHAL_ANGLE,
                                             ENERGY_POINTS,
                                             ENERGY_MIN,
                                             ENERGY_MAX,
                                             ANGLE_DEVIATION_POINTS,
                                             ANGLE_DEVIATION_MIN,
                                             ANGLE_DEVIATION_MAX,
                                             STOKES_S0,
                                             STOKES_S1,
                                             STOKES_S2,
                                             STOKES_S3,
                                             INCLINATION_ANGLE,
                                             DUMP_TO_FILE,
                                             FILE_NAME="tmp.dat"):

        # Create a GeometryType object:
        #     Bragg diffraction = 0
        #     Bragg transmission = 1
        #     Laue diffraction = 2
        #     Laue transmission = 3
        if GEOMETRY_TYPE == 0:
            GEOMETRY_TYPE_OBJECT = BraggDiffraction()

        elif GEOMETRY_TYPE == 1:
            GEOMETRY_TYPE_OBJECT = BraggTransmission()

        elif GEOMETRY_TYPE == 2:
            GEOMETRY_TYPE_OBJECT = LaueDiffraction()

        elif GEOMETRY_TYPE == 3:
            GEOMETRY_TYPE_OBJECT = LaueTransmission()

        else:
            raise Exception(
                "CrystalCalculator: The geometry type could not be interpreted!"
            )

        # Create a diffraction setup.
        # At this stage I translate angles in radians, energy in eV and all other values in SI units.
        print("CrystalCalculator: Creating a diffraction setup...\n")

        if ENERGY_POINTS == 1:
            if ENERGY_MIN != ENERGY_MAX:
                raise Exception(
                    "CrystalCalculator: Finite energy range with only one sampled value!"
                )

        diffraction_setup = DiffractionSetupSweeps(
            geometry_type=GEOMETRY_TYPE_OBJECT,  # GeometryType object
            crystal_name=str(CRYSTAL_NAME),  # string
            thickness=float(THICKNESS) * 1e-2,  # meters
            miller_h=int(MILLER_H),  # int
            miller_k=int(MILLER_K),  # int
            miller_l=int(MILLER_L),  # int
            asymmetry_angle=float(ASYMMETRY_ANGLE) / 180 * np.pi,  # radians
            azimuthal_angle=float(AZIMUTHAL_ANGLE) / 180 * np.pi,  # radians
            energy_min=float(ENERGY_MIN),  # eV
            energy_max=float(ENERGY_MAX),  # eV
            energy_points=int(ENERGY_POINTS),  # int
            angle_deviation_min=float(ANGLE_DEVIATION_MIN) * 1e-6,  # radians
            angle_deviation_max=float(ANGLE_DEVIATION_MAX) * 1e-6,  # radians
            angle_deviation_points=int(ANGLE_DEVIATION_POINTS))  # int

        # Create a Diffraction object.
        diffraction = Diffraction()

        # Create a DiffractionResult object holding the results of the diffraction calculations.
        print("CrystalCalculator: Calculating the diffraction results...\n")
        diffraction_result = diffraction.calculateDiffraction(
            diffraction_setup)

        # Create a StokesVector object.
        incoming_stokes_vector = StokesVector(
            [STOKES_S0, STOKES_S1, STOKES_S2, STOKES_S3])

        # Create a MuellerDiffraction object.
        mueller_diffraction = MuellerDiffraction(
            diffraction_result, incoming_stokes_vector,
            float(INCLINATION_ANGLE) * np.pi / 180)

        # Create a MullerResult object.
        print("CrystalCalculator: Calculating the Stokes vector...\n")
        mueller_result = mueller_diffraction.calculate_stokes()

        # Create the data to output.
        output_data = MailingBox(diffraction_result, mueller_result)

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

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

            with open(FILE_NAME, "w") as file:
                try:
                    file.write(
                        "VALUES:\n\n"
                        "geometry type: {geometry_type}\n"
                        "crystal name: {crystal_name}\n"
                        "thickness: {thickness}\n"
                        "miller H: {miller_h}\n"
                        "miller K: {miller_k}\n"
                        "miller L: {miller_l}\n"
                        "asymmetry angle: {asymmetry_angle}\n"
                        "azimuthal angle: {azimuthal_angle}\n"
                        "energy points: {energy_points}\n"
                        "energy minimum: {energy_min}\n"
                        "energy maximum: {energy_max}\n"
                        "deviation angle points: {angle_deviation_points}\n"
                        "deviation angle minimum: {angle_deviation_min}\n"
                        "deviation angle maximum: {angle_deviation_max}\n"
                        "inclination angle: {inclination_angle}\n"
                        "incoming Stokes vector: {incoming_stokes_vector}\n\n"
                        "RESULTS:\n\n"
                        "S-Polarization:\n"
                        "Intensity: {s_intensity}\n"
                        "Phase: {s_phase}\n\n"
                        "P-Polarization:\n"
                        "Intensity: {p_intensity}\n"
                        "Phase: {p_phase}\n\n"
                        "SP-Difference:\n"
                        "Intensity: {sp_intensity}\n"
                        "Phase: {sp_phase}\n\n"
                        "Stokes vector:\n"
                        "S0: {s0}\n"
                        "S1: {s1}\n"
                        "S2: {s2}\n"
                        "S3: {s3}\n\n"
                        "Degree of circular polarization: {pol_degree}".format(
                            geometry_type=GEOMETRY_TYPE_OBJECT.description(),
                            crystal_name=CRYSTAL_NAME,
                            thickness=THICKNESS,
                            miller_h=MILLER_H,
                            miller_k=MILLER_K,
                            miller_l=MILLER_L,
                            asymmetry_angle=ASYMMETRY_ANGLE,
                            azimuthal_angle=AZIMUTHAL_ANGLE,
                            energy_points=ENERGY_POINTS,
                            energy_min=ENERGY_MIN,
                            energy_max=ENERGY_MAX,
                            angle_deviation_points=ANGLE_DEVIATION_POINTS,
                            angle_deviation_min=ANGLE_DEVIATION_MIN,
                            angle_deviation_max=ANGLE_DEVIATION_MAX,
                            inclination_angle=INCLINATION_ANGLE,
                            incoming_stokes_vector=incoming_stokes_vector.
                            components(),
                            s_intensity=diffraction_result.sIntensityByEnergy(
                                ENERGY_MIN),
                            s_phase=diffraction_result.sPhaseByEnergy(
                                ENERGY_MIN, deg=True),
                            p_intensity=diffraction_result.pIntensityByEnergy(
                                ENERGY_MIN),
                            p_phase=diffraction_result.pPhaseByEnergy(
                                ENERGY_MIN, deg=True),
                            sp_intensity=diffraction_result.
                            differenceIntensityByEnergy(ENERGY_MIN),
                            sp_phase=diffraction_result.
                            differencePhaseByEnergy(ENERGY_MIN, deg=True),
                            s0=mueller_result.s0_by_energy(ENERGY_MIN),
                            s1=mueller_result.s1_by_energy(ENERGY_MIN),
                            s2=mueller_result.s2_by_energy(ENERGY_MIN),
                            s3=mueller_result.s3_by_energy(ENERGY_MIN),
                            pol_degree=mueller_result.
                            polarization_degree_by_energy(ENERGY_MIN)))
                    file.close()
                    print("File written to disk: %s" % FILE_NAME)
                except:
                    raise Exception(
                        "CrystalCalculator: The data could not be dumped onto the specified file!"
                    )

        return output_data
Beispiel #18
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
Beispiel #19
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)
Beispiel #20
0
 def setUp(self):
     self.element_list = [
         0.78177969457877930, 0.22595711869558588, 0.28797567756487550,
         0.58551861060989900
     ]
     self.stokes_vector = StokesVector(self.element_list)
    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")
Beispiel #22
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()
Beispiel #23
0
class StokesVectorTest(unittest.TestCase):
    def setUp(self):
        self.element_list = [
            0.78177969457877930, 0.22595711869558588, 0.28797567756487550,
            0.58551861060989900
        ]
        self.stokes_vector = StokesVector(self.element_list)

    def testConstructor(self):
        self.assertIsInstance(self.stokes_vector, StokesVector)
        self.assertEqual(self.stokes_vector.s0, 0.78177969457877930)
        self.assertEqual(self.stokes_vector.s1, 0.22595711869558588)
        self.assertEqual(self.stokes_vector.s2, 0.28797567756487550)
        self.assertEqual(self.stokes_vector.s3, 0.58551861060989900)

    def testGetArray(self):
        array1 = self.stokes_vector.components()
        array2 = self.stokes_vector.getList()

        self.assertEqual(type(array1), np.ndarray)
        self.assertEqual(type(array2), list)
        np.testing.assert_array_equal(array1, np.asarray(self.element_list))
        self.assertListEqual(array2, self.element_list)

    def testPolarizationDegree(self):
        pol_deg = self.stokes_vector.circularPolarizationDegree()
        self.assertEqual(type(pol_deg), float)
        self.assertAlmostEqual(pol_deg, 0.7489560226111716)

    def test_operator_equal(self):
        stokes_vector1 = self.stokes_vector
        stokes_vector2 = StokesVector([
            0.7817796945787793, 0.22595711869558588, 0.2879756775648755,
            0.585518610609899
        ])  # without final zeros
        stokes_vector3 = StokesVector([
            round(0.78177969457877930, 6),
            round(0.22595711869558588, 6),
            round(0.28797567756487550, 6),
            round(0.58551861060989900, 6)
        ])  # rounded float
        self.assertTrue(stokes_vector1 == stokes_vector1)  # identity
        self.assertTrue(stokes_vector1 == stokes_vector2)
        self.assertFalse(stokes_vector1 == stokes_vector3)

    def test_operator_not_equal(self):
        stokes_vector1 = self.stokes_vector
        stokes_vector2 = StokesVector([
            0.7817796945787793, 0.22595711869558588, 0.2879756775648755,
            0.585518610609899
        ])  # without final zeros
        stokes_vector3 = StokesVector([
            round(0.78177969457877930, 6),
            round(0.22595711869558588, 6),
            round(0.28797567756487550, 6),
            round(0.58551861060989900, 6)
        ])  # rounded float
        self.assertFalse(stokes_vector1 != stokes_vector1)
        self.assertFalse(stokes_vector1 != stokes_vector2)
        self.assertTrue(stokes_vector1 != stokes_vector3)

    def testDuplicate(self):
        v1 = StokesVector([1, 2, 3, 4])
        v2 = v1.duplicate()

        self.assertTrue(v1 == v2)

        v1.setFromValues(0, 2, 3, 4)

        self.assertFalse(v1 == v2)