XAS process¶
pymca functions¶
The xas process are made from pymca functions. The main class dealing with XAS in pymca is the XASClass
Here is the initialization of the class:
[1]:
from PyMca5.PyMcaPhysics.xas.XASClass import XASClass
pymca_xas = XASClass()
The XASClass is associated to a XASParameters
Then we have to set some spectrum
[2]:
from PyMca5.PyMcaIO import specfilewrapper as specfile
def read_spectrum(spec_file):
"""
:param spec_file: path to the spec file containing the spectrum definition
:return: (energy, mu)
:rtype: tuple
"""
scan = specfile.Specfile(spec_file)[0]
data = scan.data()
if data.shape[0] == 2:
energy = data[0, :]
mu = data[1, :]
else:
energy = None
mu = None
labels = scan.alllabels()
i = 0
for label in labels:
if label.lower() == "energy":
energy = data[i, :]
elif label.lower() in ["counts", "mu", "absorption"]:
mu = data[i, :]
i = i + 1
if (energy is None) or (mu is None):
if len(labels) == 3:
if labels[0].lower() == "point":
energy = data[1, :]
mu = data[2, :]
else:
energy = data[0, :]
mu = data[1, :]
else:
energy = data[0, :]
mu = data[1, :]
return energy, mu
[3]:
import os
from PyMca5.PyMcaPhysics.xas.XASClass import XASClass
from PyMca5.PyMcaDataDir import PYMCA_DATA_DIR
data_file = os.path.join(PYMCA_DATA_DIR, "EXAFS_Cu.dat")
energy, mu = read_spectrum(data_file)
print(energy)
print(mu)
pymca_xas = XASClass()
pymca_xas.setSpectrum(energy, mu)
[8002.894 8007.32 8011.75 ... 9972.721 9975.502 9978.284]
[0.5249888 0.5236315 0.5225714 ... 2.264979 2.263324 2.262075 ]
normalization¶
[4]:
ddict_norm = pymca_xas.normalize()
ddict_norm
[4]:
{'Edge': 8981.095829364065,
'Jump': 2.7182920330495617,
'JumpNormalizationMethod': 'Flattened',
'NormalizedBackground': array([0.51720316, 0.51653625, 0.51586874, ..., 0.22038917, 0.21997013,
0.21955093]),
'NormalizedEnergy': array([8002.894, 8007.32 , 8011.75 , ..., 9972.721, 9975.502, 9978.284]),
'NormalizedMu': array([0.00286416, 0.00261019, 0.00246576, ..., 1.02419698, 1.02461713,
1.02524238]),
'NormalizedPlotMax': 9481.095829364065,
'NormalizedPlotMin': 8002.894,
'NormalizedSignal': array([3.94772789, 3.94383839, 3.93994538, ..., 2.21667492, 2.21423102,
2.21178624])}
output should be
EXAFS (signal extraction)¶
[5]:
from PyMca5.PyMcaPhysics.xas.XASClass import e2k
params = pymca_xas._configuration["DefaultBackend"]["EXAFS"]
e0 = ddict_norm["Edge"]
kValues = e2k(energy - e0)
ddict_pe = pymca_xas.postEdge(k=kValues, mu=mu, backend=None)
print(ddict_pe)
{'KWeight': 0, 'KMin': 2, 'PostEdgeB': array([168.94520652, 168.04735184, 167.14989123, ..., 2.26707394,
2.26555332, 2.26403998]), 'PostEdgeK': array([-16.02332998, -15.98703908, -15.95063269, ..., 16.13289519,
16.1555016 , 16.17808453]), 'KMax': 16.17808452796121, 'KnotsY': array([3.0420222, 2.8137376, 2.5351834], dtype=float32), 'KnotsX': array([ 5.5445213, 9.089043 , 12.633563 ], dtype=float32)}
k weight¶
will just update k in the EXAFS and Fourier transform classes.
Fourier transform¶
[6]:
from PyMca5.PyMcaPhysics.xas.XASClass import XASClass
pymca_xas = XASClass()
ddict = pymca_xas.fourierTransform(k=kValues, mu=mu, kMin=None, kMax=None)
xas workflow¶
To keep compatibility and to normalize the process we defined processes from tomwer which are based on the pymca functions. Those are simple function to be called with a configuration (as a dict)
TODO: present XASBase and PyMcaXAS classes
Reading a spectrum file (and a configuration file)
[7]:
from PyMca5.PyMcaDataDir import PYMCA_DATA_DIR
import os
data_file = os.path.join(PYMCA_DATA_DIR, "EXAFS_Cu.dat")
[8]:
from xas.io import read_pymca_xas
from silx.io.url import DataUrl
spec_url = DataUrl(file_path=data_file, scheme='PyMca')
print(spec_url.scheme())
xas_obj = read_pymca_xas(spectrum_url=DataUrl(file_path=data_file, scheme='PyMca'))
assert 'Mu' in xas_obj.spectrum
PyMca
normalization¶
[9]:
from xas.core.process.normalization import pymca_normalization
xas_obj = pymca_normalization(xas_obj.copy())
assert 'NormalizedMu' in xas_obj.spectrum
exafs¶
[10]:
from xas.core.process.exafs import pymca_exafs
xas_obj = pymca_exafs(xas_obj.copy())
assert 'PostEdgeB' in xas_obj.spectrum
k weight¶
[11]:
from xas.core.process.k_weight import pymca_k_weight
l_xas_obj = xas_obj.copy()
l_xas_obj.configuration['SET_KWEIGHT'] = 1
xas_obj = pymca_k_weight(l_xas_obj)
assert xas_obj.spectrum['KWeight'] == 1
Fourier transform¶
[12]:
from xas.core.process.ft import pymca_ft
xas_obj = pymca_ft(xas_obj.copy())
assert 'FTRadius' in xas_obj.spectrum['FT']
Defining a treatment workflow¶
[13]:
import xas
from xas.pushworkflow.scheme.node import Node
from xas.pushworkflow.scheme.link import Link
from xas.pushworkflow.scheme.scheme import Scheme
import xas.core.process.normalization
import xas.core.process.k_weight
import xas.core.process.exafs
import xas.core.process.ft
import xas.io
read_task = Node(callback=xas.io.read_pymca_xas)
normalization_task = Node(callback=xas.core.process.normalization.pymca_normalization)
k_weight_task = Node(callback=xas.core.process.k_weight.pymca_k_weight)
exafs_task = Node(callback=xas.core.process.exafs.pymca_exafs)
ft_task = Node(callback=xas.core.process.ft.pymca_ft)
nodes = (read_task, normalization_task, k_weight_task, exafs_task, ft_task)
links = [
Link(source_node=read_task, source_channel='spectrum',
sink_node=normalization_task, sink_channel='spectrum'),
Link(source_node=normalization_task, source_channel='spectrum',
sink_node=k_weight_task, sink_channel='spectrum'),
Link(source_node=k_weight_task, source_channel='spectrum',
sink_node=exafs_task, sink_channel='spectrum'),
Link(source_node=exafs_task, source_channel='spectrum',
sink_node=ft_task, sink_channel='spectrum'),
]
scheme = Scheme(nodes=nodes, links=links)
Then we can execute the workflow previously defined
[14]:
from xas.app.process import exec_ as exec_workflow
from PyMca5.PyMcaDataDir import PYMCA_DATA_DIR
from silx.io.url import DataUrl
import os
data_file = os.path.join(PYMCA_DATA_DIR, "EXAFS_Cu.dat")
out = exec_workflow(scheme=scheme, input_=data_file)
assert isinstance(out, dict)
assert 'FTRadius' in out['spectrum']['FT']
2019-07-02 09:15:00,732 Error: dimension of knots must be dimension of polDegree+1
2019-07-02 09:15:00,733 Forced automatic (equidistant) knot definition.
2019-07-02 09:15:00,759 Missing configuration to know which value we should set to k weight, will be set to 0 by default
2019-07-02 09:15:00,763 Error: dimension of knots must be dimension of polDegree+1
2019-07-02 09:15:00,763 Forced automatic (equidistant) knot definition.
2019-07-02 09:15:00,830 Error: dimension of knots must be dimension of polDegree+1
2019-07-02 09:15:00,832 Forced automatic (equidistant) knot definition.
2019-07-02 09:15:00,834 Error: dimension of knots must be dimension of polDegree+1
2019-07-02 09:15:00,834 Forced automatic (equidistant) knot definition.
2019-07-02 09:15:00,901 Error: dimension of knots must be dimension of polDegree+1
2019-07-02 09:15:00,915 Forced automatic (equidistant) knot definition.
[ ]:
[ ]: