ISCalcSeparate.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: ISCalcSeparate
3 // Plugin Type: algorithm
4 // File: ISCalcSeparate.h and ISCalcSeparate.cxx
5 // Description:
6 // Interface to algorithm class for a specific calculation of ionization electrons and scintillation photons
7 // assuming there is no correlation between the two
8 // Input: 'sim::SimEnergyDeposit'
9 // Output: num of Photons and Electrons
10 // Sept.16 by Mu Wei
11 ////////////////////////////////////////////////////////////////////////
12 
15 
16 namespace {
17  constexpr double scint_yield_factor{1.}; // default
18 }
19 
20 namespace larg4 {
21  //----------------------------------------------------------------------------
23  {
24  fSCE = lar::providerFrom<spacecharge::SpaceChargeService>();
25  fLArProp = lar::providerFrom<detinfo::LArPropertiesService>();
26 
27  // the recombination coefficient is in g/(MeVcm^2), but we report
28  // energy depositions in MeV/cm, need to divide Recombk from the
29  // LArG4Parameters service by the density of the argon we got
30  // above; this is done in 'CalcIon' function below.
32  fRecombA = LArG4PropHandle->RecombA();
33  fRecombk = LArG4PropHandle->Recombk();
34  fModBoxA = LArG4PropHandle->ModBoxA();
35  fModBoxB = LArG4PropHandle->ModBoxB();
36  fUseModBoxRecomb = (bool)LArG4PropHandle->UseModBoxRecomb();
37  fGeVToElectrons = LArG4PropHandle->GeVToElectrons();
38  }
39 
40  //----------------------------------------------------------------------------
41  // fNumIonElectrons returns a value that is not corrected for life time effects
42  double
44  sim::SimEnergyDeposit const& edep)
45  {
46  float e = edep.Energy();
47  float ds = edep.StepLength();
48 
49  double recomb = 0.;
50  double dEdx = (ds <= 0.0) ? 0.0 : e / ds;
51  double EFieldStep = EFieldAtStep(detProp.Efield(), edep);
52 
53  // Guard against spurious values of dE/dx. Note: assumes density of LAr
54  if (dEdx < 1.) { dEdx = 1.; }
55 
56  if (fUseModBoxRecomb) {
57  if (ds > 0) {
58  double const scaled_modboxb = fModBoxB / detProp.Density(detProp.Temperature());
59  double const Xi = scaled_modboxb * dEdx / EFieldStep;
60  recomb = log(fModBoxA + Xi) / Xi;
61  }
62  else {
63  recomb = 0;
64  }
65  }
66  else {
67  double const scaled_recombk = fRecombk / detProp.Density(detProp.Temperature());
68  recomb = fRecombA / (1. + dEdx * scaled_recombk / EFieldStep);
69  }
70 
71  // 1.e-3 converts fEnergyDeposit to GeV
72  auto const numIonElectrons = fGeVToElectrons * 1.e-3 * e * recomb;
73 
74  MF_LOG_DEBUG("ISCalcSeparate")
75  << " Electrons produced for " << edep.Energy() << " MeV deposited with " << recomb
76  << " recombination: " << numIonElectrons << std::endl;
77  return numIonElectrons;
78  }
79 
80  //----------------------------------------------------------------------------
81  std::pair<double, double>
83  {
84  float const e = edep.Energy();
85  int const pdg = edep.PdgCode();
86 
87  double numScintPhotons{};
88  double scintYield = fLArProp->ScintYield(true);
90  MF_LOG_DEBUG("ISCalcSeparate") << "scintillating by particle type";
91 
92  switch (pdg) {
93  case 2212: scintYield = fLArProp->ProtonScintYield(true); break;
94  case 13:
95  case -13: scintYield = fLArProp->MuonScintYield(true); break;
96  case 211:
97  case -211: scintYield = fLArProp->PionScintYield(true); break;
98  case 321:
99  case -321: scintYield = fLArProp->KaonScintYield(true); break;
100  case 1000020040: scintYield = fLArProp->AlphaScintYield(true); break;
101  case 11:
102  case -11:
103  case 22: scintYield = fLArProp->ElectronScintYield(true); break;
104  default: scintYield = fLArProp->ElectronScintYield(true);
105  }
106 
107  numScintPhotons = scintYield * e;
108  }
109  else {
110  numScintPhotons = scint_yield_factor * scintYield * e;
111  }
112 
113  return {numScintPhotons, GetScintYieldRatio(edep)};
114  }
115 
116  //----------------------------------------------------------------------------
117  ISCalcData
119  sim::SimEnergyDeposit const& edep)
120  {
121  auto const numElectrons = CalcIon(detProp, edep);
122  auto const [numPhotons, scintYieldRatio] = CalcScint(edep);
123  return {edep.Energy(), numElectrons, numPhotons, scintYieldRatio};
124  }
125  //----------------------------------------------------------------------------
126  double
128  {
129  if (not fSCE->EnableSimEfieldSCE()) { return efield; }
130 
131  auto const eFieldOffsets = fSCE->GetEfieldOffsets(edep.MidPoint());
132  return std::hypot(
133  efield + efield * eFieldOffsets.X(), efield * eFieldOffsets.Y(), efield * eFieldOffsets.Z());
134  }
135  //----------------------------------------------------------------------------
136  double
138  {
139  if (!fLArProp->ScintByParticleType()) { return fLArProp->ScintYieldRatio(); }
140  switch (edep.PdgCode()) {
141  case 2212: return fLArProp->ProtonScintYieldRatio();
142  case 13:
143  case -13: return fLArProp->MuonScintYieldRatio();
144  case 211:
145  case -211: return fLArProp->PionScintYieldRatio();
146  case 321:
147  case -321: return fLArProp->KaonScintYieldRatio();
148  case 1000020040: return fLArProp->AlphaScintYieldRatio();
149  case 11:
150  case -11:
151  case 22: return fLArProp->ElectronScintYieldRatio();
152  default: return fLArProp->ElectronScintYieldRatio();
153  }
154  }
155 
156 } // namespace
virtual bool EnableSimEfieldSCE() const =0
virtual double ElectronScintYieldRatio() const =0
const detinfo::LArProperties * fLArProp
virtual double ScintYieldRatio() const =0
virtual double AlphaScintYield(bool prescale=false) const =0
geo::Length_t StepLength() const
std::pair< double, double > CalcScint(sim::SimEnergyDeposit const &edep)
virtual double AlphaScintYieldRatio() const =0
double Temperature() const
In kelvin.
double fModBoxA
from LArG4Parameters service
Geant4 interface.
ISCalcData CalcIonAndScint(detinfo::DetectorPropertiesData const &detProp, sim::SimEnergyDeposit const &edep) override
double fRecombk
from LArG4Parameters service
virtual double ProtonScintYieldRatio() const =0
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
double Efield(unsigned int planegap=0) const
kV/cm
virtual double ProtonScintYield(bool prescale=false) const =0
virtual double PionScintYieldRatio() const =0
double CalcIon(detinfo::DetectorPropertiesData const &detProp, sim::SimEnergyDeposit const &edep)
double dEdx(float dqdx, float Efield)
Definition: doAna.cpp:21
const double e
double fRecombA
from LArG4Parameters service
virtual double ElectronScintYield(bool prescale=false) const =0
double GetScintYieldRatio(sim::SimEnergyDeposit const &edep)
geo::Point_t MidPoint() const
double Density(double temperature=0.) const
Returns argon density at a given temperature.
virtual double PionScintYield(bool prescale=false) const =0
virtual geo::Vector_t GetEfieldOffsets(geo::Point_t const &point) const =0
double EFieldAtStep(double efield, sim::SimEnergyDeposit const &edep) override
const spacecharge::SpaceCharge * fSCE
virtual double MuonScintYield(bool prescale=false) const =0
virtual double KaonScintYield(bool prescale=false) const =0
virtual double ScintYield(bool prescale=false) const =0
Energy deposition in the active material.
virtual double MuonScintYieldRatio() const =0
#define MF_LOG_DEBUG(id)
double fGeVToElectrons
from LArG4Parameters service
double fModBoxB
from LArG4Parameters service
double Energy() const
virtual double KaonScintYieldRatio() const =0
virtual bool ScintByParticleType() const =0
int bool
Definition: qglobal.h:345
QTextStream & endl(QTextStream &s)
bool fUseModBoxRecomb
from LArG4Parameters service