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.
[ ]:

[ ]: