PyMca XAS treatments

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]:
{'Jump': 2.7182920330495683,
 'JumpNormalizationMethod': 'Flattened',
 'Edge': 8981.095829364065,
 '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]),
 'NormalizedBackground': array([0.51720316, 0.51653625, 0.51586874, ..., 0.22038917, 0.21997013,
        0.21955093]),
 'NormalizedSignal': array([3.94772789, 3.94383839, 3.93994538, ..., 2.21667492, 2.21423102,
        2.21178624]),
 'NormalizedPlotMin': 8002.894,
 'NormalizedPlotMax': 9481.095829364065}

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)
{'PostEdgeK': array([-16.02332998, -15.98703908, -15.95063269, ...,  16.13289519,
        16.1555016 ,  16.17808453]), 'PostEdgeB': array([168.94520652, 168.04735184, 167.14989123, ...,   2.26707394,
         2.26555332,   2.26403998]), 'KnotsX': array([ 5.5445213,  9.089043 , 12.633563 ], dtype=float32), 'KnotsY': array([3.0420222, 2.8137376, 2.5351834], dtype=float32), 'KMin': 2, 'KMax': 16.17808452796121, 'KWeight': 0}

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.core.io import read as 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(spectra_url=DataUrl(file_path=data_file, scheme='PyMca'), channel_url=DataUrl(file_path=data_file, scheme='PyMca'))
assert 'Mu' in xas_obj.spectra[0]
PyMca

normalization

[9]:
from xas.core.process.pymca.normalization import pymca_normalization
xas_obj = pymca_normalization(xas_obj.copy())
assert 'NormalizedMu' in xas_obj.spectra[0]
normalization: [####################] 100.0% DONE
normalization: [####################] 100% DONE

exafs

[10]:
from xas.core.process.pymca.exafs import pymca_exafs
xas_obj = pymca_exafs(xas_obj.copy())
assert 'PostEdgeB' in xas_obj.spectra[0]
exafs: [####################] 100.0% DONE
exafs: [####################] 100% DONE

k weight

[11]:
from xas.core.process.pymca.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.spectra[0]['KWeight'] == 1
k weight: [####################] 100.0% DONE
k weight: [####################] 100% DONE

Fourier transform

[12]:
from xas.core.process.pymca.ft import pymca_ft
xas_obj = pymca_ft(xas_obj.copy())
assert 'FTRadius' in xas_obj.spectra[0]['FT']
ft: [####################] 100.0% DONE
ft: [####################] 100% DONE

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.pymca.normalization
import xas.core.process.pymca.k_weight
import xas.core.process.pymca.exafs
import xas.core.process.pymca.ft
from xas.core.types import XASObject
import xas.core.io


read_task = Node(callback=xas.core.io.read_frm_file)
normalization_task = Node(callback=xas.core.process.pymca.normalization.pymca_normalization)
k_weight_task = Node(callback=xas.core.process.pymca.k_weight.pymca_k_weight)
exafs_task = Node(callback=xas.core.process.pymca.exafs.pymca_exafs)
ft_task = Node(callback=xas.core.process.pymca.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)
xas_obj_out = XASObject.from_dict(out)
assert 'FTRadius' in xas_obj_out.spectra[0].ft
normalization: [####################] 100.0% DONE
normalization: [####################] 100% DONE
2019-08-13 15:43:27,689 Missing configuration to know which value we should set to k weight, will be set to 0 by default
k weight: [--------------------] 0%
2019-08-13 15:43:27,693 Error: dimension of knots must be dimension of polDegree+1
2019-08-13 15:43:27,693        Forced automatic (equidistant) knot definition.
k weight: [####################] 100.0% DONE
k weight: [####################] 100% DONE
exafs: [--------------------] 0%
2019-08-13 15:43:27,735 Error: dimension of knots must be dimension of polDegree+1
2019-08-13 15:43:27,735        Forced automatic (equidistant) knot definition.
exafs: [####################] 100.0% DONE
exafs: [####################] 100% DONE
ft: [####################] 100.0% DONE
ft: [####################] 100% DONE
[ ]:

[ ]: