示例#1
0
    def __init__(
        self,
        geometry_type=None,
        crystal_name="",
        thickness=1e-6,
        miller_h=1,
        miller_k=1,
        miller_l=1,
        asymmetry_angle=0.0,
        azimuthal_angle=0.0,
    ):
        """
        Constructor.
        :param geometry_type: GeometryType (BraggDiffraction,...).
        :param crystal_name: The name of the crystal, e.g. Si.
        :param thickness: The crystal thickness.
        :param miller_h: Miller index H.
        :param miller_k: Miller index K.
        :param miller_l: Miller index L.
        :param asymmetry_angle: The asymmetry angle between surface normal and Bragg normal (radians).
        :param azimuthal_angle: The angle between the projection of the Bragg normal
                                on the crystal surface plane and the x axis (radians).
        """
        super().__init__(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=azimuthal_angle)

        # Load crystal from xraylib.
        self._crystal = xraylib.Crystal_GetCrystal(self.crystalName())
示例#2
0
def calc_Bragg_angle(crystal='Si', energy=8, h=1, k=1, l=1, corrected=False):
    '''
    Calculates Bragg angle using xraylib.
    
    Parameters:
        
    - crystal: crystal material. [str]
    - energy: energy in keV. [float]
    - h, k, l: Miller indexes. [int]
    
    Returns:
    
    - bragg: Bragg angle in rad. [float] 
    
    '''

    cryst = xraylib.Crystal_GetCrystal(crystal)

    bragg = xraylib.Bragg_angle(cryst, energy, h, k, l)

    if (corrected):
        w0 = calc_rocking_curve_shift(crystal=crystal,
                                      energy=energy,
                                      h=h,
                                      k=k,
                                      l=l,
                                      rel_angle=1,
                                      debye_temp_factor=1)
        bragg += w0

    return bragg
示例#3
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
示例#4
0
    def testCalculatePsiFromStructureFactor(self):
        diffraction = Diffraction()
        crystal = xraylib.Crystal_GetCrystal("Si")
        photon_in = Photon(8000, Vector(-1, 0, -1))
        structure_factor = 113.581288 + 1.763808j

        unitcell_volume = crystal['volume'] * 10**-30
        psi = diffraction._calculatePsiFromStructureFactor(
            unitcell_volume, photon_in, structure_factor)
        self.assertAlmostEqual(psi.real, -1.527826e-5)
        self.assertAlmostEqual(psi.imag, -2.372566e-7)
示例#5
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
示例#6
0
    def __init__(
        self,
        geometry_type,
        crystal_name,
        thickness,
        miller_h,
        miller_k,
        miller_l,
        asymmetry_angle,
        azimuthal_angle,
    ):
        """
        Constructor.
        :param geometry_type: GeometryType (BraggDiffraction,...).
        :param crystal_name: The name of the crystal, e.g. Si.
        :param thickness: The crystal thickness.
        :param miller_h: Miller index H.
        :param miller_k: Miller index K.
        :param miller_l: Miller index L.
        :param asymmetry_angle: The asymmetry angle between surface normal and Bragg normal (radians).
        :param azimuthal_angle: The angle between the projection of the Bragg normal
                                on the crystal surface plane and the x axis (radians).
        """
        self._geometry_type = geometry_type
        self._crystal_name = crystal_name
        self._thickness = thickness
        self._miller_h = miller_h
        self._miller_k = miller_k
        self._miller_l = miller_l
        self._asymmetry_angle = asymmetry_angle  # degrees

        # Edoardo: I add an azimuthal angle.
        self._azimuthal_angle = azimuthal_angle  # degrees

        # Set Debye Waller factor.
        self._debyeWaller = 1.0

        # Load crystal from xraylib.
        self._crystal = xraylib.Crystal_GetCrystal(self.crystalName())
示例#7
0
    def test_crystal_diffraction(self):
        crystals_list = xraylib.Crystal_GetCrystalsList()
        self.assertEqual(len(crystals_list), 38)
        for crystal_name in crystals_list:
            cs = xraylib.Crystal_GetCrystal(crystal_name)
            self.assertEqual(crystal_name, cs['name'])

        with self.assertRaises(ValueError):
            cs = xraylib.Crystal_GetCrystal(None)

        with self.assertRaises(ValueError):
            cs = xraylib.Crystal_GetCrystal("non-existent-crystal")

        cs = xraylib.Crystal_GetCrystal("Diamond") 

        cs_copy = xraylib.Crystal_MakeCopy(cs)

        with self.assertRaises(ValueError):
            xraylib.Crystal_AddCrystal(cs)

        with self.assertRaises(ValueError):
            xraylib.Crystal_AddCrystal(cs_copy)

        cs_copy['name'] = "Diamond-copy"
        xraylib.Crystal_AddCrystal(cs_copy)

        cs_copy['name'] = 20012016
        with self.assertRaises(TypeError):
            xraylib.Crystal_AddCrystal(cs_copy)

        cs_copy['name'] = "Diamond-copy"

        cs_copy['atom'] = list()
        with self.assertRaises(TypeError):
            xraylib.Crystal_AddCrystal(cs_copy)

        cs_copy['atom'] = (25, "jkewjfpwejffj", None, )
        with self.assertRaises(TypeError):
            xraylib.Crystal_AddCrystal(cs_copy)

        del cs_copy['atom']

        with self.assertRaises(KeyError):
            xraylib.Crystal_AddCrystal(cs_copy)

        crystals_list = xraylib.Crystal_GetCrystalsList()
        self.assertEqual(len(crystals_list), 39)

        for crystal_name in crystals_list:
            cs = xraylib.Crystal_GetCrystal(crystal_name)
            self.assertEqual(crystal_name, cs['name'])

        current_ncrystals = len(crystals_list)

        for i in range(xraylib.CRYSTALARRAY_MAX):
            cs_copy = xraylib.Crystal_MakeCopy(cs)
            cs_copy['name'] = "Diamond copy {}".format(i)
            if current_ncrystals < xraylib.CRYSTALARRAY_MAX:
                xraylib.Crystal_AddCrystal(cs_copy)
                current_ncrystals = current_ncrystals + 1
                self.assertEqual(len(xraylib.Crystal_GetCrystalsList()), current_ncrystals)
            else:
                with self.assertRaises(RuntimeError):
                    xraylib.Crystal_AddCrystal(cs_copy)
                self.assertEqual(len(xraylib.Crystal_GetCrystalsList()), xraylib.CRYSTALARRAY_MAX)

        cs = xraylib.Crystal_GetCrystal("Diamond") 

        # Bragg angle
        angle = xraylib.Bragg_angle(cs, 10.0, 1, 1, 1)
        self.assertAlmostEqual(angle, 0.3057795845795849)

        with self.assertRaises(TypeError):
            angle = xraylib.Bragg_angle(None, 10.0, 1, 1, 1)

        with self.assertRaises(ValueError):
            angle = xraylib.Bragg_angle(cs, -10.0, 1, 1, 1)

        with self.assertRaises(TypeError):
            angle = xraylib.Bragg_angle(cs, 1, 1, 1)

        
	# Q_scattering_amplitude
        tmp = xraylib.Q_scattering_amplitude(cs, 10.0, 1, 1, 1, math.pi/4.0)
        self.assertAlmostEqual(tmp, 0.19184445408324474)

        tmp = xraylib.Q_scattering_amplitude(cs, 10.0, 0, 0, 0, math.pi/4.0)
        self.assertEqual(tmp, 0.0)

        # Atomic factors
        (f0, f_prime, f_prime2) = xraylib.Atomic_Factors(26, 10.0, 1.0, 10.0)
        self.assertAlmostEqual(f0, 65.15)
        self.assertAlmostEqual(f_prime, -0.22193271025027966)
        self.assertAlmostEqual(f_prime2, 22.420270655080493)

        with self.assertRaises(ValueError):
            (f0, f_prime, f_prime2) = xraylib.Atomic_Factors(-10, 10.0, 1.0, 10.0)

        # unit cell volume
        tmp = xraylib.Crystal_UnitCellVolume(cs)
        self.assertAlmostEqual(tmp, 45.376673902751)

        # crystal dspacing
        tmp = xraylib.Crystal_dSpacing(cs, 1, 1, 1)
        self.assertAlmostEqual(tmp, 2.0592870875248344)

        del cs
示例#8
0
    def new_bragg(cls,
                  DESCRIPTOR="Graphite",
                  H_MILLER_INDEX=0,
                  K_MILLER_INDEX=0,
                  L_MILLER_INDEX=2,
                  TEMPERATURE_FACTOR=1.0,
                  E_MIN=5000.0,
                  E_MAX=15000.0,
                  E_STEP=100.0,
                  SHADOW_FILE="bragg.dat"):
        """
         SHADOW preprocessor for crystals - python+xraylib version

         -"""
        # retrieve physical constants needed
        codata = scipy.constants.codata.physical_constants
        codata_e2_mc2, tmp1, tmp2 = codata["classical electron radius"]
        # or, hard-code them
        # In [179]: print("codata_e2_mc2 = %20.11e \n" % codata_e2_mc2 )
        # codata_e2_mc2 =    2.81794032500e-15

        fileout = SHADOW_FILE
        descriptor = DESCRIPTOR

        hh = int(H_MILLER_INDEX)
        kk = int(K_MILLER_INDEX)
        ll = int(L_MILLER_INDEX)

        temper = float(TEMPERATURE_FACTOR)

        emin = float(E_MIN)
        emax = float(E_MAX)
        estep = float(E_STEP)

        #
        # end input section, start calculations
        #

        f = open(fileout, 'wt')

        cryst = xraylib.Crystal_GetCrystal(descriptor)
        volume = cryst['volume']

        #test crystal data - not needed
        itest = 1
        if itest:
            if (cryst == None):
                sys.exit(1)
            print("  Unit cell dimensions are %f %f %f" %
                  (cryst['a'], cryst['b'], cryst['c']))
            print("  Unit cell angles are %f %f %f" %
                  (cryst['alpha'], cryst['beta'], cryst['gamma']))
            print("  Unit cell volume is %f A^3" % volume)
            print("  Atoms at:")
            print("     Z  fraction    X        Y        Z")
            for i in range(cryst['n_atom']):
                atom = cryst['atom'][i]
                print("    %3i %f %f %f %f" %
                      (atom['Zatom'], atom['fraction'], atom['x'], atom['y'],
                       atom['z']))
            print("  ")

        volume = volume * 1e-8 * 1e-8 * 1e-8  # in cm^3
        #flag ZincBlende
        f.write("%i " % 0)
        #1/V*electronRadius
        f.write("%e " % ((1e0 / volume) * (codata_e2_mc2 * 1e2)))
        #dspacing
        dspacing = xraylib.Crystal_dSpacing(cryst, hh, kk, ll)
        f.write("%e " % (dspacing * 1e-8))
        f.write("\n")
        #Z's
        atom = cryst['atom']
        f.write("%i " % atom[0]["Zatom"])
        f.write("%i " % atom[-1]["Zatom"])
        f.write("%e " % temper)  # temperature parameter
        f.write("\n")

        ga = (1e0+0j) + cmath.exp(1j*cmath.pi*(hh+kk))  \
                                 + cmath.exp(1j*cmath.pi*(hh+ll))  \
                                 + cmath.exp(1j*cmath.pi*(kk+ll))
        gb = ga * cmath.exp(1j * cmath.pi * 0.5 * (hh + kk + ll))
        ga_bar = ga.conjugate()
        gb_bar = gb.conjugate()

        f.write("(%20.11e,%20.11e ) \n" % (ga.real, ga.imag))
        f.write("(%20.11e,%20.11e ) \n" % (ga_bar.real, ga_bar.imag))
        f.write("(%20.11e,%20.11e ) \n" % (gb.real, gb.imag))
        f.write("(%20.11e,%20.11e ) \n" % (gb_bar.real, gb_bar.imag))

        zetas = numpy.array([atom[0]["Zatom"], atom[-1]["Zatom"]])
        for zeta in zetas:
            xx01 = 1e0 / 2e0 / dspacing
            xx00 = xx01 - 0.1
            xx02 = xx01 + 0.1
            yy00 = xraylib.FF_Rayl(int(zeta), xx00)
            yy01 = xraylib.FF_Rayl(int(zeta), xx01)
            yy02 = xraylib.FF_Rayl(int(zeta), xx02)
            xx = numpy.array([xx00, xx01, xx02])
            yy = numpy.array([yy00, yy01, yy02])
            fit = numpy.polyfit(xx, yy, 2)
            #print "zeta: ",zeta
            #print "z,xx,YY: ",zeta,xx,yy
            #print "fit: ",fit[::-1] # reversed coeffs
            #print "fit-tuple: ",(tuple(fit[::-1].tolist())) # reversed coeffs
            #print("fit-tuple: %e %e %e  \n" % (tuple(fit[::-1].tolist())) ) # reversed coeffs
            f.write("%e %e %e  \n" %
                    (tuple(fit[::-1].tolist())))  # reversed coeffs

        npoint = int((emax - emin) / estep + 1)
        f.write(("%i \n") % npoint)
        for i in range(npoint):
            energy = (emin + estep * i)
            f1a = xraylib.Fi(int(zetas[0]), energy * 1e-3)
            f2a = xraylib.Fii(int(zetas[0]), energy * 1e-3)
            f1b = xraylib.Fi(int(zetas[1]), energy * 1e-3)
            f2b = xraylib.Fii(int(zetas[1]), energy * 1e-3)
            out = numpy.array([energy, f1a, abs(f2a), f1b, abs(f2b)])
            f.write(("%20.11e %20.11e %20.11e \n %20.11e %20.11e \n") %
                    (tuple(out.tolist())))

        f.close()
        print("File written to disk: %s" % fileout)
示例#9
0
print(
    "Pb Malpha XRF production cs at 20.0 keV with non-radiative cascade effect: {}"
    .format(
        xraylib.CS_FluorLine_Kissel_Nonradiative_Cascade(
            82, xraylib.MA1_LINE, 20.0)))
print("Pb Malpha XRF production cs at 20.0 keV without cascade effect: {}".
      format(xraylib.CS_FluorLine_Kissel_no_Cascade(82, xraylib.MA1_LINE,
                                                    20.0)))
print("Al mass energy-absorption cs at 20.0 keV: {}".format(
    xraylib.CS_Energy(13, 20.0)))
print("Pb mass energy-absorption cs at 40.0 keV: {}".format(
    xraylib.CS_Energy(82, 40.0)))
print("CdTe mass energy-absorption cs at 40.0 keV: {}".format(
    xraylib.CS_Energy_CP("CdTe", 40.0)))

cryst = xraylib.Crystal_GetCrystal("Si")
if cryst is None:
    raise KeyError('Diamond crystal not found')

print("Si unit cell dimensions are {} {} {}".format(cryst['a'], cryst['b'],
                                                    cryst['c']))
print("Si unit cell angles are {} {} {}".format(cryst['alpha'], cryst['beta'],
                                                cryst['gamma']))
print("Si unit cell volume is {}".format(cryst['volume']))
print("Si atoms at:")
print("   Z  fraction    X        Y        Z")
for i in range(cryst['n_atom']):
    atom = cryst['atom'][i]
    print("  {} {} {} {} {}".format(atom['Zatom'], atom['fraction'], atom['x'],
                                    atom['y'], atom['z']))
print("")
def bragg():
    """
     SHADOW preprocessor for crystals - python+xraylib version

     -""" 
    # retrieve physical constants needed
    codata = scipy.constants.codata.physical_constants
    codata_e2_mc2, tmp1, tmp2 = codata["classical electron radius"]
    # or, hard-code them
    # In [179]: print("codata_e2_mc2 = %20.11e \n" % codata_e2_mc2 )
    # codata_e2_mc2 =    2.81794032500e-15

    print("bragg: SHADOW preprocessor for crystals - python+xraylib version")
    fileout = raw_input("Name of output file : ")
    f = open(fileout, 'wb')

    print(" bragg (python) only works now for ZincBlende Cubic structures. ")
    print(" Valid descriptor are: ")
    print("     Si (alternatiovely Si_NIST, Si2) ")
    print("     Ge")
    print("     Diamond")
    print("     GaAs, GaSb, GaP")
    print("     InAs, InP, InSb")
    print("     SiC")

    descriptor = raw_input("Name of crystal descriptor : ")
    cryst = xraylib.Crystal_GetCrystal(descriptor)

    #test crystal data - not needed
    itest = 1
    if itest: 
        if (cryst == None):
            sys.exit(1)
        print "  Unit cell dimensions are %f %f %f" % (cryst['a'],cryst['b'],cryst['c'])
        print "  Unit cell angles are %f %f %f" % (cryst['alpha'],cryst['beta'],cryst['gamma'])
        volume = cryst['volume']
        print "  Unit cell volume is %f" % volume
        volume = volume*1e-8*1e-8*1e-8 # in cm^3
        print "  Atoms at:"
        print "     Z  fraction    X        Y        Z"
        for i in range(cryst['n_atom']):
            atom =  cryst['atom'][i]
            print "    %3i %f %f %f %f" % (atom['Zatom'], atom['fraction'], atom['x'], atom['y'], atom['z'])
        print "  "

    print("Miller indices of crystal plane of reflection.")
    miller = raw_input("H K L: ")
    miller = miller.split()
    hh = int(miller[0])
    kk = int(miller[1])
    ll = int(miller[2])

    #flag ZincBlende
    f.write( "%i " % 0) 
    #1/V*electronRadius
    f.write( "%e " % ((1e0/volume)*(codata_e2_mc2*1e2)) ) 
    #dspacing
    dspacing = xraylib.Crystal_dSpacing(cryst, hh, kk, ll)
    f.write( "%e " % (dspacing*1e-8) ) 
    f.write( "\n")
    #Z's
    atom =  cryst['atom']
    f.write( "%i " % atom[0]["Zatom"] )
    f.write( "%i " % atom[7]["Zatom"] )
    temper = raw_input("Temperature (Debye-Waller) factor (set 1 for default): ")
    temper = float(temper)
    f.write( "%e " % temper ) # temperature parameter
    f.write( "\n")

    ga = (1e0+0j) + cmath.exp(1j*cmath.pi*(hh+kk))  \
                             + cmath.exp(1j*cmath.pi*(hh+ll))  \
                             + cmath.exp(1j*cmath.pi*(kk+ll))
    gb = ga * cmath.exp(1j*cmath.pi*0.5*(hh+kk+ll))
    ga_bar = ga.conjugate()
    gb_bar = gb.conjugate()


    f.write( "(%20.11e,%20.11e ) \n" % (ga.real, ga.imag) ) 
    f.write( "(%20.11e,%20.11e ) \n" % (ga_bar.real, ga_bar.imag) ) 
    f.write( "(%20.11e,%20.11e ) \n" % (gb.real, gb.imag) ) 
    f.write( "(%20.11e,%20.11e ) \n" % (gb_bar.real, gb_bar.imag) ) 

    zetas = numpy.array([atom[0]["Zatom"],atom[7]["Zatom"]])
    for zeta in zetas:
        xx01 = 1e0/2e0/dspacing
        xx00 = xx01-0.1
        xx02 = xx01+0.1
        yy00= xraylib.FF_Rayl(int(zeta),xx00)
        yy01= xraylib.FF_Rayl(int(zeta),xx01)
        yy02= xraylib.FF_Rayl(int(zeta),xx02)
        xx = numpy.array([xx00,xx01,xx02])
        yy = numpy.array([yy00,yy01,yy02])
        fit = numpy.polyfit(xx,yy,2)
        #print "zeta: ",zeta
        #print "z,xx,YY: ",zeta,xx,yy
        #print "fit: ",fit[::-1] # reversed coeffs
        #print "fit-tuple: ",(tuple(fit[::-1].tolist())) # reversed coeffs
        #print("fit-tuple: %e %e %e  \n" % (tuple(fit[::-1].tolist())) ) # reversed coeffs
        f.write("%e %e %e  \n" % (tuple(fit[::-1].tolist())) ) # reversed coeffs


    emin = raw_input("minimum photon energy (eV): ")
    emin = float(emin)
    emax = raw_input("maximum photon energy (eV): ")
    emax = float(emax)
    estep = raw_input("energy step (eV): ")
    estep = float(estep)

    npoint  = int( (emax - emin)/estep + 1 )
    f.write( ("%i \n") % npoint)
    for i in range(npoint): 
        energy = (emin+estep*i)
        f1a = xraylib.Fi(int(zetas[0]),energy*1e-3)
        f2a = xraylib.Fii(int(zetas[0]),energy*1e-3)
        f1b = xraylib.Fi(int(zetas[1]),energy*1e-3)
        f2b = xraylib.Fii(int(zetas[1]),energy*1e-3)
        out = numpy.array([energy,f1a,abs(f2a),f1b,abs(f2b)])
        f.write( ("%20.11e %20.11e %20.11e \n %20.11e %20.11e \n") % ( tuple(out.tolist()) ) )

    f.close()
    print("File written to disk: %s" % fileout)
    return None
示例#11
0
    def __init__(self):
        super().__init__()

        self._input_available = False

        # Define a tuple of crystals to choose from.
        self.crystal_names = ("Si", "Ge", "Diamond")

        print("AlignmentTool: Alignment tool initialized.\n")

        box0 = gui.widgetBox(self.controlArea, " ", orientation="horizontal")

        # widget buttons: generate, set defaults, help
        gui.button(box0, self, "Apply", callback=self.apply)
        gui.button(box0, self, "Defaults", callback=self.defaults)
        gui.button(box0, self, "Help", callback=self.get_doc)

        box = gui.widgetBox(self.controlArea, " ", orientation="vertical")

        idx = -1

        # widget index 0
        idx += 1
        box1 = gui.widgetBox(box)
        gui.lineEdit(box1,
                     self,
                     "BASE_ENERGY",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     valueType=float,
                     validator=QDoubleValidator())
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 1
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "CRYSTAL_NAME",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     items=['Si', 'Ge', 'Diamond'],
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 2
        idx += 1
        box1 = gui.widgetBox(box)
        gui.lineEdit(box1,
                     self,
                     "MILLER_H",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     valueType=int,
                     validator=QIntValidator())
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 3
        idx += 1
        box1 = gui.widgetBox(box)
        gui.lineEdit(box1,
                     self,
                     "MILLER_K",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     valueType=int,
                     validator=QIntValidator())
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 4
        idx += 1
        box1 = gui.widgetBox(box)
        gui.lineEdit(box1,
                     self,
                     "MILLER_L",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     valueType=int,
                     validator=QIntValidator())
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 5
        idx += 1
        box1 = gui.widgetBox(box)
        gui.lineEdit(box1,
                     self,
                     "ALPHA_X",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     valueType=float,
                     validator=QDoubleValidator())
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 6
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "MOA",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     items=['0', '180'],
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 7
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "MODE",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     items=['Ray-to-crystal', 'Crystal-to-ray'],
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 8
        idx += 1
        box1 = gui.widgetBox(box)
        gui.comboBox(box1,
                     self,
                     "DUMP_TO_FILE",
                     label=self.unitLabels()[idx],
                     addSpace=True,
                     items=['No', 'Yes'],
                     orientation="horizontal")
        self.show_at(self.unitFlags()[idx], box1)

        # widget index 9
        idx += 1
        box1 = gui.widgetBox(box)
        gui.lineEdit(box1,
                     self,
                     "FILE_NAME",
                     label=self.unitLabels()[idx],
                     addSpace=True)
        self.show_at(self.unitFlags()[idx], box1)

        self.process_showers()

        gui.rubber(self.controlArea)

        # Load crystal from xraylib.
        self.CRYSTAL = xraylib.Crystal_GetCrystal(
            self.crystal_names[self.CRYSTAL_NAME])
示例#12
0
#
# define miller indices, distances and photon energy in eV
#
hh = 1
kk = 1
ll = 1
d1 = 3000.0
d2 = 3000.0
alpha = 5.0 * numpy.pi / 180.0 # asymmetry angle in rad
crystal_name = "Si"
photon_energy_ev = 10000.0

#
# get crystal info from xraylib
#
cryst = xraylib.Crystal_GetCrystal(crystal_name)
dspacing = xraylib.Crystal_dSpacing(cryst,hh,kk,ll )

#sin_theta = (tocm/(photon_energy_ev*2.0*dspacing*1e-8));

#rt=2*p*q/(p+q)/sin_theta;
#rs=2*p*q*sin_theta/(p+q);

theta=numpy.arcsin(tocm/(photon_energy_ev*2.0*dspacing*1e-8))
t1 = theta + alpha
t2 = theta - alpha

#calculations

s1 = numpy.sin(t1)
s2 = numpy.sin(t2)
示例#13
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
示例#14
0
def calcTemperatureFactor(temperature,
                          crystal='Si',
                          debyeTemperature=644.92,
                          millerIndex=[1, 1, 1],
                          atomicMass=28.09,
                          dSpacing=3.1354162886330583):
    """
    Calculates the (Debye) temperature factor for single crystals.
    
    Parameters
    ----------
    temperature : float 
        Crystal temperature in Kelvin (positive number).
    crystal : str 
        Crystal single-element symbol (e.g. Si, Ge, ...).   
    debyeTemperature : float 
        Debye temperature of the crystal material in Kelvin.    
    millerIndex : array-like (1D), optional
        Miller indexes of the crystal orientation. For use with xraylib only.
    atomicMass : float, optional. 
        Atomic mass of the crystal element (amu unit). if atomicMass == 0, get from xraylib.
    dSpacing : float, optional. 
        dSpacing in Angstroms, given the crystal and millerIndex . if dSpacing == 0, get from xraylib.
        
    Returns:
    --------
    temperatureFactor : float
    
    Examples:
    ---------
        ### using xraylib:
            
        >>> calcTemperatureFactor(80, crystal='Si', millerIndex=[3,1,1], debyeTemperature=644.92, dSpacing=0, atomicMass=0)
        0.983851994268226
        
        
        ### forcing it to use given dSpacing and atomicMass:
        
        >>> calcTemperatureFactor(80, crystal='Si', millerIndex=[1,1,1], debyeTemperature=644.92, atomicMass=28.09, dSpacing=3.1354163)
        0.9955698950510736
    
    References:
    -----------
    
    [1]: A. Freund, Nucl. Instrum. and Meth. 213 (1983) 495-501
    
    [2]: M. Sanchez del Rio and R. J. Dejus, "Status of XOP: an x-ray optics software toolkit", 
         SPIE proc. vol. 5536 (2004) pp.171-174
        

    """
    def debyeFunc(x):
        return x / (np.exp(-x) - 1)

    def debyePhi(y):
        from scipy.integrate import quad
        integral = quad(lambda x: debyeFunc(x), 0, y)[0]
        return (1 / y) * integral

    planck = 6.62607015e-34  # codata.Planck
    Kb = 1.380649e-23  # codata.Boltzmann
    atomicMassTokg = 1.6605390666e-27  # codata.atomic_mass

    try:
        import xraylib
        h, k, l = millerIndex
        crystalDict = xraylib.Crystal_GetCrystal(crystal)
        if (dSpacing == 0):
            dSpacing = xraylib.Crystal_dSpacing(crystalDict, h, k, l)
        if (atomicMass == 0):
            atomicMass = xraylib.AtomicWeight(
                xraylib.SymbolToAtomicNumber(crystal))

    except:
        print(
            "xraylib not available. Please give dSpacing and atomicMass manually."
        )
        if ((dSpacing == 0) or (atomicMass == 0)):
            return np.nan

    atomicMass *= atomicMassTokg  # converting to [kg]
    dSpacing *= 1e-10  # converting to [m]

    x = debyeTemperature / (-1 * temperature)  # invert temperature sign (!!!)

    B0 = (3 * planck**2) / (2 * Kb * debyeTemperature * atomicMass)

    BT = 4 * B0 * debyePhi(x) / x

    ratio = 1 / (2 * dSpacing)

    M = (B0 + BT) * ratio**2

    temperatureFactor = np.exp(-M)

    return temperatureFactor