All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SimEnergyDeposit.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file lardataobj/Simulation/SimEnergyDeposit.h
3 /// \brief contains information for a single step in the detector simulation
4 ///
5 /// \authors Hans Wenzel and William Seligman
6 ////////////////////////////////////////////////////////////////////////
7 #ifndef LARDATAOBJ_SIMULATION_SIMENERGYDEPOSIT_H
8 #define LARDATAOBJ_SIMULATION_SIMENERGYDEPOSIT_H
9 
10 // LArSoft includes
11 // Define the LArSoft standard geometry types and methods.
13 
14 // C++ includes
15 #include <vector>
16 
17 
18 namespace sim
19 {
20  /**
21  * @brief Energy deposition in the active material.
22  *
23  * The detector simulation (presently LArG4, which invokes Geant4)
24  * propagates particles through the detector in intervals of "steps".
25  * In Geant4, a step is normally defined by the smallest of the distance
26  * from the current position of the particle to the point where it
27  * enters a new volume boundary, the particle undergoes some "interesting"
28  * physics event, or the range of the particle due to its energy falls
29  * below a given limit.
30  *
31  * In `LArG4`, an additional limit is applied: We force the steps to be
32  * small (typically 1/10th the wire spacing in the planes of the TPC)
33  * so we can process the energy deposited by each step into
34  * electron clusters.
35  *
36  * The SimEnergyDeposit class defines what Geant4 truth information for
37  * each step is passed to the ionization -> `sim::SimChannel` conversion,
38  * and for the optical-photon -> `sim::SimPhoton` conversion.
39  *
40  * _William Seligman, Nevis Labs, 10/12/2017_
41  */
43  {
44  public:
45 
46  // Define the types for the private members below.
47  using Length_t = float;
49 
50  // Since we're using LArSoft geometry types, the typical way to
51  // construct a SimEnergyDeposit might be:
52  // sim::SimEnergyDeposit sed(numPhotons,
53  // numElectrons,
54  // stepEnergy,
55  // { startX, startY, startZ },
56  // { endX, endY, endZ },
57  // startTime,
58  // endTime,
59  // trackID,
60  // pdgCode);
61 
62  SimEnergyDeposit(int np = 0,
63 // int nfp = 0,
64 // int nsp = 0,
65  int ne = 0,
66  double sy = 0,
67  double e = 0.,
68  geo::Point_t start = {0.,0.,0.},
69  geo::Point_t end = {0.,0.,0.},
70  double t0 = 0.,
71  double t1 = 0.,
72  int id = 0,
73  int pdg = 0,
74  int origTrackID = 0)
75  : numPhotons(np)
76 // , numFPhotons(nfp)
77 // , numSPhotons(nsp)
78  , numElectrons(ne)
79  , scintYieldRatio(sy)
80  , edep(e)
81  , startPos(start)
82  , endPos(end)
83  , startTime(t0)
84  , endTime(t1)
85  , trackID(id)
86  , pdgCode(pdg)
88  {
89  }
90 
91 
92  // Note that even if we store a value as float, we return
93  // it as double so the user doesn't have to think about
94  // precision issues.
95 
96  int NumPhotons() const { return numPhotons; }
97  int NumFPhotons() const { return round(numPhotons * scintYieldRatio); }
98  int NumSPhotons() const { return round(numPhotons * (1.0 - scintYieldRatio)); }
99  int NumElectrons() const { return numElectrons; }
100  double ScintYieldRatio() const { return scintYieldRatio;}
101  double Energy() const { return edep; }
102  geo::Point_t Start() const { return { startPos.X(), startPos.Y(), startPos.Z() }; }
103  geo::Point_t End() const { return { endPos.X(), endPos.Y(), endPos.Z() }; }
104  double Time() const { return (startTime+endTime)/2.; }
105  int TrackID() const { return trackID; }
106  int OrigTrackID() const { return origTrackID; }
107  void setTrackID(int id) { trackID = id; }
108  int PdgCode() const { return pdgCode; }
109 
110  // While it's clear how a SimEnergyDeposit will be created by its
111  // constructor, it's not clear how users will want to access its
112  // data. So give them as many different kinds of accessors as I
113  // can think of.
114  geo::Length_t StartX() const { return startPos.X(); }
115  geo::Length_t StartY() const { return startPos.Y(); }
116  geo::Length_t StartZ() const { return startPos.Z(); }
117  double StartT() const { return startTime; }
118  geo::Length_t EndX() const { return endPos.X(); }
119  geo::Length_t EndY() const { return endPos.Y(); }
120  geo::Length_t EndZ() const { return endPos.Z(); }
121  double EndT() const { return endTime; }
122 
123  // Step mid-point.
125  return {
126  ( startPos.X() + endPos.X() )/2.
127  , ( startPos.Y() + endPos.Y() )/2.
128  , ( startPos.Z() + endPos.Z() )/2.
129  };
130  }
131  geo::Length_t MidPointX() const { return ( startPos.X() + endPos.X() )/2.; }
132  geo::Length_t MidPointY() const { return ( startPos.Y() + endPos.Y() )/2.; }
133  geo::Length_t MidPointZ() const { return ( startPos.Z() + endPos.Z() )/2.; }
134  geo::Length_t X() const { return ( startPos.X() + endPos.X() )/2.; }
135  geo::Length_t Y() const { return ( startPos.Y() + endPos.Y() )/2.; }
136  geo::Length_t Z() const { return ( startPos.Z() + endPos.Z() )/2.; }
137  double T() const { return (startTime+endTime)/2.; }
138  double T0() const { return startTime; }
139  double T1() const { return endTime; }
140  double E() const { return edep; }
141 
142  // Step length. (Recall that the difference between two
143  // geo::Point_t objects is a geo::Vector_t; we get the length from
144  // spherical coordinates.
145  geo::Length_t StepLength() const { return ( endPos - startPos ).R(); }
146 
147  // Just in case someone wants to store sim::SimEnergyDeposit
148  // objects in a sorted container, define a sort function. Note
149  // that the ideal sort order is dependent of the analysis you're
150  // trying to perform; for example, if you're dealing with cosmic
151  // rays coming along the y-axis, sorting first by z may cause some
152  // tasks like insertions to take a very long time.
153 
154  bool operator<(const SimEnergyDeposit& rhs) const
155  {
156  return trackID < rhs.trackID
157  && startTime < rhs.startTime
158  && startPos.Z() < rhs.startPos.Z()
159  && startPos.Y() < rhs.startPos.Y()
160  && startPos.X() < rhs.startPos.X()
161  && edep > rhs.edep; // sort by _decreasing_ energy
162  }
163 
164  private:
165  // While the accessors above return all values in double
166  // precision, store whatever we can in single precision to save
167  // memory and disk space.
168 
169  // There are roughly 7 digits of decimal precision in a float.
170  // This will suffice for energy. A float (as opposed to a double)
171  // can hold a little more than 7 digits of decimal precision. The
172  // smallest position resolution in the simulation is about 0.1mm,
173  // or 10^-4m. With seven digits of precision, that means a float
174  // can be accurate to up to the range of 10^3m. That's why the
175  // definition of our local Point_t (see above) is based on float,
176  // while geo::Point_t is based on double.
177 
178  // If the above reasoning is wrong, just change the definition of
179  // Length_t near the top of this file. Of course, also edit these
180  // comments if you do, because you're a good and responsible
181  // programmer.
182 
183  // For time, it's possible for long-lived particles like neutrons
184  // to deposit energy after billions of ns. Chances are time cuts
185  // will take care of that, but let's make sure that any overlay studies
186  // won't suffer due to lack of precision.
187 
188  int numPhotons; ///< of scintillation photons
189 // int numFPhotons; ///< of fast scintillation photons
190 // int numSPhotons; ///< of slow scintillation photons
191  int numElectrons; ///< of ionization electrons
192  float scintYieldRatio; ///< scintillation yield of LAr
193  float edep; ///< energy deposition (MeV)
194  geo::Point_t startPos; ///< positions in (cm)
196  double startTime; ///< (ns)
197  double endTime; ///< (ns)
198  int trackID; ///< simulation track id
199  int pdgCode; ///< pdg code of particle to avoid lookup by particle type later
200  int origTrackID; ///< complementary simulation track id, kept true to G4 even for shower secondaries/tertiaries etc.
201  };
202  /*
203  // Class utility functions.
204 
205  // The format of the sim::SimEnergyDeposit output. I'm using a
206  // template for the ostream type, since LArSoft may have some
207  // special classes for its output streams.
208  template <typename Stream>
209  Stream& operator<<(Stream&& os, const sim::SimEnergyDeposit& sed)
210  {
211  // Note that the geo::Point_t type (returned by Start() and End())
212  // has an ostream operator defined for it.
213  os << "trackID " << sed.TrackID()
214  << " pdgCode=" << sed.PdgCode()
215  << " start=" << sed.Start()
216  << " t0=" << sed.T0()
217  << " end=" << sed.End()
218  << " t1=" << sed.T1() << " [cm,ns]"
219  << " E=" << sed.E() << "[GeV]"
220  << " #photons=" << sed.NumPhotons();
221  return os;
222  }
223 
224  // It can be more memory efficient to sort objects by pointers;
225  // e.g., if you've got an unsorted
226  // std::vector<sim::SimEnergyDeposit>, create a
227  // std::set<sim::SimEnergyDeposit*,sim::CompareSED> so you're not
228  // duplicating the objects in memory. The following definition
229  // covers sorting the pointers.
230  bool compareSED(const SimEnergyDeposit* const lhs, const SimEnergyDeposit* const rhs)
231  {
232  return (*lhs) < (*rhs);
233  }
234  */
235  typedef std::vector<SimEnergyDeposit> SimEnergyDepositCollection;
236 } // namespace sim
237 #endif // LARDATAOBJ_SIMULATION_SIMENERGYDEPOSIT_H
geo::Length_t StartX() const
geo::Length_t EndZ() const
geo::Length_t StepLength() const
geo::Length_t EndY() const
SimEnergyDeposit(int np=0, int ne=0, double sy=0, double e=0., geo::Point_t start={0., 0., 0.}, geo::Point_t end={0., 0., 0.}, double t0=0., double t1=0., int id=0, int pdg=0, int origTrackID=0)
var pdg
Definition: selectors.fcl:14
double Length_t
Type used for coordinates and distances. They are measured in centimeters.
Definition: geo_vectors.h:137
geo::Length_t Y() const
int numElectrons
of ionization electrons
int origTrackID
complementary simulation track id, kept true to G4 even for shower secondaries/tertiaries etc...
geo::Length_t StartY() const
double StartT() const
geo::Point_t startPos
positions in (cm)
int numPhotons
of scintillation photons
geo::Length_t Z() const
int pdgCode
pdg code of particle to avoid lookup by particle type later
geo::Length_t EndX() const
geo::Point_t Start() const
geo::Point_t End() const
Definitions of geometry vector data types.
int trackID
simulation track id
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
geo::Point_t MidPoint() const
geo::Length_t StartZ() const
geo::Length_t MidPointX() const
geo::Length_t MidPointY() const
std::vector< SimEnergyDeposit > SimEnergyDepositCollection
float scintYieldRatio
scintillation yield of LAr
bool operator<(const SimEnergyDeposit &rhs) const
geo::Length_t MidPointZ() const
Energy deposition in the active material.
do i e
double Energy() const
geo::Length_t X() const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
double ScintYieldRatio() const
float edep
energy deposition (MeV)