All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 <limits>
13 #include <map>
14 #include <utility>
15 //ART
16 #include "art/Framework/Services/Registry/ServiceHandle.h"
17 #include "canvas/Utilities/Exception.h"
18 #include "messagefacility/MessageLogger/MessageLogger.h"
19 //LARSoft
21 
22 #include "TruthMatchUtils.h"
23 
24 namespace {
25 
26  using namespace TruthMatchUtils;
27 
28  constexpr G4ID kInvalidG4ID =
29  std::numeric_limits<G4ID>::lowest(); ///< The value used when no G4 ID has been found
30 
31  IDToEDepositMap::const_iterator
32  MaxEDepElementInMap(const IDToEDepositMap& idToEDepMap)
33  {
34  IDToEDepositMap::const_iterator highestContribIt(std::max_element(
35  idToEDepMap.begin(),
36  idToEDepMap.end(),
37  [](const std::pair<G4ID, EDeposit>& a, const std::pair<G4ID, EDeposit>& b) -> bool {
38  return std::nextafter(a.second, std::numeric_limits<EDeposit>::lowest()) <= b.second &&
39  std::nextafter(a.second, std::numeric_limits<EDeposit>::max()) >= b.second ?
40  1 :
41  a.second < b.second;
42  }));
43 
44  if (idToEDepMap.end() == highestContribIt) {
45  throw art::Exception(art::errors::LogicError)
46  << "TruthMatchUtils did not manage to find a max element in the g4 ID to energy deposit "
47  "map. The map size is: "
48  << idToEDepMap.size();
49  }
50 
51  return highestContribIt;
52  }
53 
54 } // namespace
55 
56 //------------------------------------------------------------------------------------------------------------------------------------------
57 //------------------------------------------------------------------------------------------------------------------------------------------
58 
59 bool
60 TruthMatchUtils::Valid(const G4ID g4ID) noexcept
61 {
62  return kInvalidG4ID != g4ID;
63 }
64 
65 //------------------------------------------------------------------------------------------------------------------------------------------
66 
69  const art::Ptr<recob::Hit>& pHit,
70  const bool rollupUnsavedIDs)
71 {
72  IDToEDepositMap idToEDepMap;
73  TruthMatchUtils::FillG4IDToEnergyDepositMap(idToEDepMap, clockData, pHit, rollupUnsavedIDs);
74  if (idToEDepMap.empty()) return kInvalidG4ID;
75 
76  return MaxEDepElementInMap(idToEDepMap)->first;
77 }
78 
79 //------------------------------------------------------------------------------------------------------------------------------------------
80 
83  const std::vector<art::Ptr<recob::Hit>>& pHits,
84  const bool rollupUnsavedIDs)
85 {
86  IDToEDepositMap idToEDepMap;
87  for (const art::Ptr<recob::Hit>& pHit : pHits)
88  TruthMatchUtils::FillG4IDToEnergyDepositMap(idToEDepMap, clockData, pHit, rollupUnsavedIDs);
89 
90  if (idToEDepMap.empty()) return kInvalidG4ID;
91 
92  return MaxEDepElementInMap(idToEDepMap)->first;
93 }
94 
95 //------------------------------------------------------------------------------------------------------------------------------------------
96 
99  const std::vector<art::Ptr<recob::Hit>>& pHits,
100  const bool rollupUnsavedIDs)
101 {
102  IDToEDepositMap idToChargeDepMap;
103  for (const art::Ptr<recob::Hit>& pHit : pHits) {
104  const G4ID g4ID(TruthMatchUtils::TrueParticleID(clockData, pHit, rollupUnsavedIDs));
105  const EDeposit recoCharge(static_cast<EDeposit>(pHit->Integral()));
106  auto [iterator, inserted] = idToChargeDepMap.try_emplace(g4ID, recoCharge);
107  if (!inserted) iterator->second += recoCharge;
108  }
109 
110  if (idToChargeDepMap.empty()) return kInvalidG4ID;
111 
112  return MaxEDepElementInMap(idToChargeDepMap)->first;
113 }
114 
115 //------------------------------------------------------------------------------------------------------------------------------------------
116 
119  const std::vector<art::Ptr<recob::Hit>>& pHits,
120  const bool rollupUnsavedIDs)
121 {
122  std::map<G4ID, unsigned int> idToHitCountMap;
123  for (const art::Ptr<recob::Hit>& pHit : pHits) {
124  const G4ID g4ID(TruthMatchUtils::TrueParticleID(clockData, pHit, rollupUnsavedIDs));
125  auto [iterator, inserted] = idToHitCountMap.try_emplace(g4ID, 1);
126  if (!(inserted)) iterator->second++;
127  }
128 
129  if (idToHitCountMap.empty()) return kInvalidG4ID;
130 
131  std::map<unsigned int, std::vector<G4ID>> hitCountToIDMap;
132  for (auto const& [g4ID, hitCount] : idToHitCountMap) {
133  auto [iterator, inserted] = hitCountToIDMap.try_emplace(hitCount, std::vector<G4ID>{g4ID});
134  if (!inserted) iterator->second.emplace_back(g4ID);
135  }
136 
137  if (hitCountToIDMap.empty()) {
138  throw art::Exception(art::errors::LogicError)
139  << "TruthMatchUtils::TrueParticleIDFromTotalRecoHits - Did not fill the hit count to g4 ID "
140  "vector map"
141  << "(map size == " << hitCountToIDMap.size() << ")."
142  << " The G4 ID to hit count map size is " << idToHitCountMap.size()
143  << ". The hit count to G4 ID vector map should not be empty in this case."
144  << " Something has gone wrong.";
145  }
146 
147  std::map<unsigned int, std::vector<G4ID>>::const_reverse_iterator lastElementIt(
148  hitCountToIDMap.rbegin());
149  unsigned int nMaxContributingIDs(lastElementIt->second.size());
150 
151  if (0 == nMaxContributingIDs) {
152  throw art::Exception(art::errors::LogicError)
153  << "TruthMatchUtils::TrueParticleIDFromTotalRecoHits - Counted a max number of contributing "
154  "hits ("
155  << lastElementIt->first << " hits) but did not find any G4 IDs. Something has gone wrong.";
156  }
157  else if (1 < nMaxContributingIDs) {
158  mf::LogInfo("TruthMatchUtils::TrueParticleIDFromTotalRecoHits")
159  << "There are " << nMaxContributingIDs
160  << " particles which tie for highest number of contributing hits (" << lastElementIt->first
161  << " hits). Using TruthMatchUtils::TrueParticleIDFromTotalTrueEnergy instead." << std::endl;
162  return TruthMatchUtils::TrueParticleIDFromTotalTrueEnergy(clockData, pHits, rollupUnsavedIDs);
163  }
164 
165  return lastElementIt->second.front();
166 }
167 
168 //------------------------------------------------------------------------------------------------------------------------------------------
169 
170 void
172  detinfo::DetectorClocksData const& clockData,
173  const art::Ptr<recob::Hit>& pHit,
174  const bool rollupUnsavedIDs)
175 {
176  const art::ServiceHandle<cheat::BackTrackerService> btServ;
177  const std::vector<sim::TrackIDE> trackIDEs(btServ->HitToTrackIDEs(clockData, pHit));
178  if (trackIDEs.empty()) return;
179 
180  for (const sim::TrackIDE& trackIDE : trackIDEs) {
181  const G4ID g4ID(
182  static_cast<G4ID>(rollupUnsavedIDs ? std::abs(trackIDE.trackID) : trackIDE.trackID));
183  const EDeposit eDep(static_cast<EDeposit>(trackIDE.energy));
184  auto [iterator, inserted] = idToEDepMap.try_emplace(g4ID, eDep);
185  if (!inserted) iterator->second += eDep;
186  }
187 
188  if (idToEDepMap.empty()) {
189  throw art::Exception(art::errors::LogicError)
190  << "TruthMatchUtils::FillG4IDToEnergyDepositMap did not fill the IDToEDepositMap map (map "
191  "size == "
192  << idToEDepMap.size() << ")."
193  << " The sim::TrackIDE vector size is " << trackIDEs.size()
194  << ". The IDToEDepositMap should not be empty when the"
195  << " sim::TrackIDE vector is also not empty. Something has gone wrong.";
196  }
197 
198  return;
199 }
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...
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.
process_name gaushit a
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
T abs(T value)
Utilities for matching a recob::Hit or vector of recob::Hit to the ID of the most significantly contr...
std::map< G4ID, EDeposit > IDToEDepositMap
bool Valid(const G4ID g4ID) noexcept
Test whether a G4ID returned by the TruthMatchUtils functions is valid.
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.
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:26