ElectronDriftStandardAlg.cxx
Go to the documentation of this file.
1 //
2 // ElectronDriftStandardAlg.cpp
3 // garsoft-mrb
4 //
5 // Created by Brian Rebel on 11/18/16.
6 // Copyright © 2016 Brian Rebel. All rights reserved.
7 //
9 
10 #include "CLHEP/Random/RandGauss.h"
11 
14 #include "DetectorInfo/DetectorProperties.h"
16 
17 namespace gar {
18  namespace rosim {
19 
20  //--------------------------------------------------------------------------
21  ElectronDriftStandardAlg::ElectronDriftStandardAlg(CLHEP::HepRandomEngine & engine,
22  fhicl::ParameterSet const& pset)
23  : ElectronDriftAlg(engine, pset)
24  {
25  fElectronsPerCluster = pset.get<int>("ElectronsPerCluster");
26  fMinClusters = pset.get<size_t>("MinClusters");
27 
28  // get service providers
29  fGeo = gar::providerFrom<geo::GeometryGAr>();
30  fTime = gar::providerFrom<detinfo::DetectorClocksServiceGAr>();
31  fClock = fTime->TPCClock();
32 
33  }
34 
35  //------------------------------------------------------------------------
37  {
38  }
39 
40  //--------------------------------------------------------------------------
43  {
44  // Reset the Ionization and Scintillation calculator for this step
46 
47  // figure out how many electrons were ionized in the step
48  // if none, just return the empty vector
50 
51  if (electrons <= 0) return;
52 
53  // We need a random number thrower for the diffusion, etc
54  CLHEP::RandGauss GaussRand(fEngine);
55 
56  double g4time = dep.Time();
57 
58  // the XYZ position of the midpoint has to be drifted to the readout,
59  // use the diffusion coefficients to decide where the electrons end up
60  float xyz[3] = {dep.X(),
61  dep.Y(),
62  dep.Z()};
63 
64  MF_LOG_DEBUG("ElectronDriftStandardAlg::DriftElectronsToReadout") << "energy deposition: "
65  << dep.X() << " " << dep.Y() << " " << dep.Z() << std::endl;
66 
67  // The geometry has x = TPCXCent() at the cathode plane. Compute the drift time for a two-drift-volume
68  // TPC. If we only have one drift volume, need to get that information here.
69 
70  double driftD = std::abs(std::abs(xyz[0] - fGeo->TPCXCent()) - fGeo->TPCLength()/2.0); // assume cathode is at x=TPXCent
71  if (fGeo->TPCNumDriftVols() == 1)
72  {
73  driftD = std::max(0.0, fGeo->TPCLength()/2.0 - (xyz[0] - fGeo->TPCXCent()));
74  }
75  double driftT = driftD * fInverseVelocity; // in cm
76  double sqrtDriftD = std::sqrt(driftD);
77  double lifetimeCorr = std::exp(driftT / fLifetimeCorrection);
78 
79  // how many electrons do we expect to make it to the readout?
80  float nElectrons = electrons * lifetimeCorr;
81  size_t nClusters = (size_t)std::ceil(nElectrons / fElectronsPerCluster);
82  nClusters = std::min( (size_t) std::ceil(nElectrons),std::max(nClusters,fMinClusters));
83  int ourelectronspercluster = nearbyint(nElectrons/nClusters);
84 
85  // drift them in sets. The X(Y)(Z)Diff vectors contain the additional
86  // distance to add to the step midpoint to account for diffusion.
87  std::vector<double> XDiff(nClusters, 0.);
88  std::vector<double> YDiff(nClusters, 0.);
89  std::vector<double> ZDiff(nClusters, 0.);
90  std::vector<double> TDiff(nClusters, 0.);
91  std::vector<int > nElec(nClusters, ourelectronspercluster);
92 
93  // the last cluster may have fewer electrons than the configured amount
94  nElec.back() = nearbyint(nElectrons - (nClusters - 1) * ourelectronspercluster);
95 
96  double longDiffSigma = sqrtDriftD * fLongDiffConst;
97  double transDiffSigma = sqrtDriftD * fTransDiffConst;
98 
99  GaussRand.fireArray(nClusters, &XDiff[0], 0., longDiffSigma);
100  GaussRand.fireArray(nClusters, &YDiff[0], 0., transDiffSigma);
101  GaussRand.fireArray(nClusters, &ZDiff[0], 0., transDiffSigma);
102 
103  // set the times and the positions of each cluster
104  for(size_t c = 0; c < nClusters; ++c){
105  TDiff[c] = g4time + driftT + XDiff[c] * fInverseVelocity;
106  XDiff[c] = xyz[0];
107  YDiff[c] += xyz[1];
108  ZDiff[c] += xyz[2];
109 
110  MF_LOG_DEBUG("ElectronDriftStandardAlg::DriftElectronsToReadout")
111  << "g4 time: "
112  << g4time
113  << " drift time "
114  << driftT
115  << " diffusion x:"
116  << XDiff[c]
117  << " y "
118  << YDiff[c]
119  << " z "
120  << ZDiff[c]
121  << " t "
122  << TDiff[c]
123  << " tick period "
124  << fTime->TPCClock().TickPeriod();
125 
126  }
127 
128  // reset the ElectronDriftInfo object with this information
129  driftInfo.Reset(XDiff, YDiff, ZDiff, TDiff, nElec);
130 
131  return;
132  }
133 
134  //--------------------------------------------------------------------------
135 
136  }
137 }
ElectronDriftStandardAlg(CLHEP::HepRandomEngine &engine, fhicl::ParameterSet const &pset)
double fInverseVelocity
stored for computational convenience
void Reset(std::vector< double > &xPos, std::vector< double > &yPos, std::vector< double > &zPos, std::vector< double > &time, std::vector< int > &size)
int TPCNumDriftVols() const
Returns number of TPC drift volumes.
Definition: GeometryCore.h:771
void Reset(const gar::sdp::EnergyDeposit *dep)
float const & Z() const
Definition: EnergyDeposit.h:45
float const & Y() const
Definition: EnergyDeposit.h:44
double fLongDiffConst
stored for computational convenience in sqrt(cm)
float TPCXCent() const
Returns the X location of the center of the TPC in cm.
Definition: GeometryCore.h:778
int fElectronsPerCluster
Number of electrons to drift in a cluster.
float const & Time() const
Definition: EnergyDeposit.h:41
gar::detinfo::ElecClock fClock
electronics clock
double TickPeriod() const
A single tick period in nano-second, frequency is in MHz.
Definition: ElecClock.h:125
T abs(T value)
CLHEP::HepRandomEngine & fEngine
random number engine
const gar::detinfo::DetectorClocks * fTime
electronics clock
T get(std::string const &key) const
Definition: ParameterSet.h:271
double fLifetimeCorrection
electron lifetime correction in negative ms
static int max(int a, int b)
static IonizationAndScintillation * Instance()
size_t fMinClusters
Minimum number of clusters for diffusion integral.
General GArSoft Utilities.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
double fTransDiffConst
stored for computational convenience in sqrt(cm)
float const & X() const
Definition: EnergyDeposit.h:43
#define MF_LOG_DEBUG(id)
virtual const ElecClock & TPCClock() const =0
Borrow a const TPC clock with time set to Trigger time [ns].
float TPCLength() const
Returns the length of the TPC (x direction)
Definition: GeometryCore.h:763
const gar::geo::GeometryCore * fGeo
Geometry.
QTextStream & endl(QTextStream &s)
void DriftElectronsToReadout(gar::sdp::EnergyDeposit const &dep, gar::rosim::ElectronDriftInfo &driftInfo)