npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rexafs

v0.2.14

Published

Rust-powered X-ray absorption analysis for JavaScript and TypeScript

Readme

rexafs for JavaScript and TypeScript

Published user guide · Versioned API reference

Process X-ray absorption spectra in Node or a browser using the Rust engine compiled to WebAssembly. TypeScript declarations are included.

Install

We recommend Bun to manage the dependency:

bun add rexafs

Run the library in Node 22+, or a browser with WebAssembly support. Bun can install the package for either runtime; npm install rexafs and pnpm add rexafs are also available. The npm package includes the Wasm binaries; Rust is not required to use it. Imports are ECMAScript modules.

Version note: options constructors, direct configuration arguments and XrayFFTR were added in 0.2.5. The basic pipeline also works in 0.2.4.

Node quick start

Save as analyze.mjs and run node analyze.mjs:

import { readFileSync } from "node:fs";
import { Spectrum } from "rexafs/node";

// Whitespace-delimited energy (eV) and absorption mu; # starts a comment.
const rows = readFileSync("spectrum.dat", "utf8")
  .split(/\r?\n/).map(line => line.split("#")[0].trim()).filter(Boolean)
  .map(line => line.split(/\s+/).map(Number));
const energy = Float64Array.from(rows, row => row[0]);
const mu = Float64Array.from(rows, row => row[1]);
const spectrum = new Spectrum(energy, mu);
try {
  spectrum.fft();
  console.log(spectrum.e0(), spectrum.r(), spectrum.chir_mag());
} finally {
  spectrum.free();
}

Node loads the packaged Wasm automatically. The optional default init() export is a no-op in Node, useful for code shared with browsers.

Browsers

import init, { Spectrum } from "rexafs/browser";
await init(); // Required before constructing spectra or settings.
// energy and mu are Float64Arrays loaded by your application.
const spectrum = new Spectrum(energy, mu);
try {
  spectrum.fft();
  const r = spectrum.r();
  const magnitude = spectrum.chir_mag();
  // Use the copied arrays here, or retain them outside this block.
} finally {
  spectrum.free(); // Copied arrays remain valid, including if processing failed.
}

Serve the packaged Wasm asset alongside its glue module. init(wasmUrl) or init(wasmBytes) allows an explicit asset location when a bundler relocates it. The root rexafs import selects the runtime through package export conditions; use rexafs/browser or rexafs/node when you want to choose explicitly. Calculations are synchronous after initialization; run long work in a Web Worker.

Configure only what you need

import { AUTOBK, XrayFFTF, XrayFFTR } from "rexafs/node";

const background = new AUTOBK({ rbkg: 1.0 });
const forward = new XrayFFTF({ kmin: 2.0, kmax: 12.0, kweight: 2.0 });
const inverse = new XrayFFTR({ rmin: 1.0, rmax: 3.0, dr: 0.5 });
try {
  spectrum.set_background_method(background).set_fft(forward).fft();
  spectrum.set_ifft(inverse).ifft();
  console.log(spectrum.q(), spectrum.chiq());
} finally {
  background.free(); forward.free(); inverse.free();
}

This fragment assumes a live spectrum; the ranges are examples to adapt to your data. Settings are copied by setters, so they can be freed after assignment. Changing a settings object later requires assigning it again. Rust-style BackgroundMethod.AUTOBK(settings) and NormalizationMethod.PrePostEdge(settings) remain available. Scalar field names and stage names match Rust; no additional pipeline object is needed.

| Settings | Recommended starting values | |---|---| | new PrePostEdge() | Automatic E0, pre/post-edge ranges and polynomial order | | new AUTOBK() | rbkg: 1, kstep: 0.05, kweight: 1, window: "Hanning", solver: "LinearDirect", clamp_scale_policy: "FixedPenalty", clamp_lambda: 0.001 | | new XrayFFTF() | kmin: 2, kmax: 15, kweight: 2, dk: 1, window: "KaiserBessel", nfft: 2048, grid: "Input" | | new XrayFFTR() | rmin: 0, rmax: 20, dr: 1, rweight: 0, qmax_out: 10, nfft: 2048, automatic kstep |

Omitted options retain the constructor defaults. Explicit undefined requests automatic resolution for optional fields; for example { kmax: undefined } uses the available k range rather than the forward default of 15 Å⁻¹. Automatic values are resolved on the spectrum's copied settings. The original settings object still reports the values you assigned, so its unset fields do not become a record of the resolved calculation parameters. Use new PrePostEdge({ ... }) with set_normalization_method() for custom normalization and set_e0(eV) to override the edge energy.

In 0.2.4 and later, calling set_normalization_method() or set_background_method() without an argument restores that stage's recommended defaults. null and undefined have the same effect. For custom settings, 0.2.4 accepts algorithm wrappers; 0.2.5 also accepts PrePostEdge and AUTOBK settings directly.

What the calculations mean

Normalization subtracts a fitted pre-edge baseline and divides absorption by its edge step. AUTOBK estimates the smooth background to obtain the EXAFS oscillations, chi(k). The Fourier transform weights and windows those oscillations to display them against R; its peaks are not automatically phase-corrected bond lengths. An inverse transform filters selected R contributions back into q space.

The processing theory guide explains the equations, symbols, units, assumptions and implementation choices, with scientific references. Use the fitting-statistics guide when interpreting structural fits and uncertainties.

Completion and hover help

Since 0.2.5, the package includes explanatory JSDoc for every exported configuration field, constructor and spectrum method. Version 0.2.4 has shorter editor help; the online stable reference preserves the published signatures. Options interfaces (AUTOBKOptions, XrayFFTFOptions, etc.) and string unions (FTWindow, FFTGrid, AUTOBKSolver, AUTOBKClampScalePolicy) are exported from all entry points. Editors can suggest field names and valid string choices, show units/defaults on hover and flag typos. Use TypeScript moduleResolution: "NodeNext" for Node or "Bundler" for a bundler project so package export conditions resolve correctly.

Inputs must be finite, equal-length Float64Arrays with strictly increasing energy in eV. k/q use Å⁻¹ and R uses Å. Result getters return independent arrays, or undefined before the corresponding stage runs. Narrow that optional result before indexing it. Stages return the same spectrum and throw on failure. Changing parameters invalidates dependent stages; see the shared API guide for details.

The forward transform multiplies the unnormalized, negative-exponent discrete Fourier transform by kstep / Math.sqrt(Math.PI). It applies no additional 1 / nfft or window-area correction. With dimensionless chi and k weight w, chir_real(), chir_imag() and chir_mag() have units Å⁻⁽ʷ⁺¹⁾. Use kwin_k() with kwin() because the window grid can differ from the background grid when grid is "Larch". The processing theory explains this convention and its implementation sources.

Build from source

From the repository root with Rust and Node installed:

rustup target add wasm32-unknown-unknown
cargo install wasm-pack --locked
npm --prefix js-rexafs ci
npm --prefix js-rexafs run build
npm --prefix js-rexafs test
cd js-rexafs
npm pack
# From your application directory, install the resulting file:
# npm install /path/to/rexafs/js-rexafs/rexafs-0.2.5.tgz

The package includes Node/browser Wasm and declarations. Filesystem reading, EXAFS fitting, groups, structure downloads and FEFF execution remain Rust/desktop APIs. ILPBkg remains unimplemented. The MBack API below adds full (since 0.2.10) atomic-reference normalization. TrustRegionDogLeg requires a native Rust feature absent from Wasm. The recommended LinearDirect/FixedPenalty path works in both bindings. See FFT compatibility. Licensed under MIT OR Apache-2.0.

Universal measurement reader (since 0.2.6)

Version 0.2.6 adds content-detected beamline text, CSV, Athena, XTUNES and HDF5 import through the shared Rust reader. Read a document, inspect its scans, columns, units and warnings, then select a signal mapping. Ambiguous channels require explicit selection; detector images require reduction before creating an absorption spectrum. Reading performs no processing or corrections. See the reader guide for language examples, unit conversions, dataset selection, fixture coverage and limits. This API is not included in the published 0.2.5 packages.

Larix 1.0 session import is available in the shared reader since 0.2.6, including stored absorption, complex saved arrays and inert session metadata. See the Larix import guide.

Column selections accept exact, case-sensitive names as well as zero-based indices. For QAS data, use measurement.arrays({energy: "energy", i0: "i0", it: "it"}) for transmission, iff: "iff" instead of it for fluorescence, or i0: "it", it: "ir" for the reference. Existing positional mappings remain valid. Duplicate names require indices. Omit energy_unit to preserve detected axis calibration, or explicitly override it with "eV" or "keV".

Scalar measurements (since 0.2.10)

Version 0.2.10 adds this call:

const result = spectrum.measure("mean", [-20, 30], { space: "flat" });
console.log(result.value, result.unit);

The default is normalized absorption with E₀-relative energy bounds in eV. Missing stages run on a private copy; existing arrays/settings remain unchanged. Choose origin: "absolute" for absolute energy, or space: "chi"/"fourier" for absolute k/R. Point, maximum, integral and mean share strict native-grid coverage checks. See the measurement guide for units, optional independent errors and numerical assumptions. This scalar operation is separate from the Measurement input-file reader. Type declarations include options, result fields, completion choices and hover help.

Full MBACK normalization (since 0.2.10)

import { MBack } from "rexafs/node";
const model = new MBack("Cu", "K", {pre_edge: [-200,-50], post_edge: [100,800]});
const result = model.fit(energy, mu); // Float64Array inputs: eV and raw absorption
spectrum.set_normalization_method(model).normalize();
console.log(result.norm, result.flat);
model.free();

Ranges are E₀-relative eV. Degree 2 and no erfc are the defaults. Offline atomic data load automatically. Results own their arrays; spectrum settings copy the model. spectrum.mback_result() retrieves its saved result or undefined after invalidation. result.definition creates a model pinned to the original reference; free that model after use. Browser callers must await init() and should use a Worker for large synchronous fits. See the MBACK guide for equations, assumptions and optional backgrounds. Atomic-data notices ship in the npm package's licenses/atomic directory.

Cauchy wavelets (since 0.2.10)

import { Wavelet } from "rexafs/node";
const model = new Wavelet([2, 12]);
const map = spectrum.wavelet(model);
try {
  const image = map.magnitude; // Independent Float64Array: R rows, k columns
  const region = map.integral([4, 10], [1, 3]);
  console.log(image, region.value, region.unit);
} finally {
  map.free();
  model.free();
}

The k interval uses Å⁻¹; R uses Å and is not phase-corrected. Missing normalization and background stages run on a private copy. Defaults are weight 2, order 100, k spacing 0.05 Å⁻¹, R up to 6 Å and no taper. Named options override them, for example new Wavelet([2, 12], {rmax: 4}). model.calculate(k, chi) also accepts unweighted χ(k) in Float64Array inputs. Browser callers await init() first. See the wavelet guide for layout, native-grid integrals, slices, ownership, JSON replay and scientific limitations.

Fluorescence over-absorption (since 0.2.10)

import { FluorescenceCorrection } from "rexafs/node";
const model = new FluorescenceCorrection("CuO", "Cu", "K", {line:"Ka1", angles:[45,45]});
const corrected = spectrum.correct_fluorescence(model);
try { corrected.normalize(); }
finally { corrected.free(); model.free(); }

Supply the complete sample composition, detected emission and measured incident/exit angles from the sample surface, in degrees. The angles above are examples. Internal normalization is automatic; final normalization is separate. The original stays unchanged. The new native spectrum preserves correction history and its XANES-only restriction through edits; known transmission and repeated correction fail. See the correction guide for the homogeneous thick-sample assumptions, diagnostics, replay and array API.

XANES peak fitting (since 0.2.10)

PeakFit and Spectrum.fit_peaks fit named peaks, absorption steps and baseline terms through the native core. The default representation is normalized absorption, with energy bounds relative to E₀ in eV. Results retain component curves, termination and conditional uncertainty diagnostics. The model does not select a peak count or identify chemical species. See the XANES fitting guide for binding examples, area/width conventions, constraints and interpretation limits.