Conversation
- Introduced `stopping_power` function to calculate stopping power in MeV*cm²/g. - Refactored existing mass stopping power functionality into `stopping_power.cpp` and `stopping_power.h`. - Updated stopping bindings to include new `stopping_power` function. - Enhanced error handling for particle and material processing. - Added support for both scalar and array inputs for energy, particle, and material.
…d-water-according-to-one-of-the-models_2
There was a problem hiding this comment.
Pull request overview
This PR adds new stopping power APIs to the pyamtrack.stopping nanobind module, exposing libamtrack stopping power calculations to Python (with vectorization support via the existing wrapper utilities).
Changes:
- Add new C++ wrapper functions
mass_stopping_power()andstopping_power()(nanobind-friendly, vectorized/cartesian-product capable). - Expose these functions in the
stoppingPython extension module. - Add a Jupyter notebook example demonstrating stopping power calculations.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/stopping/stopping_power.h |
Declares new stopping power API functions/constants for the stopping module. |
src/stopping/stopping_power.cpp |
Implements stopping power wrappers, argument normalization, and Particle/Material handling. |
src/stopping/stopping_bindings.cpp |
Registers the new functions in the nanobind module (and currently exports a debug function). |
src/stopping/electron_range.cpp |
Makes get_id static to avoid external linkage conflicts. |
examples/stopping.ipynb |
Adds an example notebook (currently has a unit/label mismatch vs the function called). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Witold Nieć <witold.niec@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…d-water-according-to-one-of-the-models_2
Agent-Logs-Url: https://github.com/libamtrack/pyamtrack/sessions/822ea03a-8fdf-4b4f-82f0-927cb5daedbe Co-authored-by: witNie <180410451+witNie@users.noreply.github.com>
…d-water-according-to-one-of-the-models_2
…ding-to-one-of-the-models_2' of https://github.com/libamtrack/pyamtrack into 62-add-stopping-power-for-protons-in-liquid-water-according-to-one-of-the-models_2
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It adds a substantial native binding module with intricate numeric/memory logic and introduces a functional regression (empty models submodule breaks pyamtrack.stopping.models.* used by an existing example), so human review is warranted.
Review effort: Balanced
Findings: 1
grzanka
left a comment
There was a problem hiding this comment.
Good feature overall (vectorised API, return_source, thorough mass_stopping_power docstring). Findings below, most important first.
🔴 P1 – blockers
- Tests are disabled. In
tests/test_stopping.py~177 of 397 lines are commented out: all 7 pre-existingelectron_rangetests plus 9 earlier new tests (invalid-argument,Ion/Materialargument, string/enumsource, …). Green CI no longer coverselectron_range(touched here) or the type-validation paths. Restore the old tests; revive or delete (not comment out) the new ones. - Unrelated breaking change:
pyamtrack.stopping.models.*constants are gone. The loop populatingmodelsinstopping_bindings.cppis commented out, sostopping.models.tabata/.edmundraiseAttributeError.examples/example.ipynb(l. 222, 289, 321, 327) still uses them, and (1) hides it. Restore, or deprecate explicitly in a separate PR. No commented-out code, please.
🟠 P2 – should fix before merge
- Inconsistent error contract. Docstring promises
TypeErrorfor a badsourcetype, butparse_stopping_power_sourcethrowsinvalid_argument(→ValueError) and silently accepts ints 0–3 (undocumented). For list/array input the shared wrapper rewraps everything asRuntimeError("Error processing 1-D NumPy array: …"), so scalar →ValueError, vector →RuntimeError(the new tests assert both). Pick one contract and document it. - No physics anchors in tests. Active tests compare the function to itself (scalar vs vector vs cartesian) or check
> 0. Add 2–3 NIST PSTAR reference values with a tolerance (e.g. 100 MeV p in liquid water ≈ 7.289 MeV·cm²/g). - Re-implements libamtrack internals.
stopping_power.cpphand-declaresextern AT_stopping_power_ICRU_table[2]/PSTAR_data(not in public headers) and hard-codesmaterial_no - 1,Z > 18, He ≤ 250 MeV/u, materialsWater_Liquid..Copper. This silently rots if upstream changes. Prefer upstream status codes / a public API; at minimum name and comment the constants and pin them with a test. source="default"silently switches physics model per element (PSTAR→Bethe outside the table), andallow_multiple_sources=Falsethen raises a generic "Inconsistent stopping power source selection" with no element/energy and no hint about the flag. Consider dropping the flag (and its stateful mutable lambda) in favour ofreturn_source/ a warning, or at least make the message actionable.- API shape.
return_source=Truechanges the return type (value → tuple); prefer a separate function or result object.help()showssource=0while docs say"default"..export_values()leaksDEFAULT/BETHE/PSTAR/ICRUinto thepyamtrack.stoppingnamespace.
🟡 P3 – maintainability
- Formatting churn mixed with logic (~100 lines of clang-format reflow in
particles.cpp/.h,ion.h). Split it out so the functional diff is reviewable. - Dead code:
Particle::get_id()is unused;Particle::get_particle_no()(throwing, non-virtual, hidden byIon::) is unreachable;select_stopping_power_source(…, particle_no)ignores its parameter;parse_/select_stopping_power_sourceare internal but exported instopping_power.h. - Duplicate passes:
validate_particle_argument+parse_particle_argument(same for material) walk the same structure twice (tolist()twice for arrays), then the wrapper walks it again. Onenormalize_*returning validated IDs would do. - Portability:
source_idsuselong(int32 on Windows, int64 elsewhere) → useint64_t.windows.ymldoesn't run on PRs, so this is unexercised.
🟢 P4 – docs / hygiene
docs/naming_convention.mdlists every publicpyamtrack.stoppingfunction and argument, but was not updated (mass_stopping_power,stopping_power,particle,source,allow_multiple_sources,return_source,StoppingPowerSource).stopping_powerhas no Parameters/Returns/Raises docstring.examples/stopping_power.ipynbis a scratch notebook (one ad-hoc call, leftover outputs, empty last cell) that duplicatesstopping.ipynb; drop it.stopping.ipynbagain ends with an empty code cell.- Empty PR description, typo in title ("implemetations"), 21 commits incl. "refactor wip" and 4 merges. Describe scope and API, squash on merge.
…ve argument handling
Co-authored-by: Leszek Grzanka <leszek.grzanka@gmail.com> Signed-off-by: Witold Nieć <witold.niec@gmail.com>
Co-authored-by: Leszek Grzanka <leszek.grzanka@gmail.com> Signed-off-by: Witold Nieć <witold.niec@gmail.com>
…ify error messages
…ing parameters, return values, and error handling.
…pted types and improve error messages






No description provided.