SimChannel.h
Go to the documentation of this file.
1 /**
2  * @file SimChannel.h
3  * @brief object containing MC truth information necessary for making
4  * RawDigits and doing back tracking
5  * @author seligman@nevis.columbia.edu
6  * @see SimChannel.cxx
7  *
8  * This class uses only LArSoft libraries that are header only.
9  */
10 
11 #ifndef LARDATAOBJ_SIMULATION_SIMCHANNEL_H
12 #define LARDATAOBJ_SIMULATION_SIMCHANNEL_H
13 
14 // LArSoftObj libraries
15 #include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
16 
17 // C/C++ standard libraries
18 #include <string>
19 #include <vector>
20 #include <utility> // std::pair
21 
22 namespace sim {
23 
24  /// Ionization energy from a Geant4 track
25  struct TrackIDE{
26  int trackID; ///< Geant4 supplied trackID
27  float energyFrac; ///< fraction of hit energy from the particle with this trackID
28  float energy; ///< energy from the particle with this trackID [MeV]
29  float numElectrons; ///< number of electrons from the particle detected on the wires
30 
31  TrackIDE() {}
32 
33 
34  TrackIDE(int id, float ef, float e, float ne ) : trackID(id), energyFrac(ef), energy (e), numElectrons (ne) {}
35 
36 
37  };
38 
39 
40  /**
41  * @brief Ionization at a point of the TPC sensitive volume
42  *
43  * This class stores information about the ionization from the simulation
44  * of a small step of a track through the TPC active volume.
45  *
46  * Ionization information consists of both energy and number of electrons.
47  * It is of paramount importance to understand what each field stores:
48  *
49  * - position: where the ionization occurred (from Geant4 simulation)
50  * - track ID: Geant4 track ID of the ionizing particle
51  * - energy: amount of energy released by ionization (from Geant4 simulation)
52  * - electrons: amount of electrons reaching the readout channel
53  *
54  * Note the different definition of the electrons respect to the rest:
55  * it describes the electrons at the anode _after_ the drifting occurred,
56  * while all the other quantities can be related to the moment the ionization
57  * happened.
58  *
59  * The number of electrons typically includes inefficiencies and physics
60  * effects that reduce and spread the electrons. In the simulation,
61  * this yields a fractional number of electrons.
62  *
63  * Each IDE is also typically associated with a time (TDC) count, that is
64  * the time at which the ionized electrons reached the readout channel, in
65  * electronic ticks, as opposed as the time when ionization occurred.
66  * The latter is not stored.
67  *
68  * At the time of writing this documentation (LArSoft 6.4.0), IDEs are
69  * computed in larg4::LArVoxelReadout.
70  * The energy and track ID come directly from Geant4 simulation.
71  * The position is the mid point of the Geant4 step that produced ionization.
72  * The electrons are
73  *
74  * 1. converted from that same energy (using a fundamental conversion factor
75  * stored in `larcoreobj/SimpleTypesAndConstants/PhysicalConstants.h`)
76  * 2. applied recombination effect by larg4::IonizationAndScintillation::Reset()
77  * 3. applied attenuation and diffusion in
78  * larg4::LArVoxelReadout::DriftIonizationElectrons()
79  *
80  * The latter also assembles the sim::IDE objects to be stored into
81  * sim::SimChannel.
82  *
83  */
84  struct IDE{
85 
86  /// Type of track ID (the value comes from Geant4)
87  typedef int TrackID_t;
88 
89  /// Default constructor (sets "bogus" values)
90  IDE();
91 
92 
93  /// Constructor: copies an IDE, and applies the specified offset to track ID
94  IDE(IDE const& ide, int offset);
95 
96  /// Constructor: sets all data members
97  IDE(TrackID_t tid,
98  float nel,
99  float e,
100  float xpos,
101  float ypos,
102  float zpos)
103  : trackID (tid)
104  , numElectrons(nel)
105  , energy (e)
106  , x (xpos)
107  , y (ypos)
108  , z (zpos)
109  {}
110 
111 
112  TrackID_t trackID; ///< Geant4 supplied track ID
113  float numElectrons; ///< number of electrons at the readout for this track ID and time
114  float energy; ///< energy deposited by ionization by this track ID and time [MeV]
115  float x; ///< x position of ionization [cm]
116  float y; ///< y position of ionization [cm]
117  float z; ///< z position of ionization [cm]
118  }; // struct IDE
119 
120 
121  /// List of energy deposits at the same time (on this channel)
122  typedef std::pair<unsigned short, std::vector<sim::IDE> > TDCIDE;
123 
124  /**
125  * @brief Energy deposited on a readout channel by simulated tracks
126  *
127  * This class stores the list of all energies deposited on a readout channel.
128  * The number of electrons is stored as well.
129  *
130  * The information is organized by time: it is divided by TDC ticks, and
131  * each TDC tick where some energy was deposited appears in a separate entry,
132  * while the quiet TDC ticks are omitted.
133  * For each TDC, the information is stored as a list of energy deposits;
134  * each deposit comes from a single Geant4 track and stores the location where
135  * the ionization happened according to the simulation (see `sim::IDE` class).
136  *
137  * Note that there can be multiple energy deposit records (that is `sim::IDE`)
138  * for a single track in a single TDC tick.
139  */
141  {
142  public:
143  /// Type for TDC tick used in the internal representation
144  typedef TDCIDE::first_type StoredTDC_t;
145 
146  /// Type of list of energy deposits for each TDC with signal
147  typedef std::vector<TDCIDE> TDCIDEs_t;
148 
149  private:
150  raw::ChannelID_t fChannel; ///< readout channel where electrons are collected
151  TDCIDEs_t fTDCIDEs; ///< list of energy deposits for each TDC with signal
152 
153 
154  public:
155 
156  // Default constructor
157  SimChannel();
158 
159  /// Type for TDC tick used in the interface
160  /// (different type than raw::TDCtick_t! and from internal representation!
161  /// but same meaning!)
162  typedef unsigned int TDC_t;
163 
164  /// Type of track ID (the value comes from Geant4)
166 
167 
168  /// Constructor: immediately sets the channel number
170 
171  /**
172  * @brief Add ionization electrons and energy to this channel
173  * @param trackID ID of simulated track depositing this energy (from Geant4)
174  * @param tdc TDC tick when this deposit was collected
175  * @param numberElectrons electrons created at this point by this track
176  * @param xyz coordinates of original location of ionization (3D array) [cm]
177  * @param energy energy deposited at this point by this track [MeV]
178  *
179  * The number of electrons can be fractional because of simulated
180  * efficiency and physics effects.
181  */
182  void AddIonizationElectrons(TrackID_t trackID,
183  TDC_t tdc,
184  double numberElectrons,
185  double const* xyz,
186  double energy);
187 
188  /// Returns the readout channel this object describes
189  raw::ChannelID_t Channel() const;
190 
191  /**
192  * @brief Return all the recorded energy deposition within a time interval
193  * @param startTDC TDC tick opening the time window
194  * @param endTDC TDC tick closing the time window (included in the interval)
195  * @return a collection of energy deposit information from all tracks
196  *
197  * This method returns the energy deposited on this channel by each track
198  * ID active in the specified TDC time interval.
199  *
200  * Each entry pertains a single track ID. For each entry, all energy
201  * deposit information is merged into a single record. It includes:
202  * * energy and number of electrons, as the integral in the time interval
203  * * position, as average weighted by the number of electrons
204  * * the ID of the track depositing this energy
205  *
206  * Entries are sorted by track ID number.
207  */
208  std::vector<sim::IDE> TrackIDsAndEnergies(TDC_t startTDC,
209  TDC_t endTDC) const;
210 
211  /**
212  * @brief Returns all the deposited energy information as stored
213  * @return all the deposited energy information as stored in the object
214  *
215  * The returned list is organized in pairs. Each pair contains all
216  * ionization information in a single TDC tick (collection of `sim::IDE`),
217  * and the number of that tick. The information is sorted by increasing TDC
218  * tick.
219  *
220  * See the class description for the details of the ionization information
221  * content.
222  */
223  TDCIDEs_t const& TDCIDEMap() const;
224 
225 
226  /// Returns the total number of ionization electrons on this channel in the specified TDC
227  double Charge(TDC_t tdc) const;
228 
229  /// Returns the total energy on this channel in the specified TDC [MeV]
230  double Energy(TDC_t tdc) const;
231 
232  /**
233  * @brief Returns energies collected for each track within a time interval
234  * @param startTDC TDC tick opening the time window
235  * @param endTDC TDC tick closing the time window (included in the interval)
236  * @return a collection of energy and fraction from each track in interval
237  * @see TrackIDsAndEnergies()
238  *
239  * This method returns the energy deposited on this channel by each track
240  * ID active in the specified TDC time interval.
241  *
242  * Each entry pertains a single track ID. For each entry, all energy
243  * deposit information is merged into a single record. It includes:
244  * * energy of the track, as the integral in the time interval [MeV]
245  * * energy fraction respect to the total (see below)
246  * * the ID of the track depositing this energy
247  *
248  * The energy fraction is the energy deposited by the track on this channel
249  * in the specified time interval, divided by the total of the energy
250  * deposited by all tracks on this channel in that same time interval.
251  *
252  * Entries are sorted by track ID number.
253  */
254  std::vector<sim::TrackIDE> TrackIDEs(TDC_t startTDC,
255  TDC_t endTDC) const;
256 
257  /// Comparison: sorts by channel ID
258  bool operator< (const SimChannel& other) const;
259 
260  /// Comparison: true if SimChannels have the same channel ID
261  bool operator== (const SimChannel& other) const;
262 
263  /**
264  * @brief Merges the deposits from another channel into this one
265  * @param channel the sim::SimChannel holding information to be merged
266  * @param offset track ID offset for the merge
267  * @return range of the IDs of the added tracks
268  *
269  * The information from the specified simulated channel is added to the
270  * current one.
271  * This is achieved by appending the energy deposit information (`sim::IDE`)
272  * at each TDC tick from the merged channel to the list of existing energy
273  * deposits for that TDC tick.
274  *
275  * In addition, the track IDs of the merged channel are added an offset,
276  * so that they can be distinguished from the existing ones.
277  * This is useful when simulating tracks with multiple Geant4 runs. Geant4
278  * will reuse track IDs on each run, and using the highest number of track
279  * ID from one run as the offset for the next avoids track ID collisions.
280  * Note however that this function does not perform any collision check, and
281  * it is caller's duty to ensure that the offset is properly large.
282  * The return value is a pair including the lowest and the largest track IDs
283  * added to this channel, equivalent to the lowest and the highest track IDs
284  * present in the merged channel, both augmented by the applied offset.
285  *
286  * The channel number of the merged channel is ignored.
287  */
288  std::pair<TrackID_t,TrackID_t> MergeSimChannel
289  (const SimChannel& channel, int offset);
290 
291 
292  /**
293  * @brief Dumps the full content of the SimChannel into a stream
294  * @tparam Stream an ostream-like stream object
295  * @param out the stream to send the information into
296  * @param indent indentation of the lines (default: none)
297  * @param first_indent indentation for the first line (default: as `indent`)
298  */
299  template <typename Stream>
300  void Dump(Stream&& out, std::string indent, std::string first_indent) const;
301 
302  /// Documentation at `Dump(Stream&&, std::string, std::string) const`.
303  template <typename Stream>
304  void Dump(Stream&& out, std::string indent = "") const
305  { Dump(std::forward<Stream>(out), indent, indent); }
306 
307 
308  private:
309  /// Comparison functor, sorts by increasing TDCtick value
310  struct CompareByTDC;
311 
312  /// Return the iterator to the first TDCIDE not earlier than tdc
313  TDCIDEs_t::iterator findClosestTDCIDE(StoredTDC_t tdc);
314 
315  /// Return the (constant) iterator to the first TDCIDE not earlier than tdc
316  TDCIDEs_t::const_iterator findClosestTDCIDE
317  (StoredTDC_t tdc) const;
318  /// @}
319 
320 
321  };
322 
323 } // namespace sim
324 
325 
326 inline bool sim::SimChannel::operator< (const sim::SimChannel& other) const { return fChannel < other.Channel(); }
327 inline bool sim::SimChannel::operator== (const sim::SimChannel& other) const { return fChannel == other.Channel(); }
328 inline sim::SimChannel::TDCIDEs_t const& sim::SimChannel::TDCIDEMap() const { return fTDCIDEs; }
329 inline raw::ChannelID_t sim::SimChannel::Channel() const { return fChannel; }
330 
331 
332 // -----------------------------------------------------------------------------
333 // --- template implementation
334 // ---
335 template <class Stream>
337  (Stream&& out, std::string indent, std::string first_indent) const
338 {
339  out << first_indent << "channel #" << Channel() << " read " << fTDCIDEs.size()
340  << " TDCs:\n";
341  double channel_energy = 0., channel_charge = 0.;
342  for (const auto& TDCinfo: fTDCIDEs) {
343  auto const tdc = TDCinfo.first;
344  out << indent << " TDC #" << tdc
345  << " with " << TDCinfo.second.size() << " IDEs\n";
346  double tdc_energy = 0., tdc_charge = 0.;
347  for (const sim::IDE& ide: TDCinfo.second) {
348  out << indent
349  << " (" << ide.x << ", " << ide.y << ", " << ide.z << ") "
350  << ide.numElectrons << " electrons, " << ide.energy << " MeV (trkID="
351  << ide.trackID << ")\n";
352  tdc_energy += ide.energy;
353  tdc_charge += ide.numElectrons;
354  } // for IDEs
355  out << indent << " => TDC #" << tdc << " CH #" << Channel()
356  << " collected " << tdc_charge << " electrons and " << tdc_energy
357  << " MeV\n";
358  channel_energy += tdc_energy;
359  channel_charge += tdc_charge;
360  } // for TDCs
361  out << indent << " => channel #" << Channel() << " collected "
362  << channel_charge << " electrons and " << channel_energy << " MeV\n";
363 } // sim::SimChannel::Dump<>()
364 
365 
366 #endif // LARDATAOBJ_SIMULATION_SIMCHANNEL_H
367 
368 ////////////////////////////////////////////////////////////////////////
TrackID_t trackID
Geant4 supplied track ID.
Definition: SimChannel.h:112
intermediate_table::iterator iterator
raw::ChannelID_t fChannel
readout channel where electrons are collected
Definition: SimChannel.h:150
float z
z position of ionization [cm]
Definition: SimChannel.h:117
Energy deposited on a readout channel by simulated tracks.
Definition: SimChannel.h:140
IDE(TrackID_t tid, float nel, float e, float xpos, float ypos, float zpos)
Constructor: sets all data members.
Definition: SimChannel.h:97
TH3F * xpos
Definition: doAna.cpp:29
std::pair< unsigned short, std::vector< sim::IDE > > TDCIDE
List of energy deposits at the same time (on this channel)
Definition: SimChannel.h:122
std::string string
Definition: nybbler.cc:12
void Dump(Stream &&out, std::string indent, std::string first_indent) const
Dumps the full content of the SimChannel into a stream.
Definition: SimChannel.h:337
float numElectrons
number of electrons from the particle detected on the wires
Definition: SimChannel.h:29
void Dump(Stream &&out, std::string indent="") const
Documentation at Dump(Stream&&, std::string, std::string) const.
Definition: SimChannel.h:304
intermediate_table::const_iterator const_iterator
unsigned int TDC_t
Definition: SimChannel.h:162
uint8_t channel
Definition: CRTFragment.hh:201
float energy
energy from the particle with this trackID [MeV]
Definition: SimChannel.h:28
std::vector< TDCIDE > TDCIDEs_t
Type of list of energy deposits for each TDC with signal.
Definition: SimChannel.h:147
float x
x position of ionization [cm]
Definition: SimChannel.h:115
TH3F * ypos
Definition: doAna.cpp:30
TDCIDEs_t fTDCIDEs
list of energy deposits for each TDC with signal
Definition: SimChannel.h:151
TH3F * zpos
Definition: doAna.cpp:31
TrackIDE(int id, float ef, float e, float ne)
Definition: SimChannel.h:34
const double e
Ionization at a point of the TPC sensitive volume.
Definition: SimChannel.h:84
float energy
energy deposited by ionization by this track ID and time [MeV]
Definition: SimChannel.h:114
float energyFrac
fraction of hit energy from the particle with this trackID
Definition: SimChannel.h:27
Code to link reconstructed objects back to the MC truth information.
float y
y position of ionization [cm]
Definition: SimChannel.h:116
bool operator==(const SimChannel &other) const
Comparison: true if SimChannels have the same channel ID.
Definition: SimChannel.h:327
raw::ChannelID_t Channel() const
Returns the readout channel this object describes.
Definition: SimChannel.h:329
int trackID
Geant4 supplied trackID.
Definition: SimChannel.h:26
bool operator<(const SimChannel &other) const
Comparison: sorts by channel ID.
Definition: SimChannel.h:326
IDE::TrackID_t TrackID_t
Type of track ID (the value comes from Geant4)
Definition: SimChannel.h:165
TDCIDEs_t const & TDCIDEMap() const
Returns all the deposited energy information as stored.
Definition: SimChannel.h:328
list x
Definition: train.py:276
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
int TrackID_t
Type of track ID (the value comes from Geant4)
Definition: SimChannel.h:87
Ionization energy from a Geant4 track.
Definition: SimChannel.h:25
bool operator<(const BeamGateInfo &lhs, const BeamGateInfo &rhs)
Definition: BeamGateInfo.h:45
float numElectrons
number of electrons at the readout for this track ID and time
Definition: SimChannel.h:113
TDCIDE::first_type StoredTDC_t
Type for TDC tick used in the internal representation.
Definition: SimChannel.h:144
TFile * ef
Definition: doAna.cpp:25
bool operator==(ModuleKeyAndType const &a, ModuleKeyAndType const &b) noexcept