From 067808e5784a4020bc5f45cbe492f48de9625c38 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Sun, 15 Nov 2026 20:24:11 +0100 Subject: [PATCH] Take the TPC charge of a stopping step from the energy deposit This fixes a problem in the TPC ionisation of a step that ends below the validity of the collision model. - The collision model took beta*gamma from the momentum after the step and clamped it at 7e-3. - For a track that ranged out in the step this gave up to 3.5e4 electrons for a 1 mm step, more than its energy allows. - A finite step ending below beta*gamma 7e-3 now takes its charge from Edep / Wion. - Zero-length steps (tracking-cut kills, capture at rest) still give no charge. Co-Authored-By: Claude Opus 5.5 --- Detectors/TPC/simulation/src/Detector.cxx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Detectors/TPC/simulation/src/Detector.cxx b/Detectors/TPC/simulation/src/Detector.cxx index fcb546abb63b3..1600bc67a36af 100644 --- a/Detectors/TPC/simulation/src/Detector.cxx +++ b/Detectors/TPC/simulation/src/Detector.cxx @@ -210,6 +210,11 @@ Bool_t Detector::ProcessHits(FairVolume* vol) Int_t numberOfElectrons = 0; // I.H. - the type expected in addHit is float + // ---| Stepsize in cm and beta*gamma after the step |--- + const double stepSize = fMC->TrackStep(); + const double betaGamma = momentum.P() / fMC->TrackMass(); + constexpr double minBetaGamma = 7.e-3; // validity limit of the collision model below + // use Geant4 energy deposit directly for ionisation (Kr-83m calibration simulations) if (detParam.UseGeant4Edep) { // We have multiple collisions and add fluctuations: smear nel using @@ -229,16 +234,14 @@ Bool_t Detector::ProcessHits(FairVolume* vol) // The number of electrons is stored as a float in the HitGroup: maximum cap at // 2^24 (16777216) ==> largest integer a IEEE-754 float can represent exactly numberOfElectrons = TMath::Min(numberOfElectrons, 16777216); + } else if (betaGamma < minBetaGamma && stepSize > 0.) { + // a finite step ending below the validity limit, e.g. a track that ranged out: + // ionisation electrons from the energy deposited in this step, Nel = Edep / Wion + numberOfElectrons = static_cast(fMC->Edep() / static_cast(gasParam.Wion)); } else { - // ---| Stepsize in cm |--- - const double stepSize = fMC->TrackStep(); - - double betaGamma = momentum.P() / fMC->TrackMass(); - betaGamma = TMath::Max(betaGamma, 7.e-3); // protection against too small bg - - // ---| number of primary ionisations per cm |--- + // ---| number of primary ionisations per cm (zero-length steps give no collisions) |--- const double primaryElectronsPerCM = - gasParam.Nprim * BetheBlochAleph(static_cast(betaGamma), gasParam.BetheBlochParam[0], + gasParam.Nprim * BetheBlochAleph(static_cast(TMath::Max(betaGamma, minBetaGamma)), gasParam.BetheBlochParam[0], gasParam.BetheBlochParam[1], gasParam.BetheBlochParam[2], gasParam.BetheBlochParam[3], gasParam.BetheBlochParam[4]);