Esempio n. 1
0
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
Esempio n. 2
0
 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
Esempio n. 3
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
Esempio n. 4
0
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
Esempio n. 5
0
    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
Esempio n. 6
0
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))
Esempio n. 7
0
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