LCF 批处理
对一系列未知谱用同一组标样做线性组合,写出权重与 R-factor。
pythonlarchlcf
python xanes_lcf.py --unknowns samples.prj --standards std.prj --emin -20 --emax 50
xanes_lcf.py
#!/usr/bin/env python3
"""Linear combination fitting of flattened XANES with Larch."""
import argparse
import csv
import numpy as np
from larch.io import read_athena
from larch.xafs import pre_edge, find_e0
from larch.math import interp
from scipy.optimize import nnls
def flattened(group, pre=(-150, -30), norm=(150, 800)):
e0 = find_e0(group.energy, group.mu)
pre_edge(group, e0=e0, pre1=pre[0], pre2=pre[1],
norm1=norm[0], norm2=norm[1], nvict=2)
return np.asarray(group.energy), np.asarray(group.flat), e0
def window(e, y, e0, emin, emax):
m = (e >= e0 + emin) & (e <= e0 + emax)
return e[m], y[m]
def lcf(e_unk, y_unk, stds):
# interpolate standards onto unknown grid
A = np.column_stack([interp(e, y, e_unk) for e, y, _ in stds])
w, _ = nnls(A, y_unk)
if w.sum() > 0:
w = w / w.sum()
fit = A @ w
r = np.sum((y_unk - fit) ** 2) / np.sum(y_unk ** 2)
return w, fit, r
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--unknowns", required=True)
ap.add_argument("--standards", required=True)
ap.add_argument("--emin", type=float, default=-20)
ap.add_argument("--emax", type=float, default=50)
ap.add_argument("--csv", default="lcf_report.csv")
args = ap.parse_args()
std_proj = read_athena(args.standards)
stds = []
names = []
for name, g in std_proj._athena_groups.items():
e, y, e0 = flattened(g)
stds.append((e, y, e0))
names.append(name)
rows = []
unk_proj = read_athena(args.unknowns)
for name, g in unk_proj._athena_groups.items():
e, y, e0 = flattened(g)
ew, yw = window(e, y, e0, args.emin, args.emax)
packed = []
for se, sy, se0 in stds:
sw, ssy = window(se, sy, se0, args.emin, args.emax)
packed.append((sw, ssy, se0))
w, fit, r = lcf(ew, yw, packed)
row = {"group": name, "E0": f"{e0:.2f}", "R": f"{r:.5f}"}
for n, wi in zip(names, w):
row[n] = f"{100 * wi:.2f}"
rows.append(row)
print(name, row)
with open(args.csv, "w", newline="") as f:
wri = csv.DictWriter(f, fieldnames=rows[0].keys())
wri.writeheader()
wri.writerows(rows)
if __name__ == "__main__":
main()