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