A high-performance Rust toolkit for reading, writing, and modifying ENDF-6 nuclear data files. Based on the recipe-driven approach of endf-parserpy, reimplemented in Rust for speed and safety.
- Recipe-driven parsing -- uses a formal grammar of ENDF recipes to parse and write any MF/MT section, supporting the same recipe formats as endf-parserpy (endf6, endf6-ext, jendl, pendf, errorr)
- Two parsing backends -- a flexible recipe interpreter and a compiled parser with statically generated Rust code for each MF/MT combination
- Python bindings -- drop-in replacement for endf-parserpy with identical data structures (nested dicts), via PyO3
- CLI tool --
endf-toolfor converting between ENDF and JSON formats - Roundtrip support -- parse an ENDF file, modify values, and write it back to valid ENDF-6 format (data values are preserved; number formatting may differ from the original)
| Crate | Description |
|---|---|
endf |
Core library: recipe grammar, interpreter, records, Fortran number formatting, JSON conversion |
endf-compiled |
Compiled parser with generated Rust functions for each MF/MT |
endf-parserpy-rs |
Python bindings via PyO3 (exposes EndfParser and CompiledParser) |
endf-wasm |
WebAssembly bindings for client-side browser parsing |
Requires Rust >= 1.83 and maturin.
pip install maturin
cd crates/endf-parserpy-rs
maturin develop --releaseAdd to your Cargo.toml:
[dependencies]
endf = "0.1"cargo build --release --bin endf_toolParsing the complete ENDF/B-VIII.1 neutron sublibrary (558 files, 1.28 GB)
using the endf6-ext recipe format, called from Python:
| Parser | Time | Speed |
|---|---|---|
| endf-parserpy interpreter (Python) | ~3971s | 0.32 MB/s |
| endf-parserpy C++ compiled parser | 28s | 46.6 MB/s |
| endf-parserpy-rs interpreter | 73s | 17.5 MB/s |
| endf-parserpy-rs compiled parser | 40s | 32.0 MB/s |
The Python interpreter time is extrapolated from a stratified sample (35% of the library). All other parsers were benchmarked on the full library. Times include Python-side overhead (dict conversion).
Pure Rust performance (no Python overhead):
| Parser | Time | Speed |
|---|---|---|
| Rust interpreter (endf6-ext) | 58s | 22.0 MB/s |
| Rust compiled parser (endf6) | 32s | 40.0 MB/s |
from endf_parserpy_rs import EndfParser
parser = EndfParser()
data = parser.parsefile("neutrons.endf")
# Access MF=3, MT=1
section = data[3][1]
print(f"ZA = {section['ZA']}, AWR = {section['AWR']}")
# Modify and write back
section["QM"] = 1.5
parser.writefile("modified.endf", data)The compiled parser offers better performance for the built-in recipes:
from endf_parserpy_rs import CompiledParser
parser = CompiledParser()
data = parser.parsefile("neutrons.endf")use endf::parser::EndfParser;
use std::path::Path;
let parser = EndfParser::new()?;
let data = parser.parse_file(Path::new("neutrons.endf"))?;
if let Some(qm) = data.get_path("3/1/QM") {
println!("QM = {}", qm);
}
let output = parser.write(&data)?;
std::fs::write("modified.endf", output)?;# ENDF to JSON
endf_tool endf2json input.endf output.json --pretty
# JSON to ENDF
endf_tool json2endf output.json roundtrip.endf
# Parallel parsing
endf_tool endf2json input.endf output.json --threads 0This project reimplements the core of endf-parserpy in Rust. The Python bindings provide the same API shape and identical data structures (nested Python dicts keyed by MF/MT), making migration straightforward:
# endf-parserpy
from endf_parserpy import EndfParserPy
parser = EndfParserPy(ignore_zero_mismatch=True)
# endf-parserpy-rs (this project)
from endf_parserpy_rs import EndfParser
parser = EndfParser(ignore_zero_mismatch=True)This project is in an early stage. Core parsing and writing functionality works and has been validated against endf-parserpy on the ENDF/B-VIII.1 neutron sublibrary, but not all features and options have been comprehensively tested. In particular, write-mode formatting options, edge cases in less common MF/MT sections, and non-default recipe formats may contain bugs. Use with appropriate caution and please report any issues you encounter.
The recipe-driven approach used in this project is described in:
G. Schnabel, D. Lopez Aldama, R. Capote, How to explain ENDF-6 to computers: A formal ENDF format description language, arXiv:2312.08249 (2023)
The interpreter also compiles to WebAssembly, enabling client-side ENDF parsing in the browser. A small demo app lets you upload an ENDF file, explore the parsed data as a collapsible tree, edit values, and save the result back to ENDF format — all without a server.
# requires wasm-pack: cargo install wasm-pack
cd crates/endf-wasm
wasm-pack build --target web --release
python3 -m http.server 8080
# open http://localhost:8080/www/Copyright (c) 2022-2025 International Atomic Energy Agency
Copyright (c) 2025-2026 Georg Schnabel