@@ -193,41 +193,52 @@ Bool_t Detector::ProcessHits(FairVolume* vol)
193193 Int_t numberOfElectrons = 0 ;
194194 // I.H. - the type expected in addHit is short
195195
196- // ---| Stepsize in cm |---
197- const double stepSize = fMC ->TrackStep ();
198-
199- double betaGamma = momentum.P () / fMC ->TrackMass ();
200- betaGamma = TMath::Max (betaGamma, 7 .e -3 ); // protection against too small bg
201-
202- // ---| number of primary ionisations per cm |---
203- const double primaryElectronsPerCM =
204- gasParam.Nprim * BetheBlochAleph (static_cast <float >(betaGamma), gasParam.BetheBlochParam [0 ],
205- gasParam.BetheBlochParam [1 ], gasParam.BetheBlochParam [2 ],
206- gasParam.BetheBlochParam [3 ], gasParam.BetheBlochParam [4 ]);
207-
208- // ---| mean number of collisions and random for this event |---
209- const double meanNcoll = stepSize * trackCharge * trackCharge * primaryElectronsPerCM;
210- const int nColl = static_cast <int >(fMC ->GetRandom ()->Poisson (meanNcoll));
211-
212- // Variables needed to generate random powerlaw distributed energy loss
213- const double alpha_p1 = 1 . - gasParam.Exp ; // NA49/G3 value
214- const double oneOverAlpha_p1 = 1 . / alpha_p1;
215- const double eMin = gasParam.Ipot ;
216- const double eMax = gasParam.Eend ;
217- const double kMin = TMath::Power (eMin, alpha_p1);
218- const double kMax = TMath::Power (eMax, alpha_p1);
219- const double wIon = gasParam.Wion ;
220-
221- for (Int_t n = 0 ; n < nColl; n++) {
222- // Use GEANT3 / NA49 expression:
223- // P(eDep) ~ k * edep^-gasParam.getExp()
224- // eMin(~I) < eDep < eMax(300 electrons)
225- // k fixed so that Int_Emin^EMax P(Edep) = 1.
226- const double rndm = fMC ->GetRandom ()->Rndm ();
227- const double eDep = TMath::Power ((kMax - kMin ) * rndm + kMin , oneOverAlpha_p1);
228- int nel_step = static_cast <int >(((eDep - eMin) / wIon) + 1 );
229- nel_step = TMath::Min (nel_step, 300 ); // 300 electrons corresponds to 10 keV
230- numberOfElectrons += nel_step;
196+ // use Geant4 energy deposit directly for ionisation (Kr-83m calibration simulations)
197+ if (detParam.UseGeant4Edep ) {
198+ // We have multiple collisions and add fluctuations: smear nel using
199+ // gamma distr with mean = meanIon and variance = meanIon*FanoFactorG4.
200+ // These parameters were tuned for GEANT4.
201+ const double meanIon = fMC ->Edep () / (gasParam.Wion * gasParam.ScaleFactorG4 );
202+ if (meanIon > 0 .) {
203+ numberOfElectrons = static_cast <int >(gasParam.FanoFactorG4 * Gamma (meanIon / gasParam.FanoFactorG4 ));
204+ }
205+ } else {
206+ // ---| Stepsize in cm |---
207+ const double stepSize = fMC ->TrackStep ();
208+
209+ double betaGamma = momentum.P () / fMC ->TrackMass ();
210+ betaGamma = TMath::Max (betaGamma, 7 .e -3 ); // protection against too small bg
211+
212+ // ---| number of primary ionisations per cm |---
213+ const double primaryElectronsPerCM =
214+ gasParam.Nprim * BetheBlochAleph (static_cast <float >(betaGamma), gasParam.BetheBlochParam [0 ],
215+ gasParam.BetheBlochParam [1 ], gasParam.BetheBlochParam [2 ],
216+ gasParam.BetheBlochParam [3 ], gasParam.BetheBlochParam [4 ]);
217+
218+ // ---| mean number of collisions and random for this event |---
219+ const double meanNcoll = stepSize * trackCharge * trackCharge * primaryElectronsPerCM;
220+ const int nColl = static_cast <int >(fMC ->GetRandom ()->Poisson (meanNcoll));
221+
222+ // Variables needed to generate random powerlaw distributed energy loss
223+ const double alpha_p1 = 1 . - gasParam.Exp ; // NA49/G3 value
224+ const double oneOverAlpha_p1 = 1 . / alpha_p1;
225+ const double eMin = gasParam.Ipot ;
226+ const double eMax = gasParam.Eend ;
227+ const double kMin = TMath::Power (eMin, alpha_p1);
228+ const double kMax = TMath::Power (eMax, alpha_p1);
229+ const double wIon = gasParam.Wion ;
230+
231+ for (Int_t n = 0 ; n < nColl; n++) {
232+ // Use GEANT3 / NA49 expression:
233+ // P(eDep) ~ k * edep^-gasParam.getExp()
234+ // eMin(~I) < eDep < eMax(300 electrons)
235+ // k fixed so that Int_Emin^EMax P(Edep) = 1.
236+ const double rndm = fMC ->GetRandom ()->Rndm ();
237+ const double eDep = TMath::Power ((kMax - kMin ) * rndm + kMin , oneOverAlpha_p1);
238+ int nel_step = static_cast <int >(((eDep - eMin) / wIon) + 1 );
239+ nel_step = TMath::Min (nel_step, 300 ); // 300 electrons corresponds to 10 keV
240+ numberOfElectrons += nel_step;
241+ }
231242 }
232243
233244 // LOG(info) << "tpc::AddHit" << FairLogger::endl << "Eloss: "
@@ -3240,6 +3251,23 @@ std::string Detector::getHitBranchNames(int probe) const
32403251 return std::string ();
32413252}
32423253
3254+ void Detector::SetSpecialPhysicsCuts ()
3255+ {
3256+ // lower energy threshold to track low-energy electrons for Kr-83m calibration
3257+ auto const & detParam = ParameterDetector::Instance ();
3258+ LOG (info) << " TPC SetSpecialPhysicsCuts: UseGeant4Edep=" << detParam.UseGeant4Edep ;
3259+ if (detParam.UseGeant4Edep ) {
3260+ auto & matmgr = o2::base::MaterialManager::Instance ();
3261+ for (int med : {(int )kDriftGas1 , (int )kDriftGas2 , (int )kCO2 }) {
3262+ matmgr.SpecialCut (GetName (), med, o2::base::ECut::kCUTELE , 1e-6f );
3263+ matmgr.SpecialCut (GetName (), med, o2::base::ECut::kCUTGAM , 1e-6f );
3264+ matmgr.SpecialCut (GetName (), med, o2::base::ECut::kDCUTE , 1e-6f );
3265+ matmgr.SpecialCut (GetName (), med, o2::base::ECut::kBCUTE , 1e-6f );
3266+ }
3267+ }
3268+ o2::base::Detector::SetSpecialPhysicsCuts ();
3269+ }
3270+
32433271ClassImp (o2::tpc::Detector);
32443272
32453273// Define Factory method for calling from the outside
0 commit comments