You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Introduce projected range to libdedx and wrap it (together with the already-existing CSDA range) behind a small, capability-aware transport-quantities API. The design keeps CSDA computed-by-integration (as today), adds projected range as authoritative tabulated data only, and makes the library report explicitly when projected range is unavailable rather than ever returning an approximation.
This is the upstream/core half of the work; the WASM contract + UI half is tracked downstream in aptg/dedx_web (companion issue linked below).
Current state (research findings)
CSDA range already exists.dedx_get_csda() (src/dedx_tools.c:167) computes it by adaptive Gaussian quadrature of 1/S(E) over [E_min, E]. Wrappers: dedx_get_csda_range_table() (src/dedx_wrappers.c:215), dedx_get_inverse_csda(), dedx_get_inverse_stp(). This is purely a function of the stopping-power curve and works uniformly for every program including custom compounds — it should stay computed.
Projected range does not exist anywhere in the codebase (no projected/detour references).
Data model stores stopping power only.dedx_embedded_program_data (src/dedx_embedded_data.h) and the raw data/raw/*.dat files keep a single value column per (ion, target, energy); no range columns are retained.
ESTAR/electrons:dedx_estar.h data is present but the path is hard-disabled (dedx.c:587 → DEDX_ERR_ESTAR_NOT_IMPL).
endpoint projected onto initial direction = R_CSDA × detour
No — needs multiple-scattering info
Authoritative projected-range data availability is non-uniform, and the API must reflect that:
Program
CSDA
Projected
Detour
PSTAR (protons)
✅ NIST
✅ NIST
✅
ASTAR (alphas)
✅ NIST
✅ NIST
✅
ESTAR (electrons)
✅ NIST
❌ NIST tabulates CSDA + radiation yield only
❌
MSTAR / ICRU73 / Bethe
computed
❌ none tabulated
—
ICRU90
report tables
per-ion, needs verification
—
Decisions taken (from design review)
No approximation fallback. Programs/ions without authoritative projected-range data report DEDX_RANGE_UNAVAILABLE. We do not return projected = CSDA for heavy ions. Callers (web UI) grey out the quantity, mirroring the existing ESTAR-greyout pattern.
Phased delivery. This issue's deliverable is Phase 1 (API + data plumbing + PSTAR/ASTAR tabulated projected range). Electron support and any computed scattering-power detour model are explicit future phases.
Proposed design
1. Capability-aware transport API
New public surface (in a new dedx_range.h, or extending dedx_tools.h) with an explicit method out-parameter so a tabulated value is never confused with an approximation:
typedefenum {
DEDX_RANGE_UNAVAILABLE=0, /* no authoritative data / no model */DEDX_RANGE_TABULATED, /* interpolated from authoritative table */DEDX_RANGE_CSDA_INTEGRAL, /* computed ∫dE/S (CSDA) */DEDX_RANGE_DETOUR_MODEL/* computed via scattering model (future) */
} dedx_range_method;
doublededx_get_csda_range (dedx_workspace*, dedx_config*, floatE, int*err);
doublededx_get_projected_range(dedx_workspace*, dedx_config*, floatE,
dedx_range_method*method, int*err);
doublededx_get_detour_factor (dedx_workspace*, dedx_config*, floatE,
dedx_range_method*method, int*err);
/* Query without computing — lets a GUI grey out UI ahead of time */intdedx_supports_projected_range(intprogram, intion, inttarget);
dedx_get_csda() stays as a thin backward-compatible alias of dedx_get_csda_range().
Mirror the existing CSDA surface: add dedx_get_projected_range_table(), inverse projected-range, and flat (workspace-free) wrappers, so the downstream WASM integration is a copy of the CSDA path.
When projected range is unavailable: set method = DEDX_RANGE_UNAVAILABLE, return a sentinel (e.g. -1) and a non-fatal error code (new DEDX_ERR_PROJECTED_RANGE_UNAVAILABLE).
2. Provider resolution order (per program/ion/target)
Tabulated projected range if embedded (PSTAR, ASTAR; ICRU90 where verified).
Detour model — future phase, not in scope here.
Otherwise DEDX_RANGE_UNAVAILABLE.
3. Backward-compatible data-model extension
Add optional parallel payload to dedx_embedded_program_data (NULL when absent, so embedding is incremental and never breaks existing programs):
constfloat*projected_range; /* [ion][target][energy], or NULL *//* (optionally) const float *csda_range; for NIST cross-checks */
Extend tools/dat2c.py / tools/pdf2dat.py to emit *_proj.h headers from the NIST projected-range column, with provenance comments and reproducible regeneration documented in data/README.md.
Re-extract PSTAR/ASTAR projected-range columns into new data/raw/*proj*.dat inputs.
4. Tests & validation
Assert tabulated projected-range values against NIST reference points (same style as the existing PSTAR H₂O 100 MeV check).
Assert dedx_supports_projected_range() returns 0 for ESTAR/MSTAR/ICRU73/Bethe and custom compounds, and that those paths cleanly return UNAVAILABLE (no crash, no silent CSDA substitution).
Verify dedx_get_csda() ≡ dedx_get_csda_range() (no regression).
Scope of this issue (Phase 1)
New capability-aware range API (dedx_get_csda_range, dedx_get_projected_range, dedx_get_detour_factor, dedx_supports_projected_range) + dedx_get_csda alias
Phase 3 (larger): un-gate ESTAR/electrons and add a scattering-power detour model (Highland/Lewis; ICRU 35 for electrons) so electrons get a real projected range — deferred because no NIST projected-range source exists for electrons.
Downstream
WASM API contract + web UI integration is tracked in the companion aptg/dedx_web issue (will be cross-linked once filed). Relates to the upstream-migration tracking in #118.
Summary
Introduce projected range to libdedx and wrap it (together with the already-existing CSDA range) behind a small, capability-aware transport-quantities API. The design keeps CSDA computed-by-integration (as today), adds projected range as authoritative tabulated data only, and makes the library report explicitly when projected range is unavailable rather than ever returning an approximation.
This is the upstream/core half of the work; the WASM contract + UI half is tracked downstream in
aptg/dedx_web(companion issue linked below).Current state (research findings)
dedx_get_csda()(src/dedx_tools.c:167) computes it by adaptive Gaussian quadrature of1/S(E)over[E_min, E]. Wrappers:dedx_get_csda_range_table()(src/dedx_wrappers.c:215),dedx_get_inverse_csda(),dedx_get_inverse_stp(). This is purely a function of the stopping-power curve and works uniformly for every program including custom compounds — it should stay computed.projected/detourreferences).dedx_embedded_program_data(src/dedx_embedded_data.h) and the rawdata/raw/*.datfiles keep a single value column per(ion, target, energy); no range columns are retained.dedx_estar.hdata is present but the path is hard-disabled (dedx.c:587→DEDX_ERR_ESTAR_NOT_IMPL).dedx_embedded_icru90_p/_a/_C).Physics constraint that drives the design
S(E)alone?∫₀ᴱ dE'/S(E')— total path lengthR_CSDA × detourAuthoritative projected-range data availability is non-uniform, and the API must reflect that:
Decisions taken (from design review)
DEDX_RANGE_UNAVAILABLE. We do not returnprojected = CSDAfor heavy ions. Callers (web UI) grey out the quantity, mirroring the existing ESTAR-greyout pattern.Proposed design
1. Capability-aware transport API
New public surface (in a new
dedx_range.h, or extendingdedx_tools.h) with an explicit method out-parameter so a tabulated value is never confused with an approximation:dedx_get_csda()stays as a thin backward-compatible alias ofdedx_get_csda_range().dedx_get_projected_range_table(), inverse projected-range, and flat (workspace-free) wrappers, so the downstream WASM integration is a copy of the CSDA path.method = DEDX_RANGE_UNAVAILABLE, return a sentinel (e.g.-1) and a non-fatal error code (newDEDX_ERR_PROJECTED_RANGE_UNAVAILABLE).2. Provider resolution order (per program/ion/target)
DEDX_RANGE_UNAVAILABLE.3. Backward-compatible data-model extension
Add optional parallel payload to
dedx_embedded_program_data(NULL when absent, so embedding is incremental and never breaks existing programs):tools/dat2c.py/tools/pdf2dat.pyto emit*_proj.hheaders from the NIST projected-range column, with provenance comments and reproducible regeneration documented indata/README.md.data/raw/*proj*.datinputs.4. Tests & validation
dedx_supports_projected_range()returns 0 for ESTAR/MSTAR/ICRU73/Bethe and custom compounds, and that those paths cleanly returnUNAVAILABLE(no crash, no silent CSDA substitution).dedx_get_csda()≡dedx_get_csda_range()(no regression).Scope of this issue (Phase 1)
dedx_get_csda_range,dedx_get_projected_range,dedx_get_detour_factor,dedx_supports_projected_range) +dedx_get_csdaaliasdedx_range_methodenum +DEDX_ERR_PROJECTED_RANGE_UNAVAILABLEprojected_rangepayload in the embedded data model (NULL-safe)UNAVAILABLEfor all programs/ions without authoritative datadata/README.md, public header docs)Future phases (explicitly out of scope here)
Downstream
WASM API contract + web UI integration is tracked in the companion
aptg/dedx_webissue (will be cross-linked once filed). Relates to the upstream-migration tracking in #118.https://claude.ai/code/session_01SmjfogDVtB59qhxnfyXGeZ