def _getFisxDetector(fitConfiguration, attenuatorsDetector=None): distance = fitConfiguration["concentrations"]["distance"] area = fitConfiguration["concentrations"]["area"] detectorMaterial = fitConfiguration["detector"]["detele"] if attenuatorsDetector is None: # user is not interested on accounting for detection efficiency if fitConfiguration["fit"]["escapeflag"]: # but wants to account for escape peaks # we can forget about efficiency but not about detector composition # assign "infinite" efficiency density = 0.0 thickness = 0.0 fisxDetector = Detector(detectorMaterial, density=density, thickness=thickness) else: # user is not interested on considering the escape peaks fisxDetector = None else: # make sure information is consistent if attenuatorsDetector[0] not in [ detectorMaterial, detectorMaterial + "1" ]: print("%s not equal to %s" % (attenuatorsDetector[0], detectorMaterial)) msg = "Inconsistent detector material between DETECTOR and ATTENUATORS tab" msg += "\n%s not equal to %s" % (attenuatorsDetector[0], detectorMaterial) raise ValueError(msg) if len(attenuatorsDetector) == 3: fisxDetector = Detector(detectorMaterial, density=attenuatorsDetector[1], thickness=attenuatorsDetector[2]) else: fisxDetector = Detector(detectorMaterial, density=attenuatorsDetector[1], thickness=attenuatorsDetector[2], funny=attenuatorsDetector[3]) fisxDetector.setActiveArea(area) fisxDetector.setDistance(distance) if fisxDetector is not None: nThreshold = fitConfiguration["detector"]["nthreshold"] fisxDetector.setMaximumNumberOfEscapePeaks(nThreshold) return fisxDetector
def _getFisxDetector(fitConfiguration, attenuatorsDetector=None): distance = fitConfiguration["concentrations"]["distance"] area = fitConfiguration["concentrations"]["area"] detectorMaterial = fitConfiguration["detector"]["detele"] if attenuatorsDetector is None: # user is not interested on accounting for detection efficiency if fitConfiguration["fit"]["escapeflag"]: # but wants to account for escape peaks # we can forget about efficiency but not about detector composition # assign "infinite" efficiency density = 0.0 thickness = 0.0 fisxDetector = Detector(detectorMaterial, density=density, thickness=thickness) else: # user is not interested on considering the escape peaks fisxDetector = None else: # make sure information is consistent if attenuatorsDetector[0] not in [detectorMaterial, detectorMaterial+"1"]: _logger.warning("%s not equal to %s", attenuatorsDetector[0], detectorMaterial) msg = "Inconsistent detector material between DETECTOR and ATTENUATORS tab" msg += "\n%s not equal to %s" % (attenuatorsDetector[0], detectorMaterial) raise ValueError(msg) if len(attenuatorsDetector) == 3: fisxDetector = Detector(detectorMaterial, density=attenuatorsDetector[1], thickness=attenuatorsDetector[2]) else: fisxDetector = Detector(detectorMaterial, density=attenuatorsDetector[1], thickness=attenuatorsDetector[2], funny=attenuatorsDetector[3]) fisxDetector.setActiveArea(area) fisxDetector.setDistance(distance) if fisxDetector is not None: nThreshold = fitConfiguration["detector"]["nthreshold"] fisxDetector.setMaximumNumberOfEscapePeaks(nThreshold) return fisxDetector
def _getDetector(webConfiguration): # Detector is described as a list [material, density, thickness] # Translation dictionnary Thickness = "thickness" Density = "density" Material = "material" Area = "area" Distance = "distance" material = webConfiguration["detector"].get(Material, None) if material is None: # No detector return None else: density = float(webConfiguration["detector"][Density]) thickness = float(webConfiguration["detector"][Thickness]) area = float(webConfiguration["detector"][Area]) distance = float(webConfiguration["detector"][Distance]) detectorInstance = Detector(material, density, thickness) detectorInstance.setActiveArea(area) detectorInstance.setDistance(distance) return detectorInstance
def testXRFResults(self): from fisx import Elements from fisx import Material from fisx import Detector from fisx import XRF elementsInstance = Elements() elementsInstance.initializeAsPyMca() # After the slow initialization (to be made once), the rest is fairly fast. xrf = XRF() xrf.setBeam( 16.0) # set incident beam as a single photon energy of 16 keV xrf.setBeamFilters([["Al1", 2.72, 0.11, 1.0]]) # Incident beam filters # Steel composition of Schoonjans et al, 2012 used to generate table I steel = { "C": 0.0445, "N": 0.04, "Si": 0.5093, "P": 0.02, "S": 0.0175, "V": 0.05, "Cr": 18.37, "Mn": 1.619, "Fe": 64.314, # calculated by subtracting the sum of all other elements "Co": 0.109, "Ni": 12.35, "Cu": 0.175, "As": 0.010670, "Mo": 2.26, "W": 0.11, "Pb": 0.001 } SRM_1155 = Material("SRM_1155", 1.0, 1.0) SRM_1155.setComposition(steel) elementsInstance.addMaterial(SRM_1155) xrf.setSample([["SRM_1155", 1.0, 1.0]]) # Sample, density and thickness xrf.setGeometry(45., 45.) # Incident and fluorescent beam angles detector = Detector("Si1", 2.33, 0.035) # Detector Material, density, thickness detector.setActiveArea(0.50) # Area and distance in consistent units detector.setDistance(2.1) # expected cm2 and cm. xrf.setDetector(detector) Air = Material("Air", 0.0012048, 1.0) Air.setCompositionFromLists( ["C1", "N1", "O1", "Ar1", "Kr1"], [0.0012048, 0.75527, 0.23178, 0.012827, 3.2e-06]) elementsInstance.addMaterial(Air) xrf.setAttenuators([["Air", 0.0012048, 5.0, 1.0], ["Be1", 1.848, 0.002, 1.0]]) # Attenuators fluo = xrf.getMultilayerFluorescence(["Cr K", "Fe K", "Ni K"], elementsInstance, secondary=2, useMassFractions=1) print( "\nElement Peak Energy Rate Secondary Tertiary" ) for key in fluo: for layer in fluo[key]: peakList = list(fluo[key][layer].keys()) peakList.sort() for peak in peakList: # energy of the peak energy = fluo[key][layer][peak]["energy"] # expected measured rate rate = fluo[key][layer][peak]["rate"] # primary photons (no attenuation and no detector considered) primary = fluo[key][layer][peak]["primary"] # secondary photons (no attenuation and no detector considered) secondary = fluo[key][layer][peak]["secondary"] # tertiary photons (no attenuation and no detector considered) tertiary = fluo[key][layer][peak].get("tertiary", 0.0) # correction due to secondary excitation enhancement2 = (primary + secondary) / primary enhancement3 = (primary + secondary + tertiary) / primary print("%s %s %.4f %.3g %.5g %.5g" % \ (key, peak + (13 - len(peak)) * " ", energy, rate, enhancement2, enhancement3)) # compare against expected values from Schoonjans et al. testXMI = True if (key == "Cr K") and peak.startswith("KL3"): second = 1.626 third = 1.671 elif (key == "Cr K") and peak.startswith("KM3"): second = 1.646 third = 1.694 elif (key == "Fe K") and peak.startswith("KL3"): second = 1.063 third = 1.064 elif (key == "Fe K") and peak.startswith("KL3"): second = 1.065 third = 1.066 else: testXMI = False if testXMI: discrepancy = 100 * (abs(second - enhancement2) / second) self.assertTrue(discrepancy < 1.5, "%s %s secondary discrepancy = %.1f %%" % \ (key, peak, discrepancy)) discrepancy = 100 * (abs(third - enhancement3) / third) self.assertTrue(discrepancy < 1.5, "%s %s tertiary discrepancy = %.1f %%" % \ (key, peak, discrepancy))
def testXRFResults(self): from fisx import Elements from fisx import Material from fisx import Detector from fisx import XRF elementsInstance = Elements() elementsInstance.initializeAsPyMca() # After the slow initialization (to be made once), the rest is fairly fast. xrf = XRF() xrf.setBeam(16.0) # set incident beam as a single photon energy of 16 keV xrf.setBeamFilters([["Al1", 2.72, 0.11, 1.0]]) # Incident beam filters # Steel composition of Schoonjans et al, 2012 used to generate table I steel = {"C": 0.0445, "N": 0.04, "Si": 0.5093, "P": 0.02, "S": 0.0175, "V": 0.05, "Cr":18.37, "Mn": 1.619, "Fe":64.314, # calculated by subtracting the sum of all other elements "Co": 0.109, "Ni":12.35, "Cu": 0.175, "As": 0.010670, "Mo": 2.26, "W": 0.11, "Pb": 0.001} SRM_1155 = Material("SRM_1155", 1.0, 1.0) SRM_1155.setComposition(steel) elementsInstance.addMaterial(SRM_1155) xrf.setSample([["SRM_1155", 1.0, 1.0]]) # Sample, density and thickness xrf.setGeometry(45., 45.) # Incident and fluorescent beam angles detector = Detector("Si1", 2.33, 0.035) # Detector Material, density, thickness detector.setActiveArea(0.50) # Area and distance in consistent units detector.setDistance(2.1) # expected cm2 and cm. xrf.setDetector(detector) Air = Material("Air", 0.0012048, 1.0) Air.setCompositionFromLists(["C1", "N1", "O1", "Ar1", "Kr1"], [0.0012048, 0.75527, 0.23178, 0.012827, 3.2e-06]) elementsInstance.addMaterial(Air) xrf.setAttenuators([["Air", 0.0012048, 5.0, 1.0], ["Be1", 1.848, 0.002, 1.0]]) # Attenuators fluo = xrf.getMultilayerFluorescence(["Cr K", "Fe K", "Ni K"], elementsInstance, secondary=2, useMassFractions=1) print("\nElement Peak Energy Rate Secondary Tertiary") for key in fluo: for layer in fluo[key]: peakList = list(fluo[key][layer].keys()) peakList.sort() for peak in peakList: # energy of the peak energy = fluo[key][layer][peak]["energy"] # expected measured rate rate = fluo[key][layer][peak]["rate"] # primary photons (no attenuation and no detector considered) primary = fluo[key][layer][peak]["primary"] # secondary photons (no attenuation and no detector considered) secondary = fluo[key][layer][peak]["secondary"] # tertiary photons (no attenuation and no detector considered) tertiary = fluo[key][layer][peak].get("tertiary", 0.0) # correction due to secondary excitation enhancement2 = (primary + secondary) / primary enhancement3 = (primary + secondary + tertiary) / primary print("%s %s %.4f %.3g %.5g %.5g" % \ (key, peak + (13 - len(peak)) * " ", energy, rate, enhancement2, enhancement3)) # compare against expected values from Schoonjans et al. testXMI = True if (key == "Cr K") and peak.startswith("KL3"): second = 1.626 third = 1.671 elif (key == "Cr K") and peak.startswith("KM3"): second = 1.646 third = 1.694 elif (key == "Fe K") and peak.startswith("KL3"): second = 1.063 third = 1.064 elif (key == "Fe K") and peak.startswith("KL3"): second = 1.065 third = 1.066 else: testXMI = False if testXMI: discrepancy = 100 * (abs(second-enhancement2)/second) self.assertTrue(discrepancy < 1.5, "%s %s secondary discrepancy = %.1f %%" % \ (key, peak, discrepancy)) discrepancy = 100 * (abs(third-enhancement3)/third) self.assertTrue(discrepancy < 1.5, "%s %s tertiary discrepancy = %.1f %%" % \ (key, peak, discrepancy))