TruthMatchUtils.cc
Go to the documentation of this file.
1 /**
2  * @file larsim/Utils/TruthMatchUtils.cc
3  *
4  * @brief Implementation of the TruthMatchUtils functions
5  *
6  * @author Dom Brailsford (d.brailsford@lancaster.ac.uk)
7  *
8  * $Log: $
9  */
10 
11 //STL
12 #include <utility>
13 //ART
16 //LARSoft
18 
19 #include "TruthMatchUtils.h"
20 
21 namespace {
22 
23  using namespace TruthMatchUtils;
24 
25  constexpr G4ID kInvalidG4ID =
26  std::numeric_limits<G4ID>::lowest(); ///< The value used when no G4 ID has been found
27 
29  MaxEDepElementInMap(const IDToEDepositMap& idToEDepMap)
30  {
31  IDToEDepositMap::const_iterator highestContribIt(std::max_element(
32  idToEDepMap.begin(),
33  idToEDepMap.end(),
34  [](const std::pair<G4ID, EDeposit>& a, const std::pair<G4ID, EDeposit>& b) -> bool {
35  return std::nextafter(a.second, std::numeric_limits<EDeposit>::lowest()) <= b.second &&
36  std::nextafter(a.second, std::numeric_limits<EDeposit>::max()) >= b.second ?
37  1 :
38  a.second < b.second;
39  }));
40 
41  if (idToEDepMap.end() == highestContribIt) {
43  << "TruthMatchUtils did not manage to find a max element in the g4 ID to energy deposit "
44  "map. The map size is: "
45  << idToEDepMap.size();
46  }
47 
48  return highestContribIt;
49  }
50 
51 } // namespace
52 
53 //------------------------------------------------------------------------------------------------------------------------------------------
54 //------------------------------------------------------------------------------------------------------------------------------------------
55 
56 bool
57 TruthMatchUtils::Valid(const G4ID g4ID) noexcept
58 {
59  return kInvalidG4ID != g4ID;
60 }
61 
62 //------------------------------------------------------------------------------------------------------------------------------------------
63 
66  const art::Ptr<recob::Hit>& pHit,
67  const bool rollupUnsavedIDs)
68 {
69  IDToEDepositMap idToEDepMap;
70  TruthMatchUtils::FillG4IDToEnergyDepositMap(idToEDepMap, clockData, pHit, rollupUnsavedIDs);
71  if (idToEDepMap.empty()) return kInvalidG4ID;
72 
73  return MaxEDepElementInMap(idToEDepMap)->first;
74 }
75 
76 //------------------------------------------------------------------------------------------------------------------------------------------
77 
80  const std::vector<art::Ptr<recob::Hit>>& pHits,
81  const bool rollupUnsavedIDs)
82 {
83  IDToEDepositMap idToEDepMap;
84  for (const art::Ptr<recob::Hit>& pHit : pHits)
85  TruthMatchUtils::FillG4IDToEnergyDepositMap(idToEDepMap, clockData, pHit, rollupUnsavedIDs);
86 
87  if (idToEDepMap.empty()) return kInvalidG4ID;
88 
89  return MaxEDepElementInMap(idToEDepMap)->first;
90 }
91 
92 //------------------------------------------------------------------------------------------------------------------------------------------
93 
96  const std::vector<art::Ptr<recob::Hit>>& pHits,
97  const bool rollupUnsavedIDs)
98 {
99  IDToEDepositMap idToChargeDepMap;
100  for (const art::Ptr<recob::Hit>& pHit : pHits) {
101  const G4ID g4ID(TruthMatchUtils::TrueParticleID(clockData, pHit, rollupUnsavedIDs));
102  const EDeposit recoCharge(static_cast<EDeposit>(pHit->Integral()));
103  auto [iterator, inserted] = idToChargeDepMap.try_emplace(g4ID, recoCharge);
104  if (!inserted) iterator->second += recoCharge;
105  }
106 
107  if (idToChargeDepMap.empty()) return kInvalidG4ID;
108 
109  return MaxEDepElementInMap(idToChargeDepMap)->first;
110 }
111 
112 //------------------------------------------------------------------------------------------------------------------------------------------
113 
116  const std::vector<art::Ptr<recob::Hit>>& pHits,
117  const bool rollupUnsavedIDs)
118 {
119  std::map<G4ID, unsigned int> idToHitCountMap;
120  for (const art::Ptr<recob::Hit>& pHit : pHits) {
121  const G4ID g4ID(TruthMatchUtils::TrueParticleID(clockData, pHit, rollupUnsavedIDs));
122  auto [iterator, inserted] = idToHitCountMap.try_emplace(g4ID, 1);
123  if (!(inserted)) iterator->second++;
124  }
125 
126  if (idToHitCountMap.empty()) return kInvalidG4ID;
127 
128  std::map<unsigned int, std::vector<G4ID>> hitCountToIDMap;
129  for (auto const& [g4ID, hitCount] : idToHitCountMap) {
130  auto [iterator, inserted] = hitCountToIDMap.try_emplace(hitCount, std::vector<G4ID>{g4ID});
131  if (!inserted) iterator->second.emplace_back(g4ID);
132  }
133 
134  if (hitCountToIDMap.empty()) {
136  << "TruthMatchUtils::TrueParticleIDFromTotalRecoHits - Did not fill the hit count to g4 ID "
137  "vector map"
138  << "(map size == " << hitCountToIDMap.size() << ")."
139  << " The G4 ID to hit count map size is " << idToHitCountMap.size()
140  << ". The hit count to G4 ID vector map should not be empty in this case."
141  << " Something has gone wrong.";
142  }
143 
144  std::map<unsigned int, std::vector<G4ID>>::const_reverse_iterator lastElementIt(
145  hitCountToIDMap.rbegin());
146  unsigned int nMaxContributingIDs(lastElementIt->second.size());
147 
148  if (0 == nMaxContributingIDs) {
150  << "TruthMatchUtils::TrueParticleIDFromTotalRecoHits - Counted a max number of contributing "
151  "hits ("
152  << lastElementIt->first << " hits) but did not find any G4 IDs. Something has gone wrong.";
153  }
154  else if (1 < nMaxContributingIDs) {
155  mf::LogInfo("TruthMatchUtils::TrueParticleIDFromTotalRecoHits")
156  << "There are " << nMaxContributingIDs
157  << " particles which tie for highest number of contributing hits (" << lastElementIt->first
158  << " hits). Using TruthMatchUtils::TrueParticleIDFromTotalTrueEnergy instead." << std::endl;
159  return TruthMatchUtils::TrueParticleIDFromTotalTrueEnergy(clockData, pHits, rollupUnsavedIDs);
160  }
161 
162  return lastElementIt->second.front();
163 }
164 
165 //------------------------------------------------------------------------------------------------------------------------------------------
166 
167 void
169  detinfo::DetectorClocksData const& clockData,
170  const art::Ptr<recob::Hit>& pHit,
171  const bool rollupUnsavedIDs)
172 {
174  const std::vector<sim::TrackIDE> trackIDEs(btServ->HitToTrackIDEs(clockData, pHit));
175  if (trackIDEs.empty()) return;
176 
177  for (const sim::TrackIDE& trackIDE : trackIDEs) {
178  const G4ID g4ID(
179  static_cast<G4ID>(rollupUnsavedIDs ? std::abs(trackIDE.trackID) : trackIDE.trackID));
180  const EDeposit eDep(static_cast<EDeposit>(trackIDE.energy));
181  auto [iterator, inserted] = idToEDepMap.try_emplace(g4ID, eDep);
182  if (!inserted) iterator->second += eDep;
183  }
184 
185  if (idToEDepMap.empty()) {
187  << "TruthMatchUtils::FillG4IDToEnergyDepositMap did not fill the IDToEDepositMap map (map "
188  "size == "
189  << idToEDepMap.size() << ")."
190  << " The sim::TrackIDE vector size is " << trackIDEs.size()
191  << ". The IDToEDepositMap should not be empty when the"
192  << " sim::TrackIDE vector is also not empty. Something has gone wrong.";
193  }
194 
195  return;
196 }
intermediate_table::iterator iterator
G4ID TrueParticleIDFromTotalRecoCharge(detinfo::DetectorClocksData const &clockData, const std::vector< art::Ptr< recob::Hit >> &pHits, const bool rollupUnsavedIDs)
The G4 ID of the true particle whose matched hits have produced the largest amount of reconstructed c...
std::vector< sim::TrackIDE > HitToTrackIDEs(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
G4ID TrueParticleID(detinfo::DetectorClocksData const &clockData, const art::Ptr< recob::Hit > &pHit, const bool rollupUnsavedIDs)
The G4 ID of the true particle which deposits the most energy in the recob::Hit.
struct vector vector
intermediate_table::const_iterator const_iterator
T abs(T value)
Utilities for matching a recob::Hit or vector of recob::Hit to the ID of the most significantly contr...
const double a
std::map< G4ID, EDeposit > IDToEDepositMap
static int max(int a, int b)
bool Valid(const G4ID g4ID) noexcept
Test whether a G4ID returned by the TruthMatchUtils functions is valid.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
void FillG4IDToEnergyDepositMap(IDToEDepositMap &idToEDepMap, detinfo::DetectorClocksData const &clockData, const art::Ptr< recob::Hit > &pHit, const bool rollupUnsavedIDs)
Fill an energy deposition map (maps G4 ID to true energy deposition) for a recob::Hit.
Contains all timing reference information for the detector.
G4ID TrueParticleIDFromTotalTrueEnergy(detinfo::DetectorClocksData const &clockData, const std::vector< art::Ptr< recob::Hit >> &pHits, const bool rollupUnsavedIDs)
The G4 ID of the true particle which deposits the most energy in a vector of recob::Hit.
static bool * b
Definition: config.cpp:1043
G4ID TrueParticleIDFromTotalRecoHits(detinfo::DetectorClocksData const &clockData, const std::vector< art::Ptr< recob::Hit >> &pHits, const bool rollupUnsavedIDs)
The G4 ID of the true particle who has been truth-matched to the most hits in a recob::Hit vector...
Ionization energy from a Geant4 track.
Definition: SimChannel.h:25
QTextStream & endl(QTextStream &s)