Source code for ewoksfluo.tasks.example_data.xrf_spectra

from typing import Dict, NamedTuple, Sequence, Tuple, Union

import numpy
from PyMca5.PyMcaPhysics.xrf.ClassMcaTheory import McaTheory
from PyMca5.PyMcaIO.ConfigDict import ConfigDict


[docs]class EmissionLineGroup(NamedTuple): element: str name: str counts: Union[float, Sequence] @property def counts_asarray(self): return get_counts_array(self.counts)
[docs]class ScatterLineGroup(NamedTuple): name: str counts: Union[float, Sequence] prefix: str = "Scatter" @property def counts_asarray(self): return get_counts_array(self.counts)
[docs]def get_counts_array(counts: Union[float, Sequence]): if isinstance(counts, Sequence): return numpy.asarray(counts) return numpy.array((counts))
[docs]def xrf_spectra( linegroups: Sequence[EmissionLineGroup], scattergroups: Sequence[ScatterLineGroup], nchannels: int = 1024, energy: float = 7.5, angle_in: float = 62.0, angle_out: float = 49.0, flux: float = 1e10, elapsed_time: float = 1.0, ) -> Tuple[numpy.ndarray, ConfigDict]: """The returned spectra have the shape `counts.shape + (nchannels,)`""" peaks = {linegroup.element: linegroup.name for linegroup in linegroups} counts: Dict[str, numpy.ndarray] = { f"{group.element} {group.name}": group.counts_asarray for group in linegroups } counts.update( {f"Scatter {group.name}": group.counts_asarray for group in scattergroups} ) # MCA parameters zero = 0 # keV max_energy = energy + 1.5 # keV gain = (max_energy - zero) / nchannels # Initialize theory theory = McaTheory() theory.setConfiguration( get_configuration( peaks, xmin=1, xmax=nchannels - 3, zero=zero, gain=gain, energy=energy, angle_in=angle_in, angle_out=angle_out, flux=flux, elapsed_time=elapsed_time, ) ) # Calculate emission lines x = numpy.arange(nchannels) theory.setData(x=x, y=numpy.zeros(nchannels)) theory.enableOptimizedLinearFit() theory.estimate() # Analytical XRF spectrum nglobal = theory.NGLOBAL if counts: shape = next(iter(counts.values())).shape else: shape = tuple() y = numpy.zeros(shape + (nchannels,)) for i, name in enumerate(theory.PARAMETERS[nglobal:], nglobal): normalized_group = theory.linearMcaTheoryDerivative( numpy.asarray(theory.parameters), i, x ) assert isinstance(normalized_group, numpy.ndarray) if shape: y += counts[name][..., None] * normalized_group[None, ...] else: y += counts[name] * normalized_group return y, theory.config
[docs]def get_configuration( peaks: dict, xmin: int = 0, xmax: int = 0, zero: float = 0, gain: float = 0.005, energy: float = 0, angle_in: float = 62.0, angle_out: float = 49.0, flux: float = 1e10, elapsed_time: float = 1.0, ): return { "peaks": peaks, "attenuators": get_attenuators(angle_in=angle_in, angle_out=angle_out), "fit": get_fit_config(xmin=xmin, xmax=xmax, energy=energy), "concentrations": get_quantification_config( flux=flux, elapsed_time=elapsed_time ), "detector": get_detector(zero=zero, gain=gain), "peakshape": get_peak_shape(), "materials": { "SingleLayerStrategyMaterial": { "Comment": "Last Single Layer Strategy iteration", "Thickness": 0.0025, "Density": 1.42, "CompoundFraction": "", "CompoundList": "", }, **get_materials(), }, "multilayer": { "Layer0": [1, "Cerussite", 6.8, 0.1], "Layer1": [0, "-", 0.0, 0.0], "Layer2": [0, "-", 0.0, 0.0], "Layer3": [0, "-", 0.0, 0.0], "Layer4": [0, "-", 0.0, 0.0], "Layer5": [0, "-", 0.0, 0.0], "Layer6": [0, "-", 0.0, 0.0], "Layer7": [0, "-", 0.0, 0.0], "Layer8": [0, "-", 0.0, 0.0], "Layer9": [0, "-", 0.0, 0.0], }, "SingleLayerStrategy": { "layer": "Auto", "iterations": 3, "completer": "-", "peaks": "", "materials": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "flags": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }, "tube": { "transmission": 0, "voltage": 30.0, "anode": "Ag", "anodethickness": 0.0002, "anodedensity": 10.5, "window": "Be", "windowthickness": 0.0125, "windowdensity": 1.848, "filter1": "He", "filter1thickness": 0.0, "filter1density": 0.000118, "alphax": 90.0, "alphae": 90.0, "deltaplotting": 0.1, }, "fisx": {}, }
[docs]def get_quantification_config(flux: float = 1e10, elapsed_time: float = 1.0) -> dict: return { "usematrix": 0, "useattenuators": 1, "usemultilayersecondary": 0, "usexrfmc": 0, "mmolarflag": 0, "flux": flux, "time": elapsed_time, "area": 0.774671, "distance": 4.15114, "reference": "Auto", "useautotime": 0, }
[docs]def get_peak_shape(): return { "st_arearatio": 0.0697778, "deltast_arearatio": 0.03, "fixedst_arearatio": 1, "st_sloperatio": 0.0105551, "deltast_sloperatio": 0.49, "fixedst_sloperatio": 1, "lt_arearatio": 0.1, "deltalt_arearatio": 0.15, "fixedlt_arearatio": 1, "lt_sloperatio": 0.1, "deltalt_sloperatio": 0.08, "fixedlt_sloperatio": 1, "step_heightratio": 0.1, "deltastep_heightratio": 5e-05, "fixedstep_heightratio": 1, "eta_factor": 0.02, "deltaeta_factor": 0.02, "fixedeta_factor": 1, }
[docs]def get_fit_config(xmin: int = 0, xmax: int = 0, energy: float = 0) -> dict: return { "deltaonepeak": 0.01, "strategy": "SingleLayerStrategy", "strategyflag": 0, "fitfunction": 0, "continuum": 0, "fitweight": 1, "stripalgorithm": 1, "linpolorder": 5, "exppolorder": 6, "stripconstant": 1.0, "snipwidth": 65, "stripiterations": 400, "stripwidth": 5, "stripfilterwidth": 7, "stripanchorsflag": 0, "maxiter": 10, "deltachi": 0.001, "xmin": xmin, "xmax": xmax, "linearfitflag": 1, "use_limit": 0, "stripflag": 1, "escapeflag": 0, "sumflag": 0, "scatterflag": 1, "hypermetflag": 1, "stripanchorslist": [0, 0, 0, 0], "energy": [energy], "energyweight": [1.0], "energyflag": [1], "energyscatter": [1], }
[docs]def get_attenuators(angle_in: float = 62.0, angle_out: float = 49.0) -> dict: return { "kapton": [1, "Mylar", 1.4, 0.0004, 1.0], "atmosphere": [0, "-", 0.0, 0.0, 1.0], "deadlayer": [0, "Si1", 2.33, 0.002, 1.0], "absorber": [0, "-", 1.0, 0.1, 1.0], "window": [1, "Be", 1.848, 0.0025, 1.0], "contact": [0, "moxtekAP3.3", 5.45e-05, 1.0, 1.0], "Filter 6": [0, "-", 0.0, 0.0, 1.0], "Filter 7": [0, "-", 1.0, 0.1, 1.0], "BeamFilter0": [0, "-", 0.0, 0.0, 1.0], "BeamFilter1": [0, "-", 0.0, 0.0, 1.0], "Detector": [1, "Si1", 2.33, 0.5, 1.0], "Matrix": [ 1, "Cerussite", 6.8, 0.1, angle_in, angle_out, 0, angle_in + angle_out, ], }
[docs]def get_detector(zero: float = 0, gain: float = 0.005) -> dict: return { "detele": "Si", "nthreshold": 4, "zero": zero, "deltazero": 0.1, "fixedzero": 1, "gain": gain, "deltagain": 0.002, "fixedgain": 1, "noise": -0.0955892, "deltanoise": 0.05, "fixednoise": 1, "fano": 0.0484433, "deltafano": 0.114, "fixedfano": 1, "sum": 0.0, "deltasum": 2e-06, "fixedsum": 1, "ignoreinputcalibration": 0, }
[docs]def get_materials() -> dict: return { "Air": { "Comment": "Dry Air (Near sea level) density=0.001204790 g/cm3", "Thickness": 1.0, "Density": 0.0012048, "CompoundFraction": [0.000124, 0.75527, 0.23178, 0.012827, 3.2e-06], "CompoundList": ["C1", "N1", "O1", "Ar1", "Kr1"], }, "Goethite": { "Comment": "Mineral FeO(OH) density from 3.3 to 4.3 density=4.3 g/cm3", "CompoundFraction": 1.0, "Thickness": 0.1, "Density": 4.3, "CompoundList": "Fe1O2H1", }, "Mylar": { "Comment": "Mylar (Polyethylene Terephthalate) density=1.40 g/cm3", "Density": 1.4, "CompoundFraction": [0.041959, 0.625017, 0.333025], "CompoundList": ["H1", "C1", "O1"], }, "Kapton": { "Comment": "Kapton 100 HN 25 micron density=1.42 g/cm3", "Thickness": 0.0025, "Density": 1.42, "CompoundFraction": [0.628772, 0.066659, 0.304569], "CompoundList": ["C1", "N1", "O1"], }, "Teflon": { "Comment": "Teflon density=2.2 g/cm3", "Density": 2.2, "CompoundFraction": [0.240183, 0.759817], "CompoundList": ["C1", "F1"], }, "Viton": { "Comment": "Viton Fluoroelastomer density=1.8 g/cm3", "Density": 1.8, "CompoundFraction": [0.009417, 0.280555, 0.710028], "CompoundList": ["H1", "C1", "F1"], }, "Water": { "Comment": "Water density=1.0 g/cm3", "CompoundFraction": 1.0, "Thickness": 1.0, "Density": 1.0, "CompoundList": "H2O1", }, "Gold": { "Comment": "Gold", "CompoundFraction": 1.0, "Thickness": 1e-06, "Density": 19.37, "CompoundList": "Au", }, "Cerussite": { "Comment": "Mineral PbCO3", "CompoundFraction": 1.0, "Thickness": 0.1, "Density": 6.8, "CompoundList": "Pb1C1O3", }, "mixture": { "Comment": "New Material", "Thickness": 1.0, "Density": 1.0, "CompoundFraction": [0.0096, 0.0234], "CompoundList": ["Ca1S1O6H4", "K1Cl1"], }, "sample": { "Comment": "New Material", "Thickness": 1.0, "Density": 2.36, "CompoundFraction": 1.0, "CompoundList": "Hg1S1", }, "moxtekAP3.3": { "Comment": "New Material", "Thickness": 1.0, "Density": 5.45e-05, "CompoundFraction": [0.06, 0.62, 0.055, 0.155, 0.106], "CompoundList": ["B", "C", "N", "O", "Al"], }, }
if __name__ == "__main__": linegroups = [ EmissionLineGroup("Si", "K", 300), EmissionLineGroup("Al", "K", 400), EmissionLineGroup("Cl", "K", 200), EmissionLineGroup("Pb", "M", 500), EmissionLineGroup("P", "K", 200), EmissionLineGroup("S", "K", 600), EmissionLineGroup("Ca", "K", 500), EmissionLineGroup("Ti", "K", 400), EmissionLineGroup("Ce", "L", 500), EmissionLineGroup("Fe", "K", 1000), ] scattergroups = [ ScatterLineGroup("Peak000", 100), ScatterLineGroup("Compton000", 100), ] spectrum, config = xrf_spectra(linegroups, scattergroups) import matplotlib.pyplot as plt plt.plot(spectrum) plt.show()