def simSonoraSpc(tAl2O3, e0, det, wkDst=5, lt=100, pc=1, nTraj=1000, xtraParams={}): """simSonoraSpc(tAl2O3, e0, det, wkDst=5, lt=100, pc=1, nTraj=1000, xtraParams={}) Simulate a spectrum from tAl2O3 nm of Al2O3 on Al recoreed at e0 kV using the DTSA detector det and a wkDst mm working distance for lt sec with a probe current of pc nA. Compute nTraj trajectories.""" tAl = 100 # um al2o3 = dt2.material("Al2O3",density=3.95) al = dt2.material("Al", density=2.70) lAl2O3 = [al2o3, tAl2O3*1.0e-9] lAl = [al, tAl*1.0e-6] lay = [lAl2O3, lAl] sNam = "%g-nm-Al2O3-on-Al-%g-kV" % (tAl2O3, e0) spc = dt2.wrap(mc3.multiFilm(lay, det, e0, True, nTraj, lt*pc, True, True, xtraParams)) props=spc.getProperties() props.setTextProperty(epq.SpectrumProperties.SpectrumDisplayName, sNam) props.setNumericProperty(epq.SpectrumProperties.LiveTime, lt) props.setNumericProperty(epq.SpectrumProperties.FaradayBegin, pc) props.setNumericProperty(epq.SpectrumProperties.BeamEnergy, e0) props.setNumericProperty(epq.SpectrumProperties.WorkingDistance, wkDst) return(spc)
def suggestTransitions(mat, e0=20.0): """suggestTransitions(mat, e0=20.0) Suggest a list of transitions for the specified material.""" mat = dtsa2.material(mat) xrts = ("%s K-L3", "%s K-M3", "%s L3-M5", "%s L2-N4", "%s M5-N7", "%s M4-N6") res = [] for elm in mat.getElementSet(): for xrt in xrts: tr = dtsa2.transition(xrt % elm.toAbbrev()) if tr.exists() and (tr.getEnergy() < 0.95 * epq.ToSI.keV(e0)) and (tr.getEnergy() > epq.ToSI.keV(0.2)): res.append(tr) return res
def simulate(mat, det, e0=20.0, dose=defaultDose, withPoisson=True, nTraj=defaultNumTraj, sf=defaultCharFluor, bf=defaultBremFluor, xtraParams=defaultXtraParams): """simulate(mat,det,[e0=20.0],[withPoisson=True],[nTraj=defaultNumTraj],[dose=defaultDose],[sf=defaultCharFluor],[bf=defaultBremFluor],[xtraParams=defaultXtraParams]) Simulate a bulk spectrum for the material mat on the detector det at beam energy e0 (in keV). If \ sf then simulate characteristic secondary fluorescence. If bf then simulate bremsstrahlung secondary \ fluorescence. nTraj specifies the number of electron trajectories. dose is in nA*sec.""" mat = dtsa2.material(mat) if not isinstance(mat, epq.Material): print u"Please provide a material with a density - %s" % mat tmp = u"MC simulation of bulk %s at %0.1f keV%s%s" % (mat, e0, (" + CSF" if sf else ""), (" + BSF" if bf else "")) print tmp res = base(det, e0, withPoisson, nTraj, dose, sf, bf, tmp, buildBulk, { "Material" : mat }, xtraParams) res.getProperties().setCompositionProperty(epq.SpectrumProperties.StandardComposition, mat) return res
def simNiCuPetSpc(tNi, tCu, e0, det, wkDst=17, lt=100, pc=1, nTraj=1000): """simNiCuPetSpc(tNi, tCu, e0, det, wkDst=17, lt=100, pc=1, nTraj=1000) Simulate a spectrum from tNi nm of Ni on tCu nm of Cu on PET recoreded at e0 kV using the DTSA detector det and a wkDst mm working distance for lt sec with a probe current of pc nA. Compute nTraj trajectories.""" tPET = 76 # um pet = dt2.material("C10H8O4",density=1.37) cu = dt2.material("Cu", density=8.96) ni = dt2.material("Ni", density=8.90) lNi = [ni, tNi*1.0e-9] lCu = [cu, tCu*1.0e-9] lPET = [pet, tPET*1.0e-6] lay = [lNi, lCu, lPET] sNam = "%g-nm-Ni-%g-nm-Cu-on-PET-%g-kV" % (tNi, tCu, e0) spc = dt2.wrap(mc3.multiFilm(lay, det, e0, True, nTraj, lt*pc, True, True)) props=spc.getProperties() props.setTextProperty(epq.SpectrumProperties.SpectrumDisplayName, sNam) props.setNumericProperty(epq.SpectrumProperties.LiveTime, lt) props.setNumericProperty(epq.SpectrumProperties.FaradayBegin, pc) props.setNumericProperty(epq.SpectrumProperties.BeamEnergy, e0) props.setNumericProperty(epq.SpectrumProperties.WorkingDistance, wkDst) return(spc)
def addMeasurement(spec, mat): """addMeasurement(spec, mat) Add a QC entry based on the specified spectrum collected from the named material. / The spectrum must define the probe current and detector properties.""" comp = d2.material("__QC__[%s]" % mat) if not comp: comp = d2.material(mat) if not comp: raise "Please specify a known material." comp.setName(mat) det = spec.getProperties().getDetector() if not det: raise "Please specify a detector in the spectrum properties." det = d2.Database.getEarliestCalibrated(det) beamE = spec.getProperties().getNumericWithDefault( epq.SpectrumProperties.BeamEnergy, 0.0) if beamE == 0.0: raise "Please specify the beam energy in the spectrum properties." qcp = d2.Database.getQCProject(det, comp, beamE) mode = d2.Datab data = epq.SpectrumFitter7.performQC(det, comp, spec, None) d2.Database.addQC(qcp, spec, data) print "%s added to %s" % (spec, d2.Database.describeQCProject(qcp))
def ranges(comp, e0, over=1.5): """Example: ranges(createMaterial(),5.0,1.5) Prints a list of edges, over voltages, and ionization ranges (in meters) for the specified material at the specified beam energy in keV (5.0) and required overvoltage (1.5)""" print "Shell\tOver\tRange (m)" comp = dtsa2.material(comp) for elm in comp.getElementSet(): elm = dtsa2.element(elm) sh = maxEdge(elm, e0, over) if sh != None: print "%s\t%g\t%e" % ( sh, e0 / epq.FromSI.keV(sh.getEdgeEnergy()), epq.ElectronRange.KanayaAndOkayama1972.compute( comp, sh, epq.ToSI.keV(e0)) / comp.getDensity()) else: print "%s\tNone\tNone" % elm
def suggestTransitionSets(mat, e0=20.0): """suggestTransitions(mat, e0=20.0) Suggest a list of XRayTransitionSet objects for the specified material.""" mat = dtsa2.material(mat) fams = ("Ka", "Kb", "La", "Lb", "Ma", "Mb") res = [] for elm in mat.getElementSet(): for fam in fams: xrts = dtsa2.getTransitionSet(elm, fam) removeMe = epq.XRayTransitionSet() if (xrts.size() > 0): for xrt in xrts: ee = epq.FromSI.keV(xrt.getEnergy()) if (ee < 0.2) or (ee > 0.95 * e0): removeMe.add(xrt) if removeMe.size() > 0: xrts.removeAll(removeMe) if xrts.size() > 0: res.append(xrts) return res
def stemCell(h2oThickness, objMat, objDiameter, objDepth, e0, beamOffset=0.0, detectorDistance=0.008, detectorRadius=0.02, detRingCount=100, nTraj=10000): """stemCell(h2oThickness, objMat, objDiameter, objDepth, e0, [beamOffset=0.0], [detectorDistance=0.008], [detectorRadius=0.02], [detRingCount=100], [nTraj=10000]): Model scattering from a spherical object embedded in a suspended water film. Example: > import dtsa2.stemCell as sc > sc.stemCell(1.0e-6, material("Au",10.0), 2.0e-7, 4.0e-7, 100.0,nTraj=1000)""" monte = nm.MonteCarloSS() monte.setBeamEnergy(epq.ToSI.keV(e0)) beam = nm.GaussianBeam(1.0e-10) beam.setCenter((beamOffset, 0.0, -0.01)) monte.setElectronGun(beam) h2o = d2.material("H2O", 1.0) h2oThickness = max(h2oThickness, objDiameter) objDepth = max(0.5 * objDiameter, min(h2oThickness - 0.5 * objDiameter, objDepth)) h2oSr = monte.addSubRegion( monte.getChamber(), h2o, nm.MultiPlaneShape.createFilm((0.0, 0.0, -1.0), (0.0, 0.0, 0.0), h2oThickness)) monte.addSubRegion(h2oSr, objMat, nm.Sphere((0.0, 0.0, objDepth), 0.5 * objDiameter)) ann = nm.AnnularDetector(detectorRadius, detRingCount, (0.0, 0.0, detectorDistance), (0.0, 0.0, -1.0)) monte.addActionListener(ann) monte.runMultipleTrajectories(nTraj) header = "Parameters:\nWater thickness\t%g nm\nSphere material\t%s\nSphere diameter\t%g nm\nSphere center depth\t%g nm\nBeam offset\t%g nm\nDetector distance\t%g mm\nDetector radius\t%g mm\nE0\t%g keV" % ( 1.0e9 * h2oThickness, objMat.descriptiveString(False), 1.0e9 * objDiameter, 1.0e9 * objDepth, 1.0e9 * beamOffset, 1.0e3 * detectorDistance, 1.0e3 * detectorRadius, e0) print header return (header, ann)
def simCarbonCoatedStd(mat, det, e0, nTraj, lt=100, pc=1.0, tc=20.0): """simCarbonCoatedStd(mat, det, e0, nTraj, lt=100, pc=1.0, tc=20.0) Use mc3 multilayer simulation to simulate a C-ctd standard specimen Parameters ---------- mat - a dtsa material. Note the material must have an associated density. It should have a useful name. det - a dtsa detector Here is where we get the detector properties and calibration e0 - float The accelerating voltage in kV nTraj - integer The number of trajectories to run lt - integer (100) The live time (sec) pc - float (1.0) The probe current in nA tc - float (20.0) C thickness in nm Returns ------- sim - DTSA scriptable spectrum The simulated standard spectrum Example ------- import dtsa2.jmMC3 as jm3 det = findDetector("Si(Li)") mgo = material("MgO", density=3.58) a = jm3.simCarbonCoatedStd(mgo, det, 20.0, 100, 100, 1.0, 20.0) a.display() """ dose = pc * lt # na-sec" c = dt2.material("C", density=2.1) layers = [[c, tc * 1.0e-9], [mat, 50.0e-6]] xrts = [] trs = mc3.suggestTransitions(c, e0) for tr in trs: xrts.append(tr) trs = mc3.suggestTransitions(mat, e0) for tr in trs: xrts.append(tr) xtraParams = {} xtraParams.update(mc3.configureXRayAccumulators(xrts, True, True, True)) sim = mc3.multiFilm(layers, det, e0, withPoisson=True, nTraj=nTraj, dose=dose, sf=True, bf=True, xtraParams=xtraParams) sName = "%g-nm-C-on-%s-%g-kV-%g-Traj" % (tc, mat, e0, nTraj) sim.rename(sName) sim.setAsStandard(mat) return sim
def simCtdOxOnSi(det, e0, nTraj, lt=100, pc=1.0, tox=10.0, tc=20.0): """ simCtdOxOnSi(det, e0, nTraj, lt=100, pc=1.0, tox = 10.0, tc=20.0) Use mc3 multilayer simulation to simulate a C-ctd silicon specimen with a native oxide layer. det - a dtsa detector Here is where we get the detector properties and calibration e0 - float The accelerating voltage in kV nTraj - integer The number of trajectories to run lt - integer (100) The live time (sec) pc - float (1.0) The probe current in nA tox - float (10.0) The thickness of the native oxide in nm tc - float (20.0) C thickness in nm Returns ------- sim - DTSA scriptable spectrum The simulated spectrum Example ------- import dtsa2.jmMC3 as jm3 det = findDetector("Si(Li)") a = jm3.simCtdOxOnSi(det, 3.0, 100, 100, 1.0, 10.0, 20.0) a.display() """ c = dt2.material("C", density=2.1) si = dt2.material("Si", density=2.329) sio2 = dt2.material("SiO2", density=2.65) dose = pc * lt # na-sec" layers = [[c, tc * 1.0e-9], [sio2, tox * 1.0e-9], [si, 50.0e-6]] xrts = [] trs = mc3.suggestTransitions(c, e0) for tr in trs: xrts.append(tr) trs = mc3.suggestTransitions(sio2, e0) for tr in trs: xrts.append(tr) xtraParams = {} xtraParams.update(mc3.configureXRayAccumulators(xrts, True, True, True)) sim = mc3.multiFilm(layers, det, e0, withPoisson=True, nTraj=nTraj, dose=dose, sf=True, bf=True, xtraParams=xtraParams) sName = "%g-nm-C-on-%g-nm-SiO2-on-Si-%g-kV-%g-Traj" % (tc, tox, e0, nTraj) sim.rename(sName) return sim
def zaf(comp, det, e0, nTraj=defaultNumTraj, stds={}): """zaf(comp, det, e0, nTraj = 1000, stds=None) Example: mc3.zaf(material("Al2O3",1),d2,10.0,stds={ "Al":"Al", "O":"MgO" }) The Monte Carlo equivalent of dtsa2.zaf(comp,det,e0,stds) in the base DTSA-II scripting package. \ Tabulates the ZAF corrections as computed from Monte Carlo simulations of the generated and emitted x-ray \ intensities normalized relative to the specified standards (or if no standards are specified relative to \ pure elements)""" def doMonte(cc): monte = nm.MonteCarloSS() monte.setBeamEnergy(epq.ToSI.keV(e0)) monte.addSubRegion(chamber, cc, nm.MultiPlaneShape.createSubstrate([0.0, 0.0, -1.0], origin)) # Add event listeners to model characteristic radiation chXR = nm3.CharacteristicXRayGeneration3.create(monte) chTr = nm3.XRayTransport3.create(monte, det, chXR) xrel = nm3.XRayAccumulator3(xrts, "Characteristic") chTr.addXRayListener(xrel) fxg3 = nm3.FluorescenceXRayGeneration3.create(monte, chXR) chSFTr = nm3.XRayTransport3.create(monte, det, fxg3) chSF = nm3.XRayAccumulator3(xrts, "Secondary") chSFTr.addXRayListener(chSF) det.reset() monte.runMultipleTrajectories(nTraj) return (xrel, chSF) comp = dtsa2.material(comp, 1.0) print u"Material\t%s" % comp.descriptiveString(0) print u"Detector\t%s" % det print u"Algorithm\t%s" % "Monte Carlo (Gen3)" print u"MAC\t%s" % epq.AlgorithmUser.getDefaultMAC().getName() print u"E0\t%0.1f keV" % e0 print u"Take-off\t%g%s" % (jl.Math.toDegrees(epq.SpectrumUtils.getTakeOffAngle(det.getProperties())), epq.SpectrumProperties.TakeOffAngle.getUnits()) elms = comp.getElementSet() allStds = {} for elm, std in stds.iteritems(): allStds[dtsa2.element(elm)] = dtsa2.material(std, 1.0) for elm in elms: if not allStds.has_key(elm): allStds[elm] = dtsa2.material(elm.toAbbrev(), 1.0) origin = epq.SpectrumUtils.getSamplePosition(det.getProperties()) xrts = dtsa2.majorTransitions(comp, e0, thresh=0.8) xrel, chSF = {}, {} for elm in elms: xrel[elm], chSF[elm] = doMonte(allStds[elm]) # Run unknown xrelu, chSFu = doMonte(dtsa2.material(comp, 1.0)) print u"\nIUPAC\tSeigbahn\tStandard\tEnergy\t ZAF\t Z\t A\t F\tk-ratio" for elm in elms: xrels = xrel[elm] chSFs = chSF[elm] cu = comp.weightFraction(elm, False) cs = allStds[elm].weightFraction(elm, False) for xrt in xrts: if xrt.getElement().equals(elm) and (xrels.getEmitted(xrt) > 0.0) and (xrelu.getEmitted(xrt) > 0.0): try: # print "%g\t%g\t%g\t%g" % (xrelu.getGenerated(xrt), xrelu.getEmitted(xrt),xrels.getGenerated(xrt), xrels.getEmitted(xrt) ) a = (xrelu.getEmitted(xrt) * xrels.getGenerated(xrt)) / (xrelu.getGenerated(xrt) * xrels.getEmitted(xrt)) z = (cs * xrelu.getGenerated(xrt)) / (cu * xrels.getGenerated(xrt)) f = (1.0 + chSFu.getEmitted(xrt) / xrelu.getEmitted(xrt)) / (1.0 + chSFs.getEmitted(xrt) / xrels.getEmitted(xrt)) k = (xrelu.getEmitted(xrt) / xrels.getEmitted(xrt)) * f eTr = epq.FromSI.keV(xrt.getEnergy()) print u"%s\t%s\t%s\t%2.4f\t%1.4f\t%1.4f\t%1.4f\t%1.4f\t%1.4f" % (xrt, xrt.getSiegbahnName(), allStds[elm], eTr, z * a * f, z, a, f, k) except: print u"%s - %s" % (elm, xrt)
def createGas(comp, pascal): """createGas(comp, pascal) Create a gas from a composition at the specified pressure in Pascal at 300 K. Ex: createGas("H2O", 0.1)""" return epq.Gas(dtsa2.material(comp), pascal, 300.0)
def backscatterCoefficient(mat, e0=20.0): """backscatterCoefficient(mat, e0=20.0) Computes eta, the backscatter coefficient, for the specified material (element) and beam energy keV.""" return epq.BackscatterCoefficient.Heinrich81.compute(dtsa2.material(mat),epq.ToSI.keV(e0))
def backscatterFraction(mat, e0=20.0): """backscatterFraction(mat) Computes the backscatter fraction for an element or composition""" mat=dtsa2.material(mat) return epq.BackscatterCoefficient.Heinrich81.compute(mat,epq.ToSI.keV(e0))
def simCarbonCoatedStd(mat, det, e0, nTraj, lt=100, pc=1.0, tc=20.0): """simCarbonCoatedStd(mat, det, e0, nTraj, lt=100, pc=1.0, tc=20.0) Use mc3 multilayer simulation to simulate a C-ctd standard specimen Parameters ---------- mat - a dtsa material. Note the material must have an associated density. It should have a useful name. det - a dtsa detector Here is where we get the detector properties and calibration e0 - float The accelerating voltage in kV nTraj - integer The number of trajectories to run lt - integer (100) The live time (sec) pc - float (1.0) The probe current in nA tc - float (20.0) C thickness in nm Returns ------- sim - DTSA scriptable spectrum The simulated standard spectrum Example ------- import dtsa2.jmMC3 as jm3 det = findDetector("Oxford p4 05eV 2K") mgo = material("MgO", density=3.58) a = jm3.simCarbonCoatedStd(mgo, det, 20.0, 100, 100, 1.0, 20.0) a.display() """ dose = pc * lt # na-sec" c = dt2.material("C", density=2.1) layers = [ [ c, tc*1.0e-9], [mat, 50.0e-6] ] xrts = [] trs = mc3.suggestTransitions(c, e0) for tr in trs: xrts.append(tr) trs = mc3.suggestTransitions(mat, e0) for tr in trs: xrts.append(tr) xtraParams={} xtraParams.update(mc3.configureXRayAccumulators(xrts,True, True, True)) sim = mc3.multiFilm(layers, det, e0, withPoisson=True, nTraj=nTraj, dose=dose, sf=True, bf=True, xtraParams=xtraParams) sName = "%g-nm-C-on-%s-%g-kV-%g-Traj" % (tc, mat, e0, nTraj) sim.rename(sName) sim.setAsStandard(mat) return sim
def simCtdOxOnSi(det, e0, nTraj, lt=100, pc=1.0, tox = 10.0, tc=20.0): """ simCtdOxOnSi(det, e0, nTraj, lt=100, pc=1.0, tox = 10.0, tc=20.0) Use mc3 multilayer simulation to simulate a C-ctd silicon specimen with a native oxide layer. det - a dtsa detector Here is where we get the detector properties and calibration e0 - float The accelerating voltage in kV nTraj - integer The number of trajectories to run lt - integer (100) The live time (sec) pc - float (1.0) The probe current in nA tox - float (10.0) The thickness of the native oxide in nm tc - float (20.0) C thickness in nm Returns ------- sim - DTSA scriptable spectrum The simulated spectrum Example ------- import dtsa2.jmMC3 as jm3 det = findDetector("Oxford p4 05eV 2K") a = jm3.simCtdOxOnSi(det, 3.0, 100, 100, 1.0, 10.0, 20.0) a.display() """ c = dt2.material("C", density=2.1) si = dt2.material("Si", density=2.329) sio2 = dt2.material("SiO2", density=2.65) dose = pc * lt # na-sec" layers = [ [ c, tc*1.0e-9], [sio2, tox*1.0e-9], [si, 50.0e-6] ] xrts = [] trs = mc3.suggestTransitions(c, e0) for tr in trs: xrts.append(tr) trs = mc3.suggestTransitions(sio2, e0) for tr in trs: xrts.append(tr) xtraParams={} xtraParams.update(mc3.configureXRayAccumulators(xrts,True, True, True)) sim = mc3.multiFilm(layers, det, e0, withPoisson=True, nTraj=nTraj, dose=dose, sf=True, bf=True, xtraParams=xtraParams) sName = "%g-nm-C-on-%g-nm-SiO2-on-Si-%g-kV-%g-Traj" % (tc, tox, e0, nTraj) sim.rename(sName) return sim