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  : numPhotons(np)
75 // , numFPhotons(nfp)
76 // , numSPhotons(nsp)
77  , numElectrons(ne)
78  , scintYieldRatio(sy)
79  , edep(e)
80  , startPos(start)
81  , endPos(end)
82  , startTime(t0)
83  , endTime(t1)
84  , trackID(id)
85  , pdgCode(pdg)
86  {
87  }
88 
89 
90  // Note that even if we store a value as float, we return
91  // it as double so the user doesn't have to think about
92  // precision issues.
93 
94  int NumPhotons() const { return numPhotons; }
95  int NumFPhotons() const { return round(numPhotons * scintYieldRatio); }
96  int NumSPhotons() const { return round(numPhotons * (1.0 - scintYieldRatio)); }
97  int NumElectrons() const { return numElectrons; }
98  double ScintYieldRatio() const { return scintYieldRatio;}
99  double Energy() const { return edep; }
100  geo::Point_t Start() const { return { startPos.X(), startPos.Y(), startPos.Z() }; }
101  geo::Point_t End() const { return { endPos.X(), endPos.Y(), endPos.Z() }; }
102  double Time() const { return (startTime+endTime)/2.; }
103  int TrackID() const { return trackID; }
104  int PdgCode() const { return pdgCode; }
105 
106  // While it's clear how a SimEnergyDeposit will be created by its
107  // constructor, it's not clear how users will want to access its
108  // data. So give them as many different kinds of accessors as I
109  // can think of.
110  geo::Length_t StartX() const { return startPos.X(); }
111  geo::Length_t StartY() const { return startPos.Y(); }
112  geo::Length_t StartZ() const { return startPos.Z(); }
113  double StartT() const { return startTime; }
114  geo::Length_t EndX() const { return endPos.X(); }
115  geo::Length_t EndY() const { return endPos.Y(); }
116  geo::Length_t EndZ() const { return endPos.Z(); }
117  double EndT() const { return endTime; }
118 
119  // Step mid-point.
121  return {
122  ( startPos.X() + endPos.X() )/2.
123  , ( startPos.Y() + endPos.Y() )/2.
124  , ( startPos.Z() + endPos.Z() )/2.
125  };
126  }
127  geo::Length_t MidPointX() const { return ( startPos.X() + endPos.X() )/2.; }
128  geo::Length_t MidPointY() const { return ( startPos.Y() + endPos.Y() )/2.; }
129  geo::Length_t MidPointZ() const { return ( startPos.Z() + endPos.Z() )/2.; }
130  geo::Length_t X() const { return ( startPos.X() + endPos.X() )/2.; }
131  geo::Length_t Y() const { return ( startPos.Y() + endPos.Y() )/2.; }
132  geo::Length_t Z() const { return ( startPos.Z() + endPos.Z() )/2.; }
133  double T() const { return (startTime+endTime)/2.; }
134  double T0() const { return startTime; }
135  double T1() const { return endTime; }
136  double E() const { return edep; }
137 
138  // Step length. (Recall that the difference between two
139  // geo::Point_t objects is a geo::Vector_t; we get the length from
140  // spherical coordinates.
141  geo::Length_t StepLength() const { return ( endPos - startPos ).R(); }
142 
143  // Just in case someone wants to store sim::SimEnergyDeposit
144  // objects in a sorted container, define a sort function. Note
145  // that the ideal sort order is dependent of the analysis you're
146  // trying to perform; for example, if you're dealing with cosmic
147  // rays coming along the y-axis, sorting first by z may cause some
148  // tasks like insertions to take a very long time.
149 
150  bool operator<(const SimEnergyDeposit& rhs) const
151  {
152  return trackID < rhs.trackID
153  && startTime < rhs.startTime
154  && startPos.Z() < rhs.startPos.Z()
155  && startPos.Y() < rhs.startPos.Y()
156  && startPos.X() < rhs.startPos.X()
157  && edep > rhs.edep; // sort by _decreasing_ energy
158  }
159 
160  private:
161  // While the accessors above return all values in double
162  // precision, store whatever we can in single precision to save
163  // memory and disk space.
164 
165  // There are roughly 7 digits of decimal precision in a float.
166  // This will suffice for energy. A float (as opposed to a double)
167  // can hold a little more than 7 digits of decimal precision. The
168  // smallest position resolution in the simulation is about 0.1mm,
169  // or 10^-4m. With seven digits of precision, that means a float
170  // can be accurate to up to the range of 10^3m. That's why the
171  // definition of our local Point_t (see above) is based on float,
172  // while geo::Point_t is based on double.
173 
174  // If the above reasoning is wrong, just change the definition of
175  // Length_t near the top of this file. Of course, also edit these
176  // comments if you do, because you're a good and responsible
177  // programmer.
178 
179  // For time, it's possible for long-lived particles like neutrons
180  // to deposit energy after billions of ns. Chances are time cuts
181  // will take care of that, but let's make sure that any overlay studies
182  // won't suffer due to lack of precision.
183 
184  int numPhotons; ///< of scintillation photons
185 // int numFPhotons; ///< of fast scintillation photons
186 // int numSPhotons; ///< of slow scintillation photons
187  int numElectrons; ///< of ionization electrons
188  float scintYieldRatio; ///< scintillation yield of LAr
189  float edep; ///< energy deposition (MeV)
190  geo::Point_t startPos; ///< positions in (cm)
192  double startTime; ///< (ns)
193  double endTime; ///< (ns)
194  int trackID; ///< simulation track id
195  int pdgCode; ///< pdg code of particle to avoid lookup by particle type later
196  };
197  /*
198  // Class utility functions.
199 
200  // The format of the sim::SimEnergyDeposit output. I'm using a
201  // template for the ostream type, since LArSoft may have some
202  // special classes for its output streams.
203  template <typename Stream>
204  Stream& operator<<(Stream&& os, const sim::SimEnergyDeposit& sed)
205  {
206  // Note that the geo::Point_t type (returned by Start() and End())
207  // has an ostream operator defined for it.
208  os << "trackID " << sed.TrackID()
209  << " pdgCode=" << sed.PdgCode()
210  << " start=" << sed.Start()
211  << " t0=" << sed.T0()
212  << " end=" << sed.End()
213  << " t1=" << sed.T1() << " [cm,ns]"
214  << " E=" << sed.E() << "[GeV]"
215  << " #photons=" << sed.NumPhotons();
216  return os;
217  }
218 
219  // It can be more memory efficient to sort objects by pointers;
220  // e.g., if you've got an unsorted
221  // std::vector<sim::SimEnergyDeposit>, create a
222  // std::set<sim::SimEnergyDeposit*,sim::CompareSED> so you're not
223  // duplicating the objects in memory. The following definition
224  // covers sorting the pointers.
225  bool compareSED(const SimEnergyDeposit* const lhs, const SimEnergyDeposit* const rhs)
226  {
227  return (*lhs) < (*rhs);
228  }
229  */
230  typedef std::vector<SimEnergyDeposit> SimEnergyDepositCollection;
231 } // namespace sim
232 #endif // LARDATAOBJ_SIMULATION_SIMENERGYDEPOSIT_H
geo::Length_t StartX() const
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
code to link reconstructed objects back to the MC truth information
geo::Length_t EndZ() const
geo::Length_t StepLength() const
geo::Length_t EndY() const
geo::Length_t Y() const
int numElectrons
of ionization electrons
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
const double e
int trackID
simulation track id
geo::Point_t MidPoint() const
geo::Length_t StartZ() const
Code to link reconstructed objects back to the MC truth information.
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
geo::Length_t MidPointX() const
geo::Length_t MidPointY() const
double Length_t
Type used for coordinates and distances. They are measured in centimeters.
Definition: geo_vectors.h:137
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.
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)
Definitions of geometry vector data types.
double Energy() const
geo::Length_t X() const
double ScintYieldRatio() const
float edep
energy deposition (MeV)