16 #include "art/Framework/Services/Registry/ServiceHandle.h"
17 #include "canvas/Utilities/Exception.h"
18 #include "messagefacility/MessageLogger/MessageLogger.h"
26 using namespace TruthMatchUtils;
28 constexpr
G4ID kInvalidG4ID =
29 std::numeric_limits<G4ID>::lowest();
31 IDToEDepositMap::const_iterator
34 IDToEDepositMap::const_iterator highestContribIt(std::max_element(
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 ?
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();
51 return highestContribIt;
62 return kInvalidG4ID != g4ID;
69 const art::Ptr<recob::Hit>& pHit,
70 const bool rollupUnsavedIDs)
74 if (idToEDepMap.empty())
return kInvalidG4ID;
76 return MaxEDepElementInMap(idToEDepMap)->first;
84 const bool rollupUnsavedIDs)
87 for (
const art::Ptr<recob::Hit>& pHit : pHits)
90 if (idToEDepMap.empty())
return kInvalidG4ID;
92 return MaxEDepElementInMap(idToEDepMap)->first;
100 const bool rollupUnsavedIDs)
103 for (
const art::Ptr<recob::Hit>& pHit : pHits) {
105 const EDeposit recoCharge(static_cast<EDeposit>(pHit->Integral()));
106 auto [iterator, inserted] = idToChargeDepMap.try_emplace(g4ID, recoCharge);
107 if (!inserted) iterator->second += recoCharge;
110 if (idToChargeDepMap.empty())
return kInvalidG4ID;
112 return MaxEDepElementInMap(idToChargeDepMap)->first;
120 const bool rollupUnsavedIDs)
122 std::map<G4ID, unsigned int> idToHitCountMap;
123 for (
const art::Ptr<recob::Hit>& pHit : pHits) {
125 auto [iterator, inserted] = idToHitCountMap.try_emplace(g4ID, 1);
126 if (!(inserted)) iterator->second++;
129 if (idToHitCountMap.empty())
return kInvalidG4ID;
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);
137 if (hitCountToIDMap.empty()) {
138 throw art::Exception(art::errors::LogicError)
139 <<
"TruthMatchUtils::TrueParticleIDFromTotalRecoHits - Did not fill the hit count to g4 ID "
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.";
147 std::map<unsigned int, std::vector<G4ID>>::const_reverse_iterator lastElementIt(
148 hitCountToIDMap.rbegin());
149 unsigned int nMaxContributingIDs(lastElementIt->second.size());
151 if (0 == nMaxContributingIDs) {
152 throw art::Exception(art::errors::LogicError)
153 <<
"TruthMatchUtils::TrueParticleIDFromTotalRecoHits - Counted a max number of contributing "
155 << lastElementIt->first <<
" hits) but did not find any G4 IDs. Something has gone wrong.";
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;
165 return lastElementIt->second.front();
173 const art::Ptr<recob::Hit>& pHit,
174 const bool rollupUnsavedIDs)
176 const art::ServiceHandle<cheat::BackTrackerService> btServ;
177 const std::vector<sim::TrackIDE> trackIDEs(btServ->HitToTrackIDEs(clockData, pHit));
178 if (trackIDEs.empty())
return;
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;
188 if (idToEDepMap.empty()) {
189 throw art::Exception(art::errors::LogicError)
190 <<
"TruthMatchUtils::FillG4IDToEnergyDepositMap did not fill the IDToEDepositMap map (map "
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.";
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.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
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.