DXASCalc is a browser-based calculator for dispersive X-ray absorption spectroscopy optics. It supports Bragg and Laue geometries, keeps the bending-radius and focus sign conventions explicit, and explains geometry states instead of displaying negative widths as if they were physical sizes. The API validates input and the numerical implementation has legacy and solver regression tests; these checks do not constitute experimental validation.
- A dependency-free calculation core in
dxascalc/replaces UI-coupled, order-dependent calculations for the web application. - Inputs and outputs use immutable, JSON-safe models with units in every field name.
- Invalid Miller indices, unreachable energies, zero radii, geometry singularities, and extreme JSON numbers return structured field errors.
- Signed orientation values are retained separately from non-negative display magnitudes.
- A Flask API and React interface are independently testable and run together as one deployable web service.
- The geometry-first Plotly workbench mirrors the beamline right-to-left,
supports schematic and physical scales, and lets users drag the source or
detector to update
porqbefore recalculating through the input-validating API. - Crystal-response calculations expose the sigma, pi, and selected polarization curves, their interpolated FWHM, and the finite-source contribution. Bragg uses XOP's bent-crystal multilamellar model and Laue uses its Penning-Polder model.
- Estimated total energy resolution is the FWHM of a numerical convolution of the crystal response, a Gaussian source-size response, and a one-pixel detector response. Detector sampling remains separately labeled in eV/px.
- The original Notebook calculator remains available as migration and research context; new web code does not import its widgets or file-writing workflow.
The scientific contract and unresolved Laue sign convention are documented in
docs/SCIENTIFIC_MODEL.md.
Requirements: Python 3.9+ and Node.js 20.19.x or 22.12+ (the frontend build toolchain does not support older Node releases).
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
npm ci --prefix frontend
npm run build --prefix frontend
python app.pyOpen http://localhost:5002.
For frontend development, keep python app.py running and start Vite in a
second terminal:
npm run dev --prefix frontendThe development interface is available at http://localhost:5173 and proxies
API calls to the local Flask process.
Enter any positive photon energy in eV in the Crystal panel, or choose an
element and its K, L1, L2, or L3 absorption edge to fill that field from
xraylib's tabulated edge energy. Editing the number switches the picker back
to Custom energy. The selected value still passes through the calculator's
crystal and reflection validation when recalculated. Existing API requests and
saved configuration files retain the energy_kev field for compatibility;
the interface converts at the input boundary.
Use Save and Load in the desktop toolbar (or the application menu on a small screen) to download the current setup as a versioned JSON file and open one of these files. Loading replaces the setup inputs and recalculates them with the input-validating API. The file includes all scientific inputs but no calculated results, so it can be shared or saved alongside an experiment.
- Update results (or Ctrl/⌘ + Enter) calculates edited inputs; the button reads Recalculate when the result is current. Diagram distance edits, geometry changes, and presets calculate when applied.
- Optics & results, Crystal response, and Compare setups separate the optical layout, detailed model response/coverage, and baseline comparison. All views keep the same inputs and accepted result. Set a baseline from Compare setups, then edit inputs and update results to compare them.
- The parameter shortcuts open Crystal, Geometry, or Detector. Individual section headings can also expand multiple groups; collapsed headings retain input summaries and error counts. Common reflection buttons fill h, k, and l without replacing the rest of the setup.
- Expand the pending-change count to review old and new input values. Revert restores the last calculated inputs; selecting a changed field focuses it.
- Inputs are saved locally in the browser, including unfinished numeric fields. On reopening, those inputs are restored and calculated again. Results and comparison baselines are not stored. If browser storage is unavailable, use Save to keep a configuration file.
- Preset changes, loading a file, and resetting defaults offer Undo until another input edit. Revert to calculated inputs restores the inputs for the last accepted result.
- Calculations have a 45-second request timeout and a Cancel control. Failed requests retain the edited inputs and last accepted result. Retry calculation resubmits the current inputs; unavailable preset and edge lists have their own retry controls. Cancellation stops waiting in the browser; a solver already running on the server can finish within its existing timeout.
- Narrow screens switch between Optics & results and Parameters, with the calculate action kept available at the bottom of the parameter view.
- Select the info icon beside an input to expand its explanation beneath the control; Escape closes it. Use the plot toolbar to zoom; the mouse wheel scrolls the page.
- In Detector, choose whether to enter the crystal-to-detector ray distance
q, its along-beam projection|q∥|, or its across-beam projection|q⊥|. Entering a projection converts it toqat the current calculated2θ; choose Update results to update the result. If material, reflection, or energy changes, recalculate first so the conversion uses the new angle. Saved configurations retain the physical ray distanceq; displayed projections update when the angle changes. - You can also type directly into |q∥| or |q⊥| on the diagram (or its
compact guide summary). Press Enter or leave the field to convert that
projection to
qand recalculate. The other projection updates with it; Escape cancels an edit. Recalculate changed energy/material/reflection inputs first so projection conversion uses the current angle.
python -m unittest discover -s tests -v
npm test --prefix frontend
npm run build --prefix frontendDevelopers who install the optional test dependencies with
pip install -e '.[dev]' can run the same Python suite through python -m pytest.
Pytest discovery is restricted to tests/, so the archived sample project and
its optional scientific dependencies are not collected.
The characterization suite freezes representative Bragg and Laue results from
the previous dxas_core.py implementation, including upper/lower conditions,
positive/negative radii, asymmetric Ge(220), diamond-cubic reflection rules,
and error-boundary behavior.
GET /api/health— service healthGET /api/presets— reviewed Bragg and Laue starting configurations for Si(111), Si(220), and Si(311)GET /api/absorption-edges— elements 1–100 and their available K/L1/L2/L3 edge energies in keVPOST /api/calculate— calculate one configuration
Validation failures return HTTP 422 with field-addressable issues:
{
"error": "invalid_configuration",
"issues": [
{
"level": "error",
"code": "energy_unreachable",
"message": "Energy is below the Bragg limit for this material and reflection.",
"field": "energy_kev"
}
]
}The web calculation keeps the deterministic geometry core separate from the XOP-backed crystal-response adapter. Each XOP request runs in an isolated temporary directory with a timeout, and successful XOP crystal curves are cached by their scientific inputs in a bounded 32-entry cache. Temporary fallback curves are retried on the next request. Scalar metrics retain the full 10001-point solver resolution while Plotly receives at most 2501 evenly sampled display points. The complete enrichment path has bounded concurrency, and response convolution uses NumPy FFTs. Source size is interpreted as a spatial FWHM in the dispersive plane; detector sampling is modeled as a one-pixel top-hat response, not as a Gaussian detector FWHM.
The reported total is therefore a model estimate rather than a measured
instrument line-spread function. In particular, the Laue estimate does not add
a separate Borrmann-fan spatial contribution, and neither geometry includes
fabrication strain or a measured detector PSF unless those effects are already
represented by the selected XOP response. See
docs/SCIENTIFIC_MODEL.md for the complete
assumptions and provenance.
Authors: Juanjuan Huang and George Sterbinsky Copyright © 2024, UChicago Argonne, LLC