Tags: Ameyanagi/xraydb-rs
Tags
v0.4.1 Docs and release-pipeline patch; no library code changes. - crate READMEs document the npm package (xraydb-wasm), its self-contained loader, and the trusted-publishing release flow - the tag workflow publishes xraydb-wasm to npm via OIDC trusted publishing, idempotently, alongside the crates.io steps - xraydb-wasm ships a package README and types for the loader entry point First end-to-end run of the npm trusted-publishing path.
v0.4.0
Additive: `embedded-data` defaults on and no existing API was removed or changed,
so upgrading from 0.3.0 requires nothing. The minor bump reflects new public API and
new feature flags.
Optional embedded database
--------------------------
The ~3 MB database was compiled in unconditionally and dominated every consumer —
a 4.6 MB CLI binary, a 3.4 MB .wasm. It is now behind `embedded-data` (default on),
with `zstd` controlling the decompressor separately.
xraydb = { version = "0.4", default-features = false, features = ["zstd"] }
let db = XrayDb::load_compressed(&std::fs::read("xraydb.bin.zst")?)?;
Measured on a release binary that actually queries the database:
3.72 MB -> 0.67 MB, 82% smaller.
New: XrayDb::load_compressed, load_uncompressed, current, is_loaded.
`load_uncompressed` takes an already-decoded postcard blob, so ruzstd can be dropped
entirely. Loading is first-call-wins, so handles obtained earlier stay valid.
MSRV 1.88 -> 1.87
-----------------
Seven let-chain sites were forcing 1.88 for pure syntax sugar. Rewritten, which takes
this crate's own code to 1.85 — edition 2024's floor. The declared floor stays 1.87
because ruzstd uses unsigned_is_multiple_of. Verified by building under 1.85, 1.86,
1.87 and 1.88. xraydb-data declares 1.85, having no such dependency.
Coverage
--------
Measured with cargo-llvm-cov, then improved where it was thin:
coster_kronig.rs 69.6% -> 100%
transitions.rs 77.7% -> 97.0%
ionchamber.rs 83.0% -> 94.9%
chantler.rs 85.9% -> 97.3%
library total 91.3% -> 94.0%
CI now gates the library at 90%.
Also fixed: the workspace-wide --no-default-features CI step was exercising nothing,
because xraydb-cli depends on xraydb with defaults on and cargo unifies features. The
featureless build had never actually been compiled. Feature combinations are now
checked with -p.
236 tests.
v0.3.0
Chantler f1 is now evaluated with an interpolating natural cubic spline instead of
linear interpolation, closing the one item deferred from the 0.2.0 review.
Why it mattered
- f1 drives anomalous scattering work (MAD/SAD phasing, resonant scattering), which
lives at absorption edges — exactly where linear interpolation was worst:
Au L3 was off by 0.58 electrons (3.3%), Cu K by 0.23, Fe K by 0.18.
- f2 was already exact against upstream; only f1 was affected.
Upstream has no single value to match: it fits UnivariateSpline(s=0) to a window of
the grid spanning the requested energies +/-3 points, so its answer depends on what
else is in the same call. f1_chantler('Au', 11919) alone gives -17.745813; the same
energy inside a wide batch gives -17.769546.
A global spline is the limit that windowing converges to, is independent of the
query, and matches upstream's wide-window values to 4.2e-12.
Measured against 1,727 reference values across 30 elements and every tabulated edge:
spline (0.3.0) linear (0.2.0)
mean |error| 1.6e-10 0.647
worst |error| 3.7e-9 234.7
Notes
- Coefficients are derived at load rather than shipped: storing them grew the blob
32%, deriving them costs 1.14 ms (2.3% of cold init). The embedded blob is
byte-identical to 0.2.0's; xraydb-data's wire format is unchanged.
- No slower — f1 lookups are ~100 ns, quicker than f2, which pays a ln/exp.
- Caesium's grid repeats 11.4 eV, which makes upstream raise ValueError. Fitting to
the strictly increasing subsequence keeps every element queryable.
BREAKING: f1 values shift, and everything derived from them moves too —
xray_delta_beta, and the optics delta/beta and Darwin widths.
MSRV 1.88. 219 tests.
v0.2.0
Correctness, performance, and a much larger surface.
Fixes
- material_mu and xray_delta_beta used two different formula parsers; the weaker
one rejected the crate's own 'air' materials entry, so material_mu_named("air")
and ionchamber_fluxes with air always failed. One parser now serves the crate.
- Three reachable panics removed (multilayer_reflectivity on an empty stackup or
zero periods; interp_one and elam_spline on empty tables).
- darwin_width returned Some(_) full of empty vectors in degenerate cases; now None.
- xray_delta_beta summed over a HashMap and was not reproducible; now bit-stable.
Performance
- f2_chantler scalar 19.7 us -> 106 ns (186x)
- xray_delta_beta 142 us -> 1.20 us (118x)
- xray_lines + filter 84 us -> 2.29 us (37x)
API (breaking)
- Structured returns (RefractiveIndex, Material, Composition, EdgeGuess) replace
tuples; parameter structs replace 8-11 positional optics arguments; scalar _at
variants throughout; thiserror errors that list valid options.
New
- xraydb CLI with JSON/CSV output and a machine-readable 'commands' subcommand.
- Browser demo on xraydb-wasm, and a project icon.
MSRV 1.88. 203 tests.