def calc_Darwin_width(crystal='Si', energy=8, h=1, k=1, l=1, rel_angle=1, debye_temp_factor=1): ''' Calculates Darwin width and intrinsic resolution for p and s polarizations. It uses xraylib. Parameters: - crystal: crystal material. [str] - energy: energy in keV. [float] - h, k, l: Miller indexes. [int] - rel_angle: relative angle [float] - debye_temp_factor: Debye Temperature Factor. [float] Returns: - dw_s: Angular Darwin width for s polarization in rad. [float] - dw_p: Angular Darwin width for p polarization in rad. [float] - resolution_s: Intrinsic resolution for s polarization. [float] - resolution_p: Intrinsic resolution for p polarization. [float] References: A simple formula to calculate the x-ray flux after a double-crystal monochromator - M. S. del Rio; O. MATHON. ''' cryst = xraylib.Crystal_GetCrystal(crystal) bragg = xraylib.Bragg_angle(cryst, energy, h, k, l) FH = xraylib.Crystal_F_H_StructureFactor(cryst, energy, h, k, l, debye_temp_factor, rel_angle) FHbar = xraylib.Crystal_F_H_StructureFactor(cryst, energy, -h, -k, -l, debye_temp_factor, rel_angle) C = abs(np.cos(2 * bragg)) dw_p = 1e10 * 2 * C * (xraylib.R_E / cryst['volume']) * ( xraylib.KEV2ANGST * xraylib.KEV2ANGST / (energy * energy)) * np.sqrt( abs(FH * FHbar)) / np.pi / np.sin(2 * bragg) dw_s = 1e10 * 2 * (xraylib.R_E / cryst['volume']) * ( xraylib.KEV2ANGST * xraylib.KEV2ANGST / (energy * energy)) * np.sqrt( abs(FH * FHbar)) / np.pi / np.sin(2 * bragg) resolution_p = dw_p / np.tan(bragg) resolution_s = dw_s / np.tan(bragg) return dw_s, dw_p, resolution_s, resolution_p
def F0(self, energy): """ Calculate F0 from Zachariasen. :param energy: photon energy in eV. :return: F0 """ energy_in_kev = energy / 1000.0 F_0 = xraylib.Crystal_F_H_StructureFactor(self._crystal, energy_in_kev, 0, 0, 0, self._debyeWaller, 1.0) return F_0
def FH_bar(self, energy, rel_angle=1.0): """ Calculate FH_bar from Zachariasen. :param energy: photon energy in eV. :return: FH_bar """ energy_in_kev = energy / 1000.0 F_H_bar = xraylib.Crystal_F_H_StructureFactor( self._crystal, energy_in_kev, -self.millerH(), -self.millerK(), -self.millerL(), self._debyeWaller, rel_angle) return F_H_bar
def calc_rocking_curve_shift(crystal='Si', energy=8, h=1, k=1, l=1, rel_angle=1, debye_temp_factor=1): ''' Calculates the angular shift of the Rocking Curve. It uses xraylib. Parameters: - crystal: crystal material. [str] - energy: energy in keV. [float] - h, k, l: Miller indexes. [int] - rel_angle: relative angle [float] - debye_temp_factor: Debye Temperature Factor. [float] Returns: - w0: Angular shift of the Rocking Curve in rad. [float] References: Elements of modern X-ray physics / Jens Als-Nielsen, Des McMorrow – 2nd ed. Cap. 6. ''' # Function: def calc_g(d, r0, Vc, F): return abs((2 * d * d * r0 / (Vc)) * F) # Calculating rocking curve shift: cryst = xraylib.Crystal_GetCrystal(crystal) bragg = xraylib.Bragg_angle(cryst, energy, h, k, l) r0 = physical_constants['classical electron radius'][0] F0 = xraylib.Crystal_F_H_StructureFactor(cryst, energy, 0, 0, 0, debye_temp_factor, rel_angle) d = 1e-10 * xraylib.Crystal_dSpacing(cryst, h, k, l) V = 1e-30 * cryst['volume'] g0 = calc_g(d, r0, V, F0) w0 = (g0 / (np.pi)) * np.tan(bragg) return w0
def FH(self, energy): """ Calculate FH from Zachariasen. :param energy: photon energy in eV. :return: FH """ energy_in_kev = energy / 1000.0 F_H = xraylib.Crystal_F_H_StructureFactor(self._crystal, energy_in_kev, self.millerH(), self.millerK(), self.millerL(), self._debyeWaller, 1.0) return F_H
energy = 8 debye_temp_factor = 1.0 rel_angle = 1.0 bragg = xraylib.Bragg_angle(cryst, energy, 1, 1, 1) print(" Bragg angle: Rad: {} Deg: {}".format(bragg, bragg * 180 / math.pi)) q = xraylib.Q_scattering_amplitude(cryst, energy, 1, 1, 1, rel_angle) print(" Q Scattering amplitude: {}".format(q)) #notice the 3 return values!!! f0, fp, fpp = xraylib.Atomic_Factors(14, energy, q, debye_temp_factor) print(" Atomic factors (Z = 14) f0, fp, fpp: {}, {}, i*{}".format( f0, fp, fpp)) FH = xraylib.Crystal_F_H_StructureFactor(cryst, energy, 1, 1, 1, debye_temp_factor, rel_angle) print(" FH(1,1,1) structure factor: ({}, {})".format(FH.real, FH.imag)) F0 = xraylib.Crystal_F_H_StructureFactor(cryst, energy, 0, 0, 0, debye_temp_factor, rel_angle) print(" F0=FH(0,0,0) structure factor: ({}, {})".format(F0.real, F0.imag)) # Diamond diffraction parameters cryst = xraylib.Crystal_GetCrystal("Diamond") if cryst is None: raise KeyError('Diamond crystal not found') print("") print("Diamond 111 at 8 KeV. Incidence at the Bragg angle:") bragg = xraylib.Bragg_angle(cryst, energy, 1, 1, 1) print(" Bragg angle: Rad: {} Deg: {}".format(bragg, bragg * 180 / math.pi))
def calc_Darwin_curve(delta_theta=np.linspace(-0.00015, 0.00015, 5000), crystal='Si', energy=8, h=1, k=1, l=1, rel_angle=1, debye_temp_factor=1, use_correction=True, save_txt=True, save_fig=True, filename_to_save='Darwin_curve'): ''' Calculates the Darwin curve. It does not considers absortion. Valid for s-polarization only. Parameters: - delta_theta: array containing values of (Theta - Theta_Bragg) in rad. [array] - crystal: crystal material. [str] - energy: energy in keV. [float] - h, k, l: Miller indexes. [int] - rel_angle: relative angle [float] - debye_temp_factor: Debye Temperature Factor. [float] - use_correction: if True, considers the corrected Bragg angle due to refraction. [boolean] - save_txt: if True, saves the Darwin Curve in a .txt file. [boolean] - save_fig: if True, saves a figure with the Darwin Curve in .png. [boolean] - filename_to_save: name to save the figure and the .txt file. [string] Returns: - delta_theta: Array containing values of (Theta - Theta_Bragg) in rad. [array] - R: Intensity reflectivity array. [array] - zeta_total: Total Darwin width (delta_lambda/lambda). [float] - zeta_FWHM: Darwin width FWHM (delta_lambda/lambda). [float] - w_total: Total Angular Darwin width (delta_Theta) in rad. [float] - w_FWHM: Angular Darwin width FWHM (delta_Theta) in rad. [float] - w0: Angular shift of the Rocking Curve in rad. [float] References: Elements of modern X-ray physics / Jens Als-Nielsen, Des McMorrow – 2nd ed. Cap. 6. ''' # Functions: def calc_g(d, r0, Vc, F): return abs((2 * d * d * r0 / (Vc)) * F) def calc_xc(zeta, g, g0): return np.pi * zeta / g - g0 / g def calc_zeta_total(d, r0, Vc, F): return (4 / np.pi) * (d) * (d) * (r0 * abs(F) / Vc) def Darwin_curve(xc): R = [] for x in xc: if (x >= 1): r = (x - np.sqrt(x * x - 1)) * (x - np.sqrt(x * x - 1)) if (x <= 1): r = 1 if (x <= -1): r = (x + np.sqrt(x * x - 1)) * (x + np.sqrt(x * x - 1)) R.append(r) return np.array(R) # Calculating Darwin curve: cryst = xraylib.Crystal_GetCrystal(crystal) bragg = xraylib.Bragg_angle(cryst, energy, h, k, l) zeta = delta_theta / np.tan(bragg) r0 = physical_constants['classical electron radius'][0] FH = xraylib.Crystal_F_H_StructureFactor(cryst, energy, h, k, l, debye_temp_factor, rel_angle) F0 = xraylib.Crystal_F_H_StructureFactor(cryst, energy, 0, 0, 0, debye_temp_factor, rel_angle) d = 1e-10 * xraylib.Crystal_dSpacing(cryst, h, k, l) V = 1e-30 * cryst['volume'] g = calc_g(d, r0, V, FH) g0 = calc_g(d, r0, V, F0) xc = calc_xc(zeta, g, g0) R = Darwin_curve(xc) zeta_total = calc_zeta_total(d, r0, V, FH) zeta_FWHM = (3 / (2 * np.sqrt(2))) * zeta_total w_total = zeta_total * np.tan(bragg) w_FWHM = (3 / (2 * np.sqrt(2))) * w_total w0 = (g0 / (np.pi)) * np.tan(bragg) # Correcting curve offset (due to refraction): if (use_correction): delta_theta = delta_theta - w0 # Saving .txt file: if (save_txt): filename = filename_to_save + '.txt' with open(filename, 'w') as f: f.write('#Delta_Theta[rad] Intensity_Reflectivity \n') for i in range(len(R)): f.write('%.6E\t%.6E \n' % (delta_theta[i], R[i])) # Plotting Graph: plt.figure() plt.plot(delta_theta, R, linewidth=1.8, color='black') plt.fill_between(delta_theta, R, alpha=0.9, color='C0') plt.ylabel('Intensity reflectivity', fontsize=13) plt.xlabel('$\Delta$' + '$\Theta$' + ' [rad]', fontsize=13) plt.xscale('linear') plt.yscale('linear') plt.minorticks_on() plt.ticklabel_format(style='sci', axis='x', scilimits=(0, 0)) plt.tick_params(which='both', axis='both', direction='in', right=True, top=True, labelsize=12) plt.grid(which='both', alpha=0.2) plt.tight_layout() textstr = '\n'.join((r'$\zeta_{total}=$%.4E' % (zeta_total, ), r'$\zeta_{FWHM}=$%.4E' % (zeta_FWHM, ), r'$\omega_{total}=$%.4E rad' % (w_total, ), r'$\omega_{FWHM}=$%.4E rad' % (w_FWHM, ))) props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) # wheat # gray plt.text(0.05, 0.95, textstr, transform=plt.gca().transAxes, fontsize=10, verticalalignment='top', bbox=props) plt.show() if (save_fig): plt.savefig(filename_to_save + '.png', dpi=600) return delta_theta, R, zeta_total, zeta_FWHM, w_total, w_FWHM, w0