Compute theoretical EXAFS χ(k) spectra from a crystal structure by sampling thermal and structural disorder with machine-learning interatomic potential (MLIP) molecular dynamics (MD) and computing scattering paths with FEFF9.
The pipeline:
cell relaxation → NVT molecular dynamics → FEFF input generation
→ batch FEFF (+ scratch cleanup) → configurational averaging of χ(k)
(+ E0 fit to experiment) → k-/R-space plotting
optional: linear combination fit of several simulated χ(k) to experiment
Each MD snapshot is turned into a FEFF calculation; averaging the per-snapshot χ(k) curves reproduces the thermal/static disorder that broadens and damps an experimental EXAFS signal (the effect described by Debye–Waller factors in path-based fitting).
The MD force engine can be any of these universal potentials. Install at least one; each is imported lazily so only the chosen backend must be present. Dependencies for many of the MLIPs conflict, so separate environments are recommended.
| Backend | Best for |
|---|---|
| CHGNet | Magnetic systems (Fe, Co, Ni, Mn, Cr); predicts magnetic moments |
| MACE | High-accuracy forces, materials and organic systems |
| UMA (FAIRChem) | State-of-the-art accuracy; catalysis, MOFs, diverse chemistry |
| ORB | Fast inference, large/high-throughput systems |
| SevenNet | General materials, scalable |
relax and md accept --checkpoint <path> (Python/MCP/SciLink: checkpoint=)
to load a local model file, such as a fine-tuned potential, instead of the
backend's pretrained model. Pass --checkpoint or --model, not both. The file
must be in the backend's own format:
| Backend | Checkpoint | Loaded with |
|---|---|---|
chgnet |
CHGNet trainer output (*.pth.tar) |
CHGNet.from_file |
mace |
MACE model file (*.model) |
mace_mp(model=<path>) |
uma |
fairchem checkpoint (*.pt) |
load_predict_unit |
orb |
orb-v3-conservative-inf state dict (*.ckpt, e.g. from finetune.py) |
orb_v3_conservative_inf_omat(weights_path=<path>) |
sevennet |
SevenNet checkpoint (*.pth, e.g. checkpoint_best.pth) |
SevenNetCalculator(model=<path>) |
mlmd-exafs md -i relaxed.xyz -d md_out --backend mace --checkpoint my_finetuned.modelUse the same checkpoint for relax and md, so the MD starts from the
fine-tuned model's equilibrium geometry.
NOTE: UMA models are gated. Access can be requested at https://huggingface.co/facebook/UMA.
cd MLMD-EXAFS
pip install -e .
# Then install the MLIP backend(s) you need, e.g.:
pip install -e ".[chgnet]" # or .[mace] / .[uma] / .[orb] / .[sevennet]NOTE: FEFF9 is a separate binary, not a Python package. Install it independently
from https://feff.phys.washington.edu/feffproject-feff.html
and point mlmd-exafs run-feff --feff-bin at the executable (default path:
/share/feff/feff90_binaries/feff.x).
# 1. Relax the cell
mlmd-exafs relax -i structure.cif -o relaxed.xyz --backend chgnet
# 2. Run NVT MD (writes md_out/relaxed/relaxed.traj)
mlmd-exafs md -i relaxed.xyz -d md_out --backend chgnet --temperature 300
# 3. Generate FEFF inputs (Zn K-edge here; --target-atom is the absorber index)
mlmd-exafs feff-input -f md_out/relaxed/relaxed.traj --target-atom 0 \
--hole 1 --rmax 6.0
# 4. Run FEFF over all generated inputs (scratch files are cleaned up after,
# keeping feff.inp / feff.out / chi.dat; --no-cleanup to keep everything)
mlmd-exafs run-feff -d md_out/relaxed/exafs_Zn_hole1_de_0.0_s02_1.0_rc_6.0
# 5. Average χ(k) (+ fit E0 if an experimental spectrum is available) and plot
mlmd-exafs average -d md_out/relaxed/exafs_Zn_hole1_de_0.0_s02_1.0_rc_6.0 \
--savefile exafs --exp-file exp_k.dat # .dat or .csv; omit if none
mlmd-exafs plot --chi-file exafs-chi_avg.dat --savefile exafs_k2 --k-weight 2
mlmd-exafs convergence -d md_out/relaxed/exafs_Zn_hole1_de_0.0_s02_1.0_rc_6.0
# 6. (Optional) linear combination fit of several candidate structures'
# averaged spectra to experiment
mlmd-exafs lcf --exp-file exp_k.dat --standards "sims/*-chi_avg.dat" \
--kmin 2.5 --kmax 14 --max-components 3 # --e0-mode joint|joint_shared|fixedSee TUTORIAL.md for a full walkthrough with parameter guidance for each stage.
The same pipeline is exposed three ways so it works across different agent
frameworks. All three call the identical mlmd_exafs package functions — pick
the one that matches your orchestrator.
Any agent that can run shell commands — Codex, Claude Code, Cline,
Cursor, plain scripts — drives the workflow through the mlmd-exafs CLI.
No integration needed; point the agent at the commands in
Quick start above and TUTORIAL.md. This is the
lowest-friction path and always works.
MCP-capable clients can call each stage as a native tool via the bundled Model Context Protocol server. Install the extra and register the command:
pip install -e ".[mcp]" # installs the mcp SDK (works with mcp 1.x and 2.x)The server (mlmd_exafs/mcp_server.py, entry point mlmd-exafs-mcp) exposes
ten tools — mlmd_relax, mlmd_md, mlmd_feff_input, mlmd_run_feff,
mlmd_cleanup, mlmd_average_chi, mlmd_fit_e0, mlmd_lcf, mlmd_plot,
mlmd_convergence — matching the CLI stages.
For SciLink, register the plug-in in tool/mlmd_exafs_tool.py, which
follows SciLink's tool_schemas + create_tool_functions contract:
scilink simulate --tools MLMD-EXAFS/tool/mlmd_exafs_tool.pyIt surfaces the same ten stages as SciLink custom tools, wired to the session's active structure file and results directory. See tool/README.md for details.
This SciLink plug-in format is specific to SciLink — other orchestrators do not read
tool_schemasfiles. Use the CLI or MCP server for them.
| Module | Contents |
|---|---|
mlmd_exafs/calculators.py |
MLIP calculator factory (build_calculator) |
mlmd_exafs/md.py |
Cell relaxation (relax) and NVT MD (run_md, md_engine) |
mlmd_exafs/feff.py |
carve_out, generate_feff_inputs_from_trajectory |
mlmd_exafs/run_feff.py |
Batch FEFF execution (run_feff_batch) |
mlmd_exafs/cleanup_exafs.py |
FEFF scratch-file cleanup of exafs_* dirs (cleanup_exafs) |
mlmd_exafs/analysis.py |
average_chi, xftf, plot_chi, plot_convergence |
mlmd_exafs/fitting_E0.py |
E0 shift fit against experimental χ(k), .dat/.csv (fit_e0) |
mlmd_exafs/lcf.py |
Linear combination fit of several simulated χ(k) to experiment (run_lcf) |
mlmd_exafs/cli.py |
mlmd-exafs command-line entry point |
mlmd_exafs/mcp_server.py |
MCP server (mlmd-exafs-mcp) for MCP-capable agents |
tool/mlmd_exafs_tool.py |
SciLink plug-in custom tool |
scripts/run_feff.csh |
csh alternative to run-feff for cluster batch use |
Everything is also importable as a library — see the tutorial's "Python API" section.
The shaded band in the plots is the snapshot-to-snapshot statistical dispersion of the MD ensemble (standard deviation or standard error of the mean). It shows how well converged the average is and how much the geometry fluctuates thermally. It is not a systematic force-field error bar.