LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
SimChannel.cxx
Go to the documentation of this file.
1 
9 #include <algorithm> // std::lower_bound(), std::max()
10 #include <limits> // std::numeric_limits
11 #include <map>
12 #include <stdexcept>
13 #include <utility>
14 
17 
19 
20 namespace sim {
21 
22  //-------------------------------------------------
24  : trackID(util::kBogusI)
25  , numElectrons(util::kBogusD)
26  , energy(util::kBogusD)
27  , x(util::kBogusD)
28  , y(util::kBogusD)
29  , z(util::kBogusD)
30  , origTrackID(util::kBogusI)
31  {}
32 
33  //-------------------------------------------------
34  IDE::IDE(sim::IDE const& ide, int offset) : IDE(ide)
35  {
36 
37  trackID = trackID >= 0 ? trackID + offset : trackID - offset;
38  origTrackID = origTrackID >= 0 ? origTrackID + offset : origTrackID - offset;
39  }
40 
41  // Default constructor
42  //-------------------------------------------------
44 
45  //-------------------------------------------------
47 
48  //-------------------------------------------------
50  TDC_t tdc,
51  double numberElectrons,
52  double const* xyz,
53  double energy,
54  TrackID_t origTrackID)
55  {
56  // look at the collection to see if the current TDC already
57  // exists, if not, add it, if so, just add a new track id to the
58  // vector, or update the information if track is already present
59 
60  // no electrons? no energy? no good!
61  if ((numberElectrons < std::numeric_limits<double>::epsilon()) ||
62  (energy <= std::numeric_limits<double>::epsilon())) {
63  // will throw
64  MF_LOG_ERROR("SimChannel") << "AddIonizationElectrons() trying to add to TDC #" << tdc << " "
65  << numberElectrons << " electrons with " << energy
66  << " MeV of energy from track ID=" << trackID;
67  return;
68  } // if no energy or no electrons
69 
70  auto itr = findClosestTDCIDE(tdc);
71 
72  // check if this tdc value is in the vector, it is possible that
73  // the lower bound is different from the given tdc, in which case
74  // we need to add something for that tdc
75  if (itr == fTDCIDEs.end() || itr->first != tdc) {
76  std::vector<sim::IDE> idelist;
77  idelist.emplace_back(trackID, numberElectrons, energy, xyz[0], xyz[1], xyz[2], origTrackID);
78  fTDCIDEs.emplace(itr, tdc, std::move(idelist));
79  }
80  else { // we have that TDC already; itr points to it
81 
82  // loop over the IDE vector for this tdc and add the electrons
83  // to the entry with the same G4 track id
84  for (auto& ide : itr->second) {
85 
86  if (ide.origTrackID != origTrackID) continue;
87 
88  // make a weighted average for the location information
89  double weight = ide.numElectrons + numberElectrons;
90  ide.x = (ide.x * ide.numElectrons + xyz[0] * numberElectrons) / weight;
91  ide.y = (ide.y * ide.numElectrons + xyz[1] * numberElectrons) / weight;
92  ide.z = (ide.z * ide.numElectrons + xyz[2] * numberElectrons) / weight;
93  ide.numElectrons = weight;
94  ide.energy = ide.energy + energy;
95 
96  // found the track id we wanted, so return;
97  return;
98  } // for
99 
100  // if we never found the track id, then this is the first instance of
101  // the track id for this tdc, so add ide to the vector
102  itr->second.emplace_back(
103  trackID, numberElectrons, energy, xyz[0], xyz[1], xyz[2], origTrackID);
104 
105  } // if new TDC ... else
106 
107  } // SimChannel::AddIonizationElectrons()
108 
109  //-------------------------------------------------
110  double SimChannel::Charge(TDC_t tdc) const
111  {
112  double charge = 0.;
113 
114  auto itr = findClosestTDCIDE(tdc);
115 
116  // check to see if this tdc value is in the map
117  if (itr != fTDCIDEs.end() && itr->first == tdc) {
118 
119  // loop over the list for this tdc value and add up
120  // the total number of electrons
121  for (auto ide : itr->second) {
122  charge += ide.numElectrons;
123  } // end loop over sim::IDE for this tdc
124 
125  } // end if this tdc is represented in the map
126 
127  return charge;
128  }
129 
130  //-------------------------------------------------
131  double SimChannel::Energy(TDC_t tdc) const
132  {
133  double energy = 0.;
134 
135  auto itr = findClosestTDCIDE(tdc);
136 
137  // check to see if this tdc value is in the map
138  if (itr != fTDCIDEs.end() && itr->first == tdc) {
139 
140  // loop over the list for this tdc value and add up
141  // the total number of electrons
142  for (auto ide : itr->second) {
143  energy += ide.energy;
144  } // end loop over sim::IDE for this tdc
145 
146  } // end if this tdc is represented in the map
147 
148  return energy;
149  }
150 
151  //-----------------------------------------------------------------------
152  // the start and end tdc values are assumed to be inclusive
153  std::vector<sim::IDE> SimChannel::TrackIDsAndEnergies(TDC_t startTDC, TDC_t endTDC) const
154  {
155  // make a map of track ID values to sim::IDE objects
156 
157  if (startTDC > endTDC) {
158  mf::LogWarning("SimChannel")
159  << "requested tdc range is bogus: " << startTDC << " " << endTDC << " return empty vector";
160  return {}; // returns an empty vector
161  }
162 
163  std::map<TrackID_t, sim::IDE> idToIDE;
164 
165  //find the lower bound for this tdc and then iterate from there
166  auto itr = findClosestTDCIDE(startTDC);
167 
168  while (itr != fTDCIDEs.end()) {
169 
170  // check the tdc value for the iterator, break the loop if we
171  // are outside the range
172  if (itr->first > endTDC) break;
173 
174  // grab the vector of IDEs for this tdc
175  auto const& idelist = itr->second;
176  // now loop over them and add their content to the map
177  for (auto const& ide : idelist) {
178  auto itTrkIDE = idToIDE.find(ide.trackID);
179  if (itTrkIDE != idToIDE.end()) {
180  // the IDE we are going to update:
181  sim::IDE& trackIDE = itTrkIDE->second;
182 
183  double const nel1 = trackIDE.numElectrons;
184  double const nel2 = ide.numElectrons;
185  double const en1 = trackIDE.energy;
186  double const en2 = ide.energy;
187  double const energy = en1 + en2;
188  double const weight = nel1 + nel2;
189 
190  // make a weighted average for the location information
191  trackIDE.x = (ide.x * nel2 + trackIDE.x * nel1) / weight;
192  trackIDE.y = (ide.y * nel2 + trackIDE.y * nel1) / weight;
193  trackIDE.z = (ide.z * nel2 + trackIDE.z * nel1) / weight;
194  trackIDE.numElectrons = weight;
195  trackIDE.energy = energy;
196  } // end if the track id for this one is found
197  else {
198  idToIDE[ide.trackID] = sim::IDE(ide);
199  }
200  } // end loop over vector
201 
202  ++itr;
203  } // end loop over tdc values
204 
205  // now fill the vector with the ides from the map
206  std::vector<sim::IDE> ides;
207  ides.reserve(idToIDE.size());
208  for (auto const& itr : idToIDE) {
209  ides.push_back(itr.second);
210  }
211 
212  return ides;
213  }
214 
215  //-----------------------------------------------------------------------
216  // the start and end tdc values are assumed to be inclusive
217  std::vector<sim::TrackIDE> SimChannel::TrackIDEs(TDC_t startTDC, TDC_t endTDC) const
218  {
219 
220  std::vector<sim::TrackIDE> trackIDEs;
221 
222  if (startTDC > endTDC) {
223  mf::LogWarning("SimChannel::TrackIDEs")
224  << "requested tdc range is bogus: " << startTDC << " " << endTDC << " return empty vector";
225  return trackIDEs;
226  }
227 
228  double totalE = 0.;
229  std::vector<sim::IDE> const ides = TrackIDsAndEnergies(startTDC, endTDC);
230  for (auto const& ide : ides)
231  totalE += ide.energy;
232 
233  // protect against a divide by zero below
234  if (totalE < 1.e-5) totalE = 1.;
235 
236  // loop over the entries in the map and fill the input vectors
237  for (auto const& ide : ides) {
238  if (ide.trackID == sim::NoParticleId) continue;
239  trackIDEs.emplace_back(
240  ide.trackID, ide.energy / totalE, ide.energy, ide.numElectrons, ide.origTrackID);
241  }
242 
243  return trackIDEs;
244  }
245 
246  //-----------------------------------------------------------------------
247  // Merge the collection of IDEs from one sim channel to another.
248  // Requires an agreed upon offset for G4 trackID
249  std::pair<SimChannel::TrackID_t, SimChannel::TrackID_t> SimChannel::MergeSimChannel(
250  SimChannel const& channel,
251  int offset)
252  {
253  if (this->Channel() != channel.Channel())
254  throw std::runtime_error("ERROR SimChannel Merge: Trying to merge different channels!");
255 
256  std::pair<TrackID_t, TrackID_t> range_trackID(std::numeric_limits<int>::max(),
257  std::numeric_limits<int>::min());
258 
259  for (auto const& itr : channel.TDCIDEMap()) {
260 
261  auto tdc = itr.first;
262  auto const& ides = itr.second;
263 
264  // find the entry from this SimChannel corresponding to the tdc from the other
265  auto itrthis = findClosestTDCIDE(tdc);
266 
267  // pick which IDE list we have to fill: new one or existing one
268  std::vector<sim::IDE>* curIDEVec;
269  if (itrthis == fTDCIDEs.end() || itrthis->first != tdc) {
270  fTDCIDEs.emplace_back(tdc, std::vector<sim::IDE>());
271  curIDEVec = &(fTDCIDEs.back().second);
272  }
273  else
274  curIDEVec = &(itrthis->second);
275 
276  for (auto const& ide : ides) {
277  curIDEVec->emplace_back(ide, offset);
278  auto tid = std::abs(ide.trackID) + offset;
279  if (tid < range_trackID.first) range_trackID.first = tid;
280  if (tid > range_trackID.second) range_trackID.second = tid;
281  } //end loop over IDEs
282 
283  } //end loop over TDCIDEMap
284 
285  return range_trackID;
286  }
287 
288  //-------------------------------------------------
290 
291  bool operator()(TDCIDE const& a, TDCIDE const& b) const { return a.first < b.first; }
292 
293  bool operator()(StoredTDC_t a_tdc, TDCIDE const& b) const { return a_tdc < b.first; }
294 
295  bool operator()(TDCIDE const& a, StoredTDC_t b_tdc) const { return a.first < b_tdc; }
296 
297  }; // struct CompareByTDC
298 
300  {
301  return std::lower_bound(fTDCIDEs.begin(), fTDCIDEs.end(), tdc, CompareByTDC());
302  }
303 
305  {
306  return std::lower_bound(fTDCIDEs.begin(), fTDCIDEs.end(), tdc, CompareByTDC());
307  }
308 
309  //-------------------------------------------------
310 
311 }
Float_t x
Definition: compare.C:6
TrackID_t trackID
Geant4 supplied track ID.
Definition: SimChannel.h:107
intermediate_table::iterator iterator
std::pair< TrackID_t, TrackID_t > MergeSimChannel(const SimChannel &channel, int offset)
Merges the deposits from another channel into this one.
Definition: SimChannel.cxx:249
raw::ChannelID_t fChannel
readout channel where electrons are collected
Definition: SimChannel.h:145
float z
z position of ionization [cm]
Definition: SimChannel.h:112
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
Energy deposited on a readout channel by simulated tracks.
Definition: SimChannel.h:136
std::pair< unsigned short, std::vector< sim::IDE > > TDCIDE
List of energy deposits at the same time (on this channel)
Definition: SimChannel.h:118
double Energy(TDC_t tdc) const
Returns the total energy on this channel in the specified TDC [MeV].
Definition: SimChannel.cxx:131
Float_t y
Definition: compare.C:6
Double_t z
Definition: plot.C:276
constexpr auto abs(T v)
Returns the absolute value of the argument.
#define MF_LOG_ERROR(category)
TrackID_t origTrackID
Geant4 supplied track ID (remains true trackID even for shower secondaries/tertiaries etc) ...
Definition: SimChannel.h:114
constexpr int kBogusI
obviously bogus integer value
intermediate_table::const_iterator const_iterator
Raw data description.
Definition: RawTypes.h:6
unsigned int TDC_t
Definition: SimChannel.h:155
float x
x position of ionization [cm]
Definition: SimChannel.h:110
TDCIDEs_t fTDCIDEs
list of energy deposits for each TDC with signal
Definition: SimChannel.h:146
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
Definition: RawTypes.h:31
bool operator()(TDCIDE const &a, TDCIDE const &b) const
Definition: SimChannel.cxx:291
double Charge(TDC_t tdc) const
Returns the total number of ionization electrons on this channel in the specified TDC...
Definition: SimChannel.cxx:110
Ionization at a point of the TPC sensitive volume.
Definition: SimChannel.h:85
static const int NoParticleId
Definition: sim.h:21
float energy
energy deposited by ionization by this track ID and time [MeV]
Definition: SimChannel.h:109
std::vector< sim::TrackIDE > TrackIDEs(TDC_t startTDC, TDC_t endTDC) const
Returns energies collected for each track within a time interval.
Definition: SimChannel.cxx:217
double energy
Definition: plottest35.C:25
Monte Carlo Simulation.
bool operator()(TDCIDE const &a, StoredTDC_t b_tdc) const
Definition: SimChannel.cxx:295
TDCIDEs_t::iterator findClosestTDCIDE(StoredTDC_t tdc)
Return the iterator to the first TDCIDE not earlier than tdc.
Definition: SimChannel.cxx:299
float y
y position of ionization [cm]
Definition: SimChannel.h:111
raw::ChannelID_t Channel() const
Returns the readout channel this object describes.
Definition: SimChannel.h:323
double weight
Definition: plottest35.C:25
std::vector< sim::IDE > TrackIDsAndEnergies(TDC_t startTDC, TDC_t endTDC) const
Return all the recorded energy deposition within a time interval.
Definition: SimChannel.cxx:153
IDE::TrackID_t TrackID_t
Type of track ID (the value comes from Geant4)
Definition: SimChannel.h:158
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
object containing MC truth information necessary for making RawDigits and doing back tracking ...
bool operator()(StoredTDC_t a_tdc, TDCIDE const &b) const
Definition: SimChannel.cxx:293
TDCIDEs_t const & TDCIDEMap() const
Returns all the deposited energy information as stored.
Definition: SimChannel.h:319
constexpr double kBogusD
obviously bogus double value
IDE()
Default constructor (sets "bogus" values)
Definition: SimChannel.cxx:23
void AddIonizationElectrons(TrackID_t trackID, TDC_t tdc, double numberElectrons, double const *xyz, double energy, TrackID_t origTrackID=util::kBogusI)
Add ionization electrons and energy to this channel.
Definition: SimChannel.cxx:49
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
Float_t e
Definition: plot.C:35
Tools and modules for checking out the basics of the Monte Carlo.
float numElectrons
number of electrons at the readout for this track ID and time
Definition: SimChannel.h:108
TDCIDE::first_type StoredTDC_t
Type for TDC tick used in the internal representation.
Definition: SimChannel.h:139