Skip to content

Commit 4d6ff4d

Browse files
authored
Add initial documentation and fix energy loss bugs (#260)
* First attempt at fixing bug * Fix Bethe-Bloch straggling and add CATIMA benchmark tests - GetElossStraggling/GetdEdxStraggling: evaluate dEdx at energyFin (Tschalar formula requires stopping power at the exit point, not entrance; error was largest near the Bragg peak) - BuildSpline: replace manual trapezoidal rule for Ω²(E) with a spline of 1/dEdx³ and segment-wise Simpson integration (exact for cubics) - AtELossCATIMA: add fConfig member and SetConfig() so callers can tune the CATIMA calculation model; thread fConfig through all catima API calls (default_config preserves existing behaviour) - AtELossBetheBlochTest: add AtELossBetheBlochVsCATIMAFixture comparing GetRangeVariance and GetElossStraggling against pure-Bohr CATIMA (z_eff_type::none) at narrow and wide energy traversals up to 10→1 MeV * Add energy loss model comparison macro * Add documentation useful for agents/humans Add documentation into four subdirectories directly under docs/: - tooling/: installation, daily-use (merged setup+building), testing - contributing/: contributor guide, new-module, code-style - reference/: modules, data-model, branch-io-contracts, macro-cookbook - subsystems/: simulation/reconstruction pipelines, generators, psa, energy-loss docs/development/ is reserved for branch-specific in-progress notes (fitting-status.md, UKF.md, etc.). Update all cross-links and the CLAUDE.md to point to the new docs rather than repeat the information. * Fix MeV/cm vs MeV/mm unit error in AtELossCATIMA GetBraggCurve stored result.dEdxi * fDensity directly (MeV/cm) into the output vector, while all other paths (GetdEdx, base-class GetBraggCurve) divide by 10 to convert to MeV/mm. The energy-step calculation in the same loop used dEdx * rangeStepSize / 10, which accidentally cancelled the unit error during tracking, so range and energy results were unaffected — only the returned dEdx y-values were 10× too large, inflating the displayed Bragg peak height relative to BB and SRIM curves. Adds a fourth model per scenario — CATIMA with bare projectile charge (z_eff_type::none) and dEdx corrections disabled (no Barkas, Lindhard, or shell corrections) — to isolate which physics differences drive the disagreement between Bethe-Bloch and full CATIMA: - dEdx/range divergence at low energy → effective charge (Pierce-Blann) - Range straggling floor in BB vs steep fall in CATIMA → Firsov/Lindhard-X straggling correction (hardwired in CATIMA, absent in BB) - Bragg peak shape difference → effective charge suppressing dEdx as v→0 * Update checkout github action version
1 parent 82ecba9 commit 4d6ff4d

33 files changed

Lines changed: 2055 additions & 158 deletions

.claude/CLAUDE.md

Lines changed: 42 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,146 +1,60 @@
11
# CLAUDE.md
22

3-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4-
5-
## About
6-
7-
ATTPCROOT is a ROOT/FairRoot-based C++ framework for simulation and analysis of Active Target Time Projection Chamber (AT-TPC) detector data. It integrates with FairSoft (provides ROOT, Geant4, VMC) and FairRoot (provides the task/run framework).
8-
9-
## Environment Setup
10-
11-
Before building or running anything, the environment must be loaded. The VSCode terminal auto-sources this on startup:
12-
13-
```bash
14-
source build/config.sh
15-
```
16-
17-
This sets `LD_LIBRARY_PATH`, `ROOTSYS`, `VMCWORKDIR`, `ROOT_INCLUDE_PATH`, and Geant4 data paths. The key install paths on this machine are:
18-
- FairRoot: `~/fair_install/FairRootInstall`
19-
- FairSoft: `~/fair_install/FairSoftInstall`
20-
21-
For CMake configuration (not the build itself), the following env vars are needed:
22-
```bash
23-
export FAIRROOTPATH=~/fair_install/FairRootInstall
24-
export SIMPATH=~/fair_install/FairSoftInstall
25-
```
26-
27-
## Build Commands
28-
29-
```bash
30-
# Configure (from repo root, out-of-source into build/)
31-
cmake -S . -B build -DCMAKE_PREFIX_PATH=~/fair_install/hdf5
32-
33-
# Build (10 parallel jobs)
34-
cmake --build build -j10
35-
36-
# Build a specific target
37-
cmake --build build --target AtSimulationData -j10
38-
39-
# Run all unit tests
40-
cd build && ctest -V
41-
42-
# Run a specific test binary directly
43-
./build/tests/AtSimulationDataTests
44-
./build/tests/AtGeneratorsTests
45-
./build/tests/AtToolsTests
46-
```
47-
48-
Tests are built by default (`BUILD_TESTS=ON`). Test binaries are placed in `build/tests/`.
49-
50-
## Code Formatting
51-
52-
The project uses `clang-format-17` with the config in `.clang-format` (based on LLVM style, 3-space indent, 120-char column limit). Format on save is configured in VSCode. To format manually:
3+
ATTPCROOT is a ROOT/FairRoot-based C++ framework for simulation and analysis of Active Target Time Projection Chamber (AT-TPC) detector data.
4+
5+
## Documentation
6+
7+
Full developer documentation lives in `docs/`. See [docs/index.md](../docs/index.md) for the full map. Quick topic links:
8+
9+
| Topic | File |
10+
|-------|------|
11+
| First-time install | [tooling/installation.md](../docs/tooling/installation.md) |
12+
| Daily use (build/test) | [tooling/daily-use.md](../docs/tooling/daily-use.md) |
13+
| Testing patterns | [tooling/testing.md](../docs/tooling/testing.md) |
14+
| Contributor guide | [contributing/guide.md](../docs/contributing/guide.md) |
15+
| Adding a new module | [contributing/new-module.md](../docs/contributing/new-module.md) |
16+
| Code style | [contributing/code-style.md](../docs/contributing/code-style.md) |
17+
| Module overview | [reference/modules.md](../docs/reference/modules.md) |
18+
| Data model | [reference/data-model.md](../docs/reference/data-model.md) |
19+
| Branch I/O contracts | [reference/branch-io-contracts.md](../docs/reference/branch-io-contracts.md) |
20+
| Simulation pipeline | [subsystems/simulation-pipeline.md](../docs/subsystems/simulation-pipeline.md) |
21+
| Reconstruction pipeline | [subsystems/reconstruction-pipeline.md](../docs/subsystems/reconstruction-pipeline.md) |
22+
| Event generators | [subsystems/generators.md](../docs/subsystems/generators.md) |
23+
| Pulse shape analysis | [subsystems/psa.md](../docs/subsystems/psa.md) |
24+
| Energy loss | [subsystems/energy-loss.md](../docs/subsystems/energy-loss.md) |
25+
26+
## Quick Reference: Build & Test
5327

5428
```bash
55-
clang-format-17 -i <file>
56-
# Or format all changed files:
57-
scripts/formatAll.sh
29+
source build/config.sh # load environment (do this first)
30+
cmake --build build -j10 # build everything
31+
cd build && ctest -V # run all unit tests
5832
```
5933

60-
Static analysis uses `clang-tidy` (config in `.clang-tidy`): modernize-* and cppcoreguidelines-* checks.
61-
62-
## Architecture
63-
64-
The framework follows FairRoot's task pipeline pattern: data flows through a chain of `FairTask` subclasses, persisted as ROOT TClonesArrays in a TTree.
65-
66-
### Module Overview
67-
68-
| Module | Purpose |
69-
|--------|---------|
70-
| `AtSimulationData` | MC truth data: `AtStack`, `AtMCTrack`, `AtMCPoint`, `AtVertexPropagator` |
71-
| `AtGenerators` | FairGenerator subclasses for beam/reaction/decay event generation |
72-
| `AtDetectors` | Geant4 sensitive detector implementations (AT-TPC, GADGET-II, SpecMAT, etc.) |
73-
| `AtDigitization` | Converts MC points → simulated pad signals (`AtClusterize`, `AtPulse`) |
74-
| `AtUnpack` | Unpacks raw experimental data (GET/GRAW, HDF5, ROOT formats) |
75-
| `AtData` | Core data classes: `AtRawEvent`, `AtEvent`, `AtHit`, `AtPad`, `AtTrack` |
76-
| `AtMap` | Pad mapping between electronics channels and detector geometry |
77-
| `AtParameter` | FairRuntimeDb parameter containers |
78-
| `AtReconstruction` | PSA, pattern recognition, fitting tasks |
79-
| `AtTools` | Utilities: energy loss (CATIMA), kinematics, space charge, hit sampling |
80-
| `AtAnalysis` | High-level analysis tasks and `AtRunAna` |
81-
| `AtS800` | S800 spectrograph data handling |
82-
| `AtEventDisplay` | ROOT Eve-based event display |
83-
84-
### Data Flow
85-
86-
**Simulation pipeline** (macros in `macro/Simulation/`):
87-
1. `FairPrimaryGenerator` with an `AtReactionGenerator` subclass → particle stack
88-
2. Geant4/VMC transport → `AtMCPoint` hits in sensitive volumes
89-
3. `AtClusterizeTask` → electron clusters from ionization
90-
4. `AtPulseTask` → simulated pad signals (`AtRawEvent`)
91-
92-
**Reconstruction pipeline** (macros in `macro/Unpack_*/` and `macro/Analysis/`):
93-
1. `AtUnpackTask``AtRawEvent` (raw pad traces)
94-
2. `AtFilterTask` → filtered `AtRawEvent`
95-
3. `AtPSAtask` (Pulse Shape Analysis) → `AtEvent` with `AtHit` objects
96-
4. `AtSampleConsensusTask` / `AtPRAtask``AtPatternEvent` with `AtTrack` objects
97-
5. `AtMCFitterTask` / `AtFitterTask` → fitted tracks with kinematics
98-
99-
### Key Design Patterns
100-
101-
**FairTask subclasses**: Each processing step is a `FairTask`. They retrieve input branches via `TClonesArray*` from `FairRootManager` in `Init()` and process them in `Exec()`.
102-
103-
**AtReactionGenerator**: Abstract base for all reaction generators. Subclasses implement `GenerateReaction()`. The `ReadEvent()` method is `final` and handles the beam/reaction event alternation via `AtVertexPropagator`. Generators can be chained for sequential decays using `SetSequentialDecay(true)`.
104-
105-
**AtVertexPropagator**: Singleton (`AtVertexPropagator::Instance()`) that communicates vertex, momentum, and kinematics between chained generators and downstream tasks. Alternates beam/reaction events via `EndEvent()`. Use `ResetForTesting()` in unit tests.
106-
107-
**PSA (Pulse Shape Analysis)**: `AtPSA` is the abstract base. Concrete implementations (`AtPSAMax`, `AtPSAFull`, `AtPSADeconv`, etc.) extract hits from pad traces. `AtPSAComposite` allows chaining PSA methods.
108-
109-
**Energy loss**: `AtELossModel` is the base; `AtELossCATIMA` wraps the CATIMA library (fetched automatically if not installed). Used via `AtELossManager`.
110-
111-
### Adding a New Module Library
112-
113-
Each module's `CMakeLists.txt` follows this pattern:
114-
```cmake
115-
set(LIBRARY_NAME MyModule)
116-
set(SRCS file1.cxx file2.cxx)
117-
set(DEPENDENCIES ATTPCROOT::AtData ROOT::Core ...)
118-
set(TEST_SRCS MyModuleTest.cxx)
119-
attpcroot_generate_tests(${LIBRARY_NAME}Tests SRCS ${TEST_SRCS} DEPS ${LIBRARY_NAME})
120-
generate_target_and_root_library(${LIBRARY_NAME} LINKDEF ${LIBRARY_NAME}LinkDef.h SRCS ${SRCS} DEPS_PUBLIC ${DEPENDENCIES})
121-
```
34+
## Code-Writing Rules
12235

123-
ROOT dictionary generation requires a `*LinkDef.h` file listing every class that needs ROOT reflection. Every class with `ClassDef` in its header must appear in the LinkDef.
36+
These rules apply whenever editing or adding C++ code in this repo.
12437

125-
**LinkDef streamer suffix** — the suffix after the class name controls whether ROOT generates a full I/O streamer:
38+
### LinkDef Streamer Suffixes
12639

127-
- `ClassName +;` — generates a full streamer. Use this **only** for classes that are written to a ROOT file (i.e. stored as a branch in a `TClonesArray` or `TTree`). Examples: `AtHit`, `AtEvent`, `AtRawEvent`, `AtMCPoint`.
128-
- `ClassName -!;` — registers the class for reflection (usable in interpreted macros, usable as a pointer type) but **suppresses the streamer**. Use this for every class that is never written to disk: tasks, algorithms, models, samplers, etc. Examples: `AtELossModel`, `AtSpaceChargeModel`, `AtSample` subclasses.
40+
Every class in a `*LinkDef.h` file must use the correct suffix:
12941

130-
Generating an unnecessary streamer bloats the dictionary and binary with unused I/O code, so the default should be `-!` unless disk persistence is actually required.
42+
- `ClassName +;` — generates a full I/O streamer. **Only** for classes written to a ROOT file (stored in a `TClonesArray` or `TTree` branch). Examples: `AtHit`, `AtEvent`, `AtRawEvent`, `AtMCPoint`.
43+
- `ClassName -!;` — reflection only, no streamer. Use for **everything else**: tasks, algorithms, models, samplers. Examples: `AtPSAMax`, `AtELossModel`, `AtFitterTask`.
13144

132-
**C++ vs ROOT typedefs** — use plain C++ types (`bool`, `int`, `double`, `std::string`) in all classes that are not written to a ROOT file. Only use ROOT's portability typedefs (`Bool_t`, `Int_t`, `Double_t`, etc.) in classes that are persisted to disk, where ROOT's cross-platform I/O guarantees matter. Mixing ROOT types into purely algorithmic or task classes is unnecessary overhead.
45+
Default to `-!` unless disk persistence is actually required.
13346

134-
### Unit Tests
47+
### C++ vs ROOT Typedefs
13548

136-
Tests use Google Test, placed alongside source files (e.g., `AtVertexPropagatorTest.cxx` in `AtSimulationData/`). Register them in the module's `CMakeLists.txt` via `attpcroot_generate_tests()`. Tests must not access external files or network resources.
49+
- Non-persisted classes (tasks, algorithms, models): use `bool`, `int`, `double`, `std::string`.
50+
- Persisted data classes only: use `Bool_t`, `Int_t`, `Double_t`, etc.
13751

138-
### Macros
52+
### Test Isolation
13953

140-
ROOT macros (`.C` files) in `macro/` are the primary user interface for running simulations and analyses. They are not compiled into libraries—they run interpreted by ROOT. Integration tests live in `macro/tests/`.
54+
Unit tests must not access external files or network resources. Hardcode test data inline.
14155

14256
## Contributing
14357

144-
- PRs must target the `develop` branch and apply cleanly (fast-forward, no merge commits).
145-
- Commit messages: present imperative mood, ≤72 characters summary.
146-
- All PRs are checked by `clang-format`, `clang-tidy`, and the unit test suite.
58+
- PRs target the `develop` branch; fast-forward only (no merge commits).
59+
- Commit messages: present imperative mood, ≤72 characters.
60+
- All PRs must pass `clang-format`, `clang-tidy`, and unit tests.

.github/workflows/CI-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
runs-on: ubuntu-latest
1919
container: anthoak13/attpcroot-deps
2020
steps:
21-
- uses: actions/checkout@v4
21+
- uses: actions/checkout@v6
2222

2323
- name: Configure CMake
2424
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
runs-on: ubuntu-latest
99

1010
steps:
11-
- uses: actions/checkout@v2
11+
- uses: actions/checkout@v6
1212
- name: Run clang-format
1313
uses: DoozyX/clang-format-lint-action@v0.17
1414
# These are optional (defaults displayed)

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
*.pdf
12
*.swp
23
*.root
34
*.log
@@ -57,3 +58,6 @@ macros/data
5758
.DS_Store
5859
.nfs*
5960
compiled/E20009Analysis/.NabinWorkDir/
61+
62+
.claude/plans/*
63+

AGENTS.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# AGENTS.md
2+
3+
ATTPCROOT is a ROOT/FairRoot-based C++ framework for simulation and analysis of Active Target Time Projection Chamber (AT-TPC) detector data.
4+
5+
## Documentation
6+
7+
Full developer documentation lives in `docs/`. See [docs/index.md](docs/index.md) for the full map. Quick topic links:
8+
9+
| Topic | File |
10+
|-------|------|
11+
| First-time install | [tooling/installation.md](docs/tooling/installation.md) |
12+
| Daily use (build/test) | [tooling/daily-use.md](docs/tooling/daily-use.md) |
13+
| Testing patterns | [tooling/testing.md](docs/tooling/testing.md) |
14+
| Contributor guide | [contributing/guide.md](docs/contributing/guide.md) |
15+
| Adding a new module | [contributing/new-module.md](docs/contributing/new-module.md) |
16+
| Code style | [contributing/code-style.md](docs/contributing/code-style.md) |
17+
| Module overview | [reference/modules.md](docs/reference/modules.md) |
18+
| Data model | [reference/data-model.md](docs/reference/data-model.md) |
19+
| Branch I/O contracts | [reference/branch-io-contracts.md](docs/reference/branch-io-contracts.md) |
20+
| Simulation pipeline | [subsystems/simulation-pipeline.md](docs/subsystems/simulation-pipeline.md) |
21+
| Reconstruction pipeline | [subsystems/reconstruction-pipeline.md](docs/subsystems/reconstruction-pipeline.md) |
22+
| Event generators | [subsystems/generators.md](docs/subsystems/generators.md) |
23+
| Pulse shape analysis | [subsystems/psa.md](docs/subsystems/psa.md) |
24+
| Energy loss | [subsystems/energy-loss.md](docs/subsystems/energy-loss.md) |
25+
26+
## Quick Reference: Build & Test
27+
28+
```bash
29+
source build/config.sh # load environment (do this first)
30+
cmake --build build -j10 # build everything
31+
cd build && ctest -V # run all unit tests
32+
```
33+
34+
## Code-Writing Rules
35+
36+
These rules apply whenever editing or adding C++ code in this repo.
37+
38+
### LinkDef Streamer Suffixes
39+
40+
Every class in a `*LinkDef.h` file must use the correct suffix:
41+
42+
- `ClassName +;` — generates a full I/O streamer. **Only** for classes written to a ROOT file (stored in a `TClonesArray` or `TTree` branch). Examples: `AtHit`, `AtEvent`, `AtRawEvent`, `AtMCPoint`.
43+
- `ClassName -!;` — reflection only, no streamer. Use for **everything else**: tasks, algorithms, models, samplers. Examples: `AtPSAMax`, `AtELossModel`, `AtFitterTask`.
44+
45+
Default to `-!` unless disk persistence is actually required.
46+
47+
### C++ vs ROOT Typedefs
48+
49+
- Non-persisted classes (tasks, algorithms, models): use `bool`, `int`, `double`, `std::string`.
50+
- Persisted data classes only: use `Bool_t`, `Int_t`, `Double_t`, etc.
51+
52+
### Test Isolation
53+
54+
Unit tests must not access external files or network resources. Hardcode test data inline.
55+
56+
## Contributing
57+
58+
- PRs target the `develop` branch; fast-forward only (no merge commits).
59+
- Commit messages: present imperative mood, ≤72 characters.
60+
- All PRs must pass `clang-format`, `clang-tidy`, and unit tests.

AtTools/AtELossBetheBloch.cxx

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,24 @@ void AtELossBetheBloch::BuildSpline(double E_min_MeV, double E_max_MeV, int nPoi
7878
dXdE[i] = (dedxValues[i] > 0) ? 1.0 / dedxValues[i] : 1e10;
7979

8080
fdXdE = tk::spline(energies, dXdE);
81+
82+
// Build Ω²(E) spline: Bohr range variance accumulated from 0 to E.
83+
// ω²_unit [MeV²/mm] = K · z² · (Z/A) · ρ[g/mm³] · mₑc²
84+
// (kK is in MeV cm²/mol; ×100 → MeV mm²/mol; density g/cm³ → g/mm³ = /1000; combined: /10)
85+
double z = IsElectron() ? 1.0 : fPart_q;
86+
double omega2_unit = kK * z * z * (static_cast<double>(fMat_Z) / fMat_A) * (fDensity / 10.0) * kM_e;
87+
88+
// Build spline of the integrand dΩ²/dE = 1/|dEdx|³, then integrate segment-by-segment using
89+
// Simpson's rule (exact for cubics, O(h⁴)) rather than the O(h²) trapezoidal rule.
90+
std::vector<double> integrandValues(nPoints);
91+
for (int i = 0; i < nPoints; ++i)
92+
integrandValues[i] = (dedxValues[i] > 0) ? 1.0 / (dedxValues[i] * dedxValues[i] * dedxValues[i]) : 0.0;
93+
tk::spline integrand(energies, integrandValues);
94+
95+
std::vector<double> rangeVar(nPoints, 0.0);
96+
for (int i = 1; i < nPoints; ++i)
97+
rangeVar[i] = rangeVar[i - 1] + omega2_unit * integrand.integrate(energies[i - 1], energies[i]);
98+
fRangeVariance = tk::spline(energies, rangeVar);
8199
}
82100

83101
double AtELossBetheBloch::GetdEdx_formula(double energy) const
@@ -199,23 +217,32 @@ double AtELossBetheBloch::GetEnergy(double energyIni, double distance) const
199217

200218
double AtELossBetheBloch::GetElossStraggling(double energyIni, double energyFin) const
201219
{
202-
double dx_mm = GetRange(energyIni, energyFin);
203-
if (dx_mm <= 0)
220+
if (energyIni <= energyFin)
204221
return 0;
205-
206-
// Bohr approximation: σ² = K·z²·(Z/A)·ρ·Δx[cm]·mₑc²
207-
double z = IsElectron() ? 1.0 : fPart_q;
208-
double dx_cm = dx_mm * 0.1;
209-
double sigma2 = kK * z * z * (static_cast<double>(fMat_Z) / fMat_A) * fDensity * dx_cm * kM_e;
210-
return std::sqrt(sigma2);
222+
double omega2 = GetRangeVariance(energyIni) - GetRangeVariance(energyFin);
223+
if (omega2 <= 0)
224+
return 0;
225+
return std::abs(GetdEdx(energyFin)) * std::sqrt(omega2);
211226
}
212227

213228
double AtELossBetheBloch::GetdEdxStraggling(double energyIni, double energyFin) const
214229
{
215230
double dx_mm = GetRange(energyIni, energyFin);
216231
if (dx_mm <= 0)
217232
return 0;
218-
return GetElossStraggling(energyIni, energyFin) / dx_mm;
233+
double omega2 = GetRangeVariance(energyIni) - GetRangeVariance(energyFin);
234+
if (omega2 <= 0)
235+
return 0;
236+
return std::abs(GetdEdx(energyFin)) * std::sqrt(omega2) / dx_mm;
237+
}
238+
239+
double AtELossBetheBloch::GetRangeVariance(double energy) const
240+
{
241+
if (energy <= fRangeVariance.get_x_min())
242+
return 0;
243+
if (energy >= fRangeVariance.get_x_max())
244+
return fRangeVariance(fRangeVariance.get_x_max());
245+
return fRangeVariance(energy);
219246
}
220247

221248
} // namespace AtTools

AtTools/AtELossBetheBloch.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ class AtELossBetheBloch : public AtELossModel {
2828
int fMat_A; // target mass number (g/mol)
2929
double fI_MeV; // mean excitation energy in MeV
3030

31-
tk::spline fdXdE; // spline of dx/dE vs. energy; integral cached for O(log n) GetRange
31+
tk::spline fdXdE; // spline of dx/dE vs. energy; integral cached for O(log n) GetRange
32+
tk::spline fRangeVariance; // spline of Ω²(E) [mm²] vs. energy; accumulated Bohr range variance
3233

3334
public:
3435
/**
@@ -57,6 +58,7 @@ class AtELossBetheBloch : public AtELossModel {
5758
virtual double GetEnergy(double energyIni, double distance) const override;
5859
virtual double GetElossStraggling(double energyIni, double energyFin) const override;
5960
virtual double GetdEdxStraggling(double energyIni, double energyFin) const override;
61+
virtual double GetRangeVariance(double energy) const override;
6062

6163
private:
6264
bool IsElectron() const { return std::abs(fPart_mass - kM_e) < 0.01; }

0 commit comments

Comments
 (0)