Example #1
0
    def testAllGeometryTypes(self):
        all_geometries = GeometryType.allGeometryTypes()

        self.assertIn(BraggDiffraction(), all_geometries)
        self.assertIn(LaueDiffraction(), all_geometries)
        self.assertIn(BraggTransmission(), all_geometries)
        self.assertIn(LaueTransmission(), all_geometries)
Example #2
0
    def testCalculateDiffraction(self):
        res = {}
        for geometry_type in GeometryType.allGeometryTypes():
            effective_asymmetry = 0.0
            if geometry_type == LaueDiffraction(
            ) or geometry_type == LaueTransmission():
                effective_asymmetry = 90.0 * numpy.pi / 180

            diffraction_setup = DiffractionSetupSweeps(
                geometry_type,
                "Si",
                thickness=128 * 1e-6,
                miller_h=1,
                miller_k=1,
                miller_l=1,
                asymmetry_angle=effective_asymmetry,
                azimuthal_angle=0.0,
                energy_min=8174,
                energy_max=8174,
                energy_points=1,
                angle_deviation_min=-20.0e-6,
                angle_deviation_max=20e-6,
                angle_deviation_points=5)
            diffraction = Diffraction()
            res[geometry_type] = diffraction.calculateDiffraction(
                diffraction_setup)
Example #3
0
    def _checkSetup(self, diffraction_setup, bragg_angle, F_0, F_H, F_H_bar):
        """
        Checks if a given diffraction setup is possible, i.e. if a given Diffraction/Transmission for the given asymmetry
        and Miller indices is possible. Raises an exception if impossible.
        :param diffraction_setup: Diffraction setup.
        :param bragg_angle: Bragg angle.
        :param F_0: Structure factor F_0.
        :param F_H: Structure factor F_H.
        :param F_H_bar: Structure factor F_H_bar.
        """
        # Check if the given geometry is a valid Bragg/Laue geometry.
        if diffraction_setup.geometryType() == BraggDiffraction(
        ) or diffraction_setup.geometryType() == BraggTransmission():
            if diffraction_setup.asymmetryAngle() >= bragg_angle:
                raise ReflectionImpossibleException()
        elif diffraction_setup.geometryType() == LaueDiffraction(
        ) or diffraction_setup.geometryType() == LaueTransmission():
            if diffraction_setup.asymmetryAngle() <= bragg_angle:
                raise TransmissionImpossibleException()

        # Check structure factor F_0.
        if abs(F_0.real) < 1e-7 or isnan(F_0.real):
            raise StructureFactorF0isZeroException()

        # Check structure factor F_H.
        if abs(F_H.real) < 1e-7 or isnan(
                F_H.real) or abs(F_H.imag) < 1e-7 or isnan(F_H.imag):
            raise StructureFactorFHisZeroException()

        # Check structure factor F_H_bar.
        if abs(F_H_bar.real) < 1e-7 or isnan(
                F_H_bar.real) or abs(F_H_bar.imag) < 1e-7 or isnan(
                    F_H_bar.imag):
            raise StructureFactorFHbarIsZeroException()
Example #4
0
 def _checkSetupDiffraction(self, diffraction_setup, bragg_angle):
     """
     Checks if a given diffraction setup is possible, i.e. if a given Diffraction/Transmission for the given asymmetry
     and Miller indices is possible. Raises an exception if impossible.
     :param diffraction_setup: Diffraction setup.
     :param bragg_angle: Bragg angle.
     """
     # Check if the given geometry is a valid Bragg/Laue geometry.
     if diffraction_setup.geometryType() == BraggDiffraction(
     ) or diffraction_setup.geometryType() == BraggTransmission():
         if diffraction_setup.asymmetryAngle() >= bragg_angle:
             raise ReflectionImpossibleException()
     elif diffraction_setup.geometryType() == LaueDiffraction(
     ) or diffraction_setup.geometryType() == LaueTransmission():
         if diffraction_setup.asymmetryAngle() <= bragg_angle:
             raise TransmissionImpossibleException()
Example #5
0
 def testCalculateLaueTransmission(self):
     diffraction_setup = DiffractionSetupSweeps(LaueTransmission(),
                                          "Si",
                                          thickness=100 * 1e-6,
                                          miller_h=1,
                                          miller_k=1,
                                          miller_l=1,
                                          asymmetry_angle=90*numpy.pi/180,
                                          azimuthal_angle=0.0,
                                          energy_min=10000,
                                          energy_max=10000,
                                          energy_points=1,
                                          angle_deviation_min= -20.0e-6,
                                          angle_deviation_max=20.0e-6,
                                          angle_deviation_points=5)
     diffraction = Diffraction()
     res = diffraction.calculateDiffraction(diffraction_setup)
def generatePerfectCrystalDiffraction():

    # Si(111), E=3124eV
    angle_bragg = 0.685283
    psi_0 = -0.00010047702301 - 0.00001290853605j
    psi_H = -0.00004446850675 + 0.00003155997069j
    psi_H_bar = -0.00003155997069 - 0.00004446850675j
    d_spacing = 3.135416 * 1e-10

    geometry_type = LaueTransmission()
    normal_bragg = Vector(0, 0, 1).scalarMultiplication(2.0 * pi / d_spacing)
    normal_surface = Vector(1.0, 0.0, 0.0)

    thickness = 128 * 1e-6

    perfect_crystal_diffraction = PerfectCrystalDiffraction(
        geometry_type, normal_bragg, normal_surface, angle_bragg, psi_0, psi_H,
        psi_H_bar, thickness, d_spacing)

    return perfect_crystal_diffraction
    def testConstructor(self):
        perfect_crystal_diffraction = generatePerfectCrystalDiffraction()

        self.assertIsInstance(perfect_crystal_diffraction,
                              PerfectCrystalDiffraction)
        self.assertEqual(perfect_crystal_diffraction.geometryType(),
                         LaueTransmission())
        self.assertEqual(
            perfect_crystal_diffraction.braggNormal(),
            Vector(0, 0,
                   1).scalarMultiplication(2.0 * pi / (3.135416 * 1e-10)))
        self.assertEqual(perfect_crystal_diffraction.surface_normal(),
                         Vector(1, 0, 0))
        self.assertEqual(perfect_crystal_diffraction.braggAngle(), 0.685283)
        self.assertAlmostEqual(perfect_crystal_diffraction.Psi0(),
                               -0.00010047702301 - 0.00001290853605j)
        self.assertAlmostEqual(perfect_crystal_diffraction.PsiH(),
                               -0.00004446850675 + 0.00003155997069j)
        self.assertAlmostEqual(perfect_crystal_diffraction.PsiHBar(),
                               -0.00003155997069 - 0.00004446850675j)
        self.assertAlmostEqual(perfect_crystal_diffraction.dSpacing(),
                               3.135416 * 1e-10)
        self.assertAlmostEqual(perfect_crystal_diffraction.thickness(),
                               128 * 1e-6)
    def _calculateComplexAmplitude(self, photon_in, zac_q, zac_z, gamma_0,
                                   effective_psi_h_bar):
        """
        Calculates the complex amplitude of the questioned wave: diffracted or transmission.
        :param photon_in: Incoming photon.
        :param zac_q: q as defined in Zachariasen [3-123].
        :param zac_z: z as defined in Zachariasen [3-123].
        :param gamma_0: Projection cosine as defined in Zachariasen [3-115].
        :param effective_psi_h_bar: Effective PsiHBar (depending of polarisation. See text following [3.-139]).
        :return: Complex amplitude.
        """
        # Calculate geometry independent parts.
        tmp_root = (zac_q + zac_z * zac_z)**0.5

        zac_x1 = (-1.0 * zac_z + tmp_root) / effective_psi_h_bar
        zac_x2 = (-1.0 * zac_z - tmp_root) / effective_psi_h_bar
        zac_delta1 = 0.5 * (self.Psi0() - zac_z + tmp_root)
        zac_delta2 = 0.5 * (self.Psi0() - zac_z - tmp_root)
        zac_phi1 = 2 * pi / gamma_0 / photon_in.wavelength() * zac_delta1
        zac_phi2 = 2 * pi / gamma_0 / photon_in.wavelength() * zac_delta2

        zac_c1 = -1j * self.thickness() * zac_phi1
        zac_c2 = -1j * self.thickness() * zac_phi2

        if self.isDebug:
            self.logDebug("__zac_c1" + str(zac_c1))
            self.logDebug("__zac_c2" + str(zac_c2))

        cv_zac_c1 = self._exponentiate(zac_c1)
        cv_zac_c2 = self._exponentiate(zac_c2)

        cv_zac_x1 = self._createVariable(zac_x1)
        cv_zac_x2 = self._createVariable(zac_x2)

        # Calculate complex amplitude according to given geometry.
        if self.geometryType() == BraggDiffraction():
            complex_amplitude = cv_zac_x1 * cv_zac_x2 * (cv_zac_c2 - cv_zac_c1) / \
                                (cv_zac_c2 * cv_zac_x2 - cv_zac_c1 * cv_zac_x1)
        elif self.geometryType() == LaueDiffraction():
            complex_amplitude = cv_zac_x1 * cv_zac_x2 * (cv_zac_c1 - cv_zac_c2) / \
                                (cv_zac_x2 - cv_zac_x1)
        elif self.geometryType() == BraggTransmission():
            complex_amplitude = cv_zac_c1 * cv_zac_c2 * (cv_zac_x2 - cv_zac_x1) / \
                                (cv_zac_c2 * cv_zac_x2 - cv_zac_c1 * cv_zac_x1)
        elif self.geometryType() == LaueTransmission():
            complex_amplitude = (cv_zac_x2 * cv_zac_c1 - cv_zac_x1 * cv_zac_c2) / \
                                (cv_zac_x2 - cv_zac_x1)
        else:
            raise Exception

        if self.isDebug:
            self.logDebug("ctemp: " + str(tmp_root))
            self.logDebug("zac_z" + str(zac_z))
            self.logDebug("zac_q" + str(zac_q))
            self.logDebug("zac delta 1" + str(zac_delta1))
            self.logDebug("zac delta 2" + str(zac_delta2))
            self.logDebug("gamma_0" + str(gamma_0))
            self.logDebug("wavelength" + str(photon_in.wavelength()))
            self.logDebug("zac phi 1" + str(zac_phi1))
            self.logDebug("zac phi 2" + str(zac_phi2))
            self.logDebug("zac_c1: " + str(cv_zac_c1))
            self.logDebug("zac_c2: " + str(cv_zac_c2))
            self.logDebug("zac_x1: " + str(cv_zac_x1))
            self.logDebug("zac_x2: " + str(cv_zac_x2))

        return ComplexAmplitude(complex(complex_amplitude))
    def _calculatePhotonOut(self, photon_in):
        """
        Solves the Laue equation to calculates the outgoing photon from the incoming photon and the Bragg normal.
        :param photon_in: Incoming photon.
        :return: Outgoing photon.
        """
        # # Retrieve k_0.
        # k_in = photon_in.wavevector()

        # # Solve unscaled Laue equation.
        # k_out = self.braggNormal().addVector(k_in)

        # Create photon in k_out direction and scale by setting the photon energy.
        # photon_out = Photon(photon_in.energy(), k_out)
        """
        GENERAL VERSION:
        Solves the Laue equation for the parallel components of the vectors and
        uses the conservation of the wavevector modulus to calculate the outgoing wavevector
        even for diffraction not at the Bragg angle.
        """
        # Retrieve k_0.
        k_in = photon_in.wavevector()

        # Decompose the vector into a component parallel to the surface normal and
        # a component parallel to the surface: (k_in * n) n.
        k_in_normal = self.surface_normal().scalarMultiplication(
            k_in.scalarProduct(self.surface_normal()))
        k_in_parallel = k_in.subtractVector(k_in_normal)

        # Retrieve the B_H vector.
        B_H = self.braggNormal()

        # Decompose the vector into a component parallel to the surface normal and
        # a component parallel to the surface: (B_H * n) n.
        B_H_normal = self.surface_normal().scalarMultiplication(
            B_H.scalarProduct(self.surface_normal()))
        B_H_parallel = B_H.subtractVector(B_H_normal)

        # Apply the Laue formula for the parallel components.
        k_out_parallel = k_in_parallel.addVector(B_H_parallel)

        # Calculate K_out normal.
        k_out_normal_modulus = sqrt(k_in.norm()**2 - k_out_parallel.norm()**2)
        k_out_normal = self.surface_normal().scalarMultiplication(
            k_out_normal_modulus)

        # # Calculate the outgoing photon.
        # # changed [email protected] to negative normal component to take into account that crystal normal points
        # # outsize
        # k_out_1 = k_out_parallel.addVector(k_out_normal)
        # k_out_2 = k_out_parallel.scalarMultiplication(-1.0).addVector(k_out_normal)
        #
        # # select k_out_1 or k_out_2
        #
        # k_out_Ewald = photon_in.unitDirectionVector().scalarMultiplication(photon_in.wavenumber())
        # k_out_Ewald = k_out_Ewald.addVector(B_H)
        # k_out_Ewald = k_out_Ewald.getNormalizedVector()
        #
        # tmp1 = k_out_1.scalarProduct(k_out_Ewald)
        # tmp2 = k_out_2.scalarProduct(k_out_Ewald)

        # TODO: try to put some logic here
        if self.geometryType() == BraggDiffraction():
            k_out = k_out_parallel.addVector(k_out_normal)
        elif self.geometryType() == LaueDiffraction():
            k_out = k_out_parallel.addVector(
                k_out_normal.scalarMultiplication(-1.0))
        elif self.geometryType() == BraggTransmission():
            k_out = k_out_parallel.addVector(k_out_normal)
        elif self.geometryType() == LaueTransmission():
            k_out = k_out_parallel.addVector(
                k_out_normal.scalarMultiplication(-1.0))
        else:
            raise Exception

        photon_out = photon_in.duplicate()
        photon_out.setUnitDirectionVector(k_out)

        if self.isDebug:
            self.logDebug("surface normal" +
                          str(self.surface_normal().components()))
            self.logDebug("Angle bragg normal photon_in" + str(
                (photon_in.unitDirectionVector().angle(self.braggNormal()),
                 pi * 0.5 -
                 photon_in.unitDirectionVector().angle(self.braggNormal()))))
            self.logDebug("Angle bragg normal photon_out" + str(
                (photon_out.unitDirectionVector().angle(self.braggNormal()),
                 pi * 0.5 -
                 photon_out.unitDirectionVector().angle(self.braggNormal()))))
            self.logDebug("photon_in direction" +
                          str(photon_in.unitDirectionVector().components()))
            self.logDebug("photon_out direction" +
                          str(photon_out.unitDirectionVector().components()))

        # Return outgoing photon.
        return photon_out
def calculate_with_crystalpy(
        bragg_or_laue=0,  #
        diffracted_or_transmitted=0,  #
        crystal_name="Si",  # string
        thickness=1e-2,  # meters
        miller_h=1,  # int
        miller_k=1,  # int
        miller_l=1,  # int
        asymmetry_angle=0.0,  # radians
        energy=8000.0,  # eV
        angle_deviation_min=-100e-6,  # radians
        angle_deviation_max=100e-6,  # radians
        angle_deviation_points=500,
        method=0,  # 0=crystalpy input, 1=shadow4 preprocessor file
):

    if bragg_or_laue == 0:
        if diffracted_or_transmitted == 0:
            geometry_type = BraggDiffraction()
        elif diffracted_or_transmitted == 1:
            geometry_type = BraggTransmission()
        else:
            raise Exception("Bad geometry type")
    elif bragg_or_laue == 1:
        if diffracted_or_transmitted == 0:
            geometry_type = LaueDiffraction()
        elif diffracted_or_transmitted == 1:
            geometry_type = LaueTransmission()
        else:
            raise Exception("Bad geometry type")
    else:
        raise Exception("Bad geometry type")

    # Create a diffraction setup.

    # print("\nCreating a diffraction setup...")
    if method == 0:
        diffraction_setup = DiffractionSetup(geometry_type=geometry_type,
                                             crystal_name=crystal_name,
                                             thickness=thickness,
                                             miller_h=miller_h,
                                             miller_k=miller_k,
                                             miller_l=miller_l,
                                             asymmetry_angle=asymmetry_angle,
                                             azimuthal_angle=0.0)
    else:
        create_bragg_preprocessor_file_v1(interactive=False,
                                          DESCRIPTOR=crystal_name,
                                          H_MILLER_INDEX=miller_h,
                                          K_MILLER_INDEX=miller_k,
                                          L_MILLER_INDEX=miller_l,
                                          TEMPERATURE_FACTOR=1.0,
                                          E_MIN=5000.0,
                                          E_MAX=15000.0,
                                          E_STEP=100.0,
                                          SHADOW_FILE="bragg_xop.dat")

        diffraction_setup = DiffractionSetupShadowPreprocessor(
            geometry_type=geometry_type,
            crystal_name=crystal_name,
            thickness=thickness,
            miller_h=miller_h,
            miller_k=miller_k,
            miller_l=miller_l,
            asymmetry_angle=asymmetry_angle,
            azimuthal_angle=0.0,
            preprocessor_file="bragg_xop.dat")

    angle_step = (angle_deviation_max -
                  angle_deviation_min) / angle_deviation_points

    #
    # gets Bragg angle needed to create deviation's scan
    #
    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 (the calculator)
    diffraction = Diffraction()

    # initialize arrays for storing outputs
    deviations = numpy.zeros(angle_deviation_points)
    intensityS = numpy.zeros(angle_deviation_points)
    intensityP = numpy.zeros(angle_deviation_points)

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

        # angle = deviation  + bragg_angle + asymmetry_angle
        # # calculate the components of the unitary vector of the incident photon scan
        # # Note that diffraction plane is YZ
        # yy = numpy.cos(angle)
        # zz = - numpy.abs(numpy.sin(angle))
        # photon = Photon(energy_in_ev=energy,direction_vector=Vector(0.0,yy,zz))

        k_unitary = diffraction_setup.incomingPhotonDirection(
            energy, deviation)

        # or equivalently
        # k_0_unitary = diffraction_setup.incomingPhotonDirection(energy, 0.0)
        # k_unitary = k_0_unitary.rotateAroundAxis( Vector(1.0,0.0,0.0), -deviation)

        photon = Photon(energy_in_ev=energy, direction_vector=k_unitary)

        # perform the calculation
        coeffs = diffraction.calculateDiffractedComplexAmplitudes(
            diffraction_setup, photon)
        # store results
        deviations[ia] = deviation
        intensityS[ia] = coeffs['S'].intensity()
        intensityP[ia] = coeffs['P'].intensity()

    return deviations, intensityS, intensityP
    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
Example #12
0
    def calculate_external_Crystal(GEOMETRY_TYPE,
                                          CRYSTAL_NAME,
                                          THICKNESS,
                                          MILLER_H,
                                          MILLER_K,
                                          MILLER_L,
                                          ASYMMETRY_ANGLE,
                                          AZIMUTHAL_ANGLE,
                                          incoming_bunch,
                                          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("Crystal: The geometry type could not be interpreted!\n")

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

        diffraction_setup = DiffractionSetup(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
                                             # incoming_photons=incoming_bunch)

        # Create a Diffraction object.
        diffraction = Diffraction()

        # Create a PolarizedPhotonBunch object holding the results of the diffraction calculations.
        print("Crystal: Calculating the outgoing photons...\n")
        outgoing_bunch = diffraction.calculateDiffractedPolarizedPhotonBunch(diffraction_setup,
                                                                    incoming_bunch,
                                                                    INCLINATION_ANGLE)

        # Check that the result of the calculation is indeed a PolarizedPhotonBunch object.
        if not isinstance(outgoing_bunch, PolarizedPhotonBunch):
            raise Exception("Crystal: Expected PolarizedPhotonBunch as a result, found {}!\n".format(type(outgoing_bunch)))

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

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

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

        return outgoing_bunch
Example #13
0
    def testCheckSetup(self):
        diffraction = Diffraction()

        diffraction_setup = DiffractionSetupSweeps(
            BraggDiffraction(),
            "Si",
            thickness=128 * 1e-6,
            miller_h=1,
            miller_k=1,
            miller_l=1,
            asymmetry_angle=0,
            azimuthal_angle=0.0,
            energy_min=8174,
            energy_max=8174,
            energy_points=1,
            angle_deviation_min=-20.0e-6,
            angle_deviation_max=20e-6,
            angle_deviation_points=5)

        angle_bragg = 0.19902705045
        F_0 = 113.581288 + 1.763808j
        F_H = 43.814631 - 42.050823J
        F_H_bar = 42.050823 + 43.814631j

        # Test possible setup.
        diffraction._checkSetup(diffraction_setup, angle_bragg, F_0, F_H,
                                F_H_bar)

        # Test impossible Bragg reflection.
        diffraction_setup._asymmetry_angle = 45 * numpy.pi / 180

        self.assertRaises(ReflectionImpossibleException,
                          diffraction._checkSetup, diffraction_setup,
                          angle_bragg, F_0, F_H, F_H_bar)

        diffraction_setup._geometry_type = BraggTransmission()
        self.assertRaises(ReflectionImpossibleException,
                          diffraction._checkSetup, diffraction_setup,
                          angle_bragg, F_0, F_H, F_H_bar)

        # Test impossible Laue reflection.
        diffraction_setup._asymmetry_angle = 10 * numpy.pi / 180

        diffraction_setup._geometry_type = LaueDiffraction()
        self.assertRaises(TransmissionImpossibleException,
                          diffraction._checkSetup, diffraction_setup,
                          angle_bragg, F_0, F_H, F_H_bar)

        diffraction_setup._geometry_type = LaueTransmission()
        self.assertRaises(TransmissionImpossibleException,
                          diffraction._checkSetup, diffraction_setup,
                          angle_bragg, F_0, F_H, F_H_bar)

        # Test forbidden reflection
        diffraction_setup._geometry_type = BraggDiffraction()
        diffraction_setup._asymmetry_angle = 0

        # ... for F_0.
        self.assertRaises(StructureFactorF0isZeroException,
                          diffraction._checkSetup, diffraction_setup,
                          angle_bragg, 0.0, F_H, F_H_bar)

        # ... for F_H.
        self.assertRaises(StructureFactorFHisZeroException,
                          diffraction._checkSetup, diffraction_setup,
                          angle_bragg, F_0, 0.0, F_H_bar)

        self.assertRaises(StructureFactorFHisZeroException,
                          diffraction._checkSetup, diffraction_setup,
                          angle_bragg, F_0,
                          float('nan') * 1j, F_H_bar)

        # ... for F_H_bar.
        self.assertRaises(StructureFactorFHbarIsZeroException,
                          diffraction._checkSetup, diffraction_setup,
                          angle_bragg, F_0, F_H, 0.0)

        self.assertRaises(StructureFactorFHbarIsZeroException,
                          diffraction._checkSetup, diffraction_setup,
                          angle_bragg, F_0, F_H,
                          float('nan') * 1j)
Example #14
0
 def testConstructor(self):
     laue_transmission = LaueTransmission()
     self.assertEqual(laue_transmission.description(), "Laue transmission")
 def testGeometryType(self):
     perfect_crystal_diffraction = generatePerfectCrystalDiffraction()
     self.assertEqual(perfect_crystal_diffraction.geometryType(),
                      LaueTransmission())
def calculate_with_crystalpy(
    bragg_or_laue=0,  #
    diffracted_or_transmitted=0,  #
    crystal_name="Si",  # string
    thickness=1e-2,  # meters
    miller_h=1,  # int
    miller_k=1,  # int
    miller_l=1,  # int
    asymmetry_angle=0.0,  # radians
    energy=8000.0,  # eV
    angle_deviation_min=-100e-6,  # radians
    angle_deviation_max=100e-6,  # radians
    angle_deviation_points=500,
):

    if bragg_or_laue == 0:
        if diffracted_or_transmitted == 0:
            geometry_type = BraggDiffraction()
        elif diffracted_or_transmitted == 1:
            geometry_type = BraggTransmission()
        else:
            raise Exception("Bad geometry type")
    elif bragg_or_laue == 1:
        if diffracted_or_transmitted == 0:
            geometry_type = LaueDiffraction()
        elif diffracted_or_transmitted == 1:
            geometry_type = LaueTransmission()
        else:
            raise Exception("Bad geometry type")
    else:
        raise Exception("Bad geometry type")

    # Create a diffraction setup.

    print("\nCreating a diffraction setup...")
    diffraction_setup = DiffractionSetup(geometry_type=geometry_type,
                                         crystal_name=crystal_name,
                                         thickness=thickness,
                                         miller_h=miller_h,
                                         miller_k=miller_k,
                                         miller_l=miller_l,
                                         asymmetry_angle=asymmetry_angle,
                                         azimuthal_angle=0.0)

    # 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

    #
    # gets Bragg angle needed to create deviation's scan
    #
    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 (the calculator)
    diffraction = Diffraction()

    # initialize arrays for storing outputs
    deviations = numpy.zeros(angle_deviation_points)
    intensityS = numpy.zeros(angle_deviation_points)
    intensityP = numpy.zeros(angle_deviation_points)

    k_0_unitary = diffraction_setup.incomingPhotonDirection(energy, 0.0)
    # photon_0 = Photon(energy_in_ev=energy,direction_vector=k_0_unitary)
    # k_H_unitary = diffraction_setup._
    # print(">>>>>>>>>>>>>>>>>>>>>>>>k_0: ",k_0_unitary._components )

    # plot_crystal_sketch(k_0_unitary,k_0_unitary,)

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

        # angle = deviation  + bragg_angle + asymmetry_angle
        # # calculate the components of the unitary vector of the incident photon scan
        # # Note that diffraction plane is YZ
        # yy = numpy.cos(angle)
        # zz = - numpy.abs(numpy.sin(angle))
        # photon = Photon(energy_in_ev=energy,direction_vector=Vector(0.0,yy,zz))

        k_unitary = diffraction_setup.incomingPhotonDirection(
            energy, deviation)

        # or equivalently
        # k_0_unitary = diffraction_setup.incomingPhotonDirection(energy, 0.0)
        # k_unitary = k_0_unitary.rotateAroundAxis( Vector(1.0,0.0,0.0), -deviation)

        photon = Photon(energy_in_ev=energy, direction_vector=k_unitary)

        # perform the calculation
        coeffs = diffraction.calculateDiffractedComplexAmplitudes(
            diffraction_setup, photon)

        # store results
        deviations[ia] = deviation
        intensityS[ia] = coeffs['S'].intensity()
        intensityP[ia] = coeffs['P'].intensity()

    # print(">>>>>>>>>>>>>>>>>>>>>>>>k_0: ",k_0_unitary._components,k_0_unitary.getNormalizedVector()._components )
    return deviations, intensityS, intensityP