9 #include "Pandora/PdgTable.h" 11 #include "Objects/CaloHit.h" 12 #include "Objects/MCParticle.h" 13 #include "Objects/ParticleFlowObject.h" 15 #include "Helpers/MCParticleHelper.h" 28 unsigned int LArMonitoringHelper::CountHitsByType(
const HitType hitType,
const CaloHitList &caloHitList)
30 unsigned int nHitsOfSpecifiedType(0);
32 for (
const CaloHit *
const pCaloHit : caloHitList)
34 if (hitType == pCaloHit->GetHitType())
35 ++nHitsOfSpecifiedType;
38 return nHitsOfSpecifiedType;
43 void LArMonitoringHelper::GetOrderedMCParticleVector(
48 if (mcParticleToGoodHitsMap.empty())
52 std::vector<LArMCParticleHelper::MCParticleCaloHitListPair> mcParticleToGoodHitsVect;
53 std::copy(mcParticleToGoodHitsMap.begin(), mcParticleToGoodHitsMap.end(), std::back_inserter(mcParticleToGoodHitsVect));
56 std::sort(mcParticleToGoodHitsVect.begin(), mcParticleToGoodHitsVect.end(),
60 const bool isANuFinalState(LArMCParticleHelper::IsBeamNeutrinoFinalState(a.first)),
61 isBNuFinalState(LArMCParticleHelper::IsBeamNeutrinoFinalState(b.first));
63 if (isANuFinalState != isBNuFinalState)
64 return isANuFinalState;
66 const bool isABeamParticle(LArMCParticleHelper::IsBeamParticle(a.first)),
67 isBBeamParticle(LArMCParticleHelper::IsBeamParticle(b.first));
69 if (isABeamParticle != isBBeamParticle)
70 return isABeamParticle;
73 if (a.second.size() != b.second.size())
74 return (a.second.size() > b.second.size());
77 return LArMCParticleHelper::SortByMomentum(a.first, b.first);
81 orderedMCParticleVector.push_back(mcParticleCaloHitPair.first);
85 const unsigned int nMCParticles(orderedMCParticleVector.size());
86 if (std::distance(orderedMCParticleVector.begin(), std::unique(orderedMCParticleVector.begin(), orderedMCParticleVector.end())) != nMCParticles)
87 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
95 std::vector<LArMCParticleHelper::PfoCaloHitListPair> pfoToReconstructable2DHitsVect;
96 std::copy(pfoToReconstructable2DHitsMap.begin(), pfoToReconstructable2DHitsMap.end(), std::back_inserter(pfoToReconstructable2DHitsVect));
99 std::sort(pfoToReconstructable2DHitsVect.begin(), pfoToReconstructable2DHitsVect.end(),
103 const bool isANuFinalState(LArPfoHelper::IsNeutrinoFinalState(a.first)), isBNuFinalState(LArPfoHelper::IsNeutrinoFinalState(b.first));
105 if (isANuFinalState != isBNuFinalState)
106 return isANuFinalState;
108 if (a.second.size() != b.second.size())
109 return (a.second.size() > b.second.size());
112 return LArPfoHelper::SortByNHits(a.first, b.first);
116 orderedPfoVector.push_back(pfoCaloHitPair.first);
119 const unsigned int nPfos(orderedPfoVector.size());
120 if (std::distance(orderedPfoVector.begin(), std::unique(orderedPfoVector.begin(), orderedPfoVector.end())) != nPfos)
121 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
126 void LArMonitoringHelper::PrintMCParticleTable(
129 if (selectedMCParticleToGoodHitsMap.empty())
131 std::cout <<
"No MCParticles supplied." << std::endl;
135 LArFormattingHelper::Table table({
"ID",
"NUANCE",
"TYPE",
"",
"E",
"dist",
"",
"nGoodHits",
"U",
"V",
"W"});
137 unsigned int usedParticleCount(0);
138 for (
unsigned int id = 0;
id < orderedMCParticleVector.size(); ++id)
140 const MCParticle *
const pMCParticle(orderedMCParticleVector.at(
id));
143 if (selectedMCParticleToGoodHitsMap.end() == it)
147 table.AddElement(
id + 1);
148 table.AddElement(LArMCParticleHelper::GetNuanceCode(pMCParticle));
149 table.AddElement(PdgTable::GetParticleName(pMCParticle->GetParticleId()));
151 table.AddElement(pMCParticle->GetEnergy());
152 table.AddElement((pMCParticle->GetEndpoint() - pMCParticle->GetVertex()).GetMagnitude());
154 table.AddElement(it->second.size());
155 table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_U, it->second));
156 table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_V, it->second));
157 table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_W, it->second));
163 if (usedParticleCount != selectedMCParticleToGoodHitsMap.size())
164 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
173 if (pfoToReconstructable2DHitsMap.empty())
175 std::cout <<
"No Pfos supplied." << std::endl;
181 for (
unsigned int id = 0;
id < orderedPfoVector.size(); ++id)
183 const ParticleFlowObject *
const pPfo(orderedPfoVector.at(
id));
186 if (pfoToReconstructable2DHitsMap.end() == it)
187 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
190 table.AddElement(
id + 1);
191 table.AddElement(pPfo->GetParticleId());
192 table.AddElement(LArPfoHelper::IsNeutrinoFinalState(pPfo));
194 table.AddElement(it->second.size());
195 table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_U, it->second));
196 table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_V, it->second));
197 table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_W, it->second));
205 void LArMonitoringHelper::PrintMatchingTable(
const PfoVector &orderedPfoVector,
const MCParticleVector &orderedMCParticleVector,
208 if (orderedPfoVector.empty())
210 std::cout <<
"No Pfos supplied." << std::endl;
214 if (orderedMCParticleVector.empty())
216 std::cout <<
"No MCParticles supplied." << std::endl;
221 unsigned int maxMatches(0);
222 for (
const auto &entry : mcParticleToPfoHitSharingMap)
223 maxMatches = std::max(static_cast<unsigned int>(entry.second.size()), maxMatches);
225 const bool showOthersColumn(maxMatches > nMatches);
226 const unsigned int nMatchesToShow(std::min(maxMatches, nMatches));
229 std::vector<std::string> tableHeaders({
"MCParticle",
""});
230 for (
unsigned int i = 0; i < nMatchesToShow; ++i)
232 tableHeaders.push_back(
"");
233 tableHeaders.push_back(
"Pfo");
234 tableHeaders.push_back(
"nSharedHits");
237 if (showOthersColumn)
239 tableHeaders.push_back(
"");
240 tableHeaders.push_back(
"");
241 tableHeaders.push_back(
"nOtherPfos");
242 tableHeaders.push_back(
"nSharedHits");
248 for (
unsigned int mcParticleId = 0; mcParticleId < orderedMCParticleVector.size(); ++mcParticleId)
250 const MCParticle *
const pMCParticle(orderedMCParticleVector.at(mcParticleId));
254 if (it != mcParticleToPfoHitSharingMap.end())
255 pfoToSharedHitsVector = it->second;
258 ? LArFormattingHelper::LIGHT_GREEN
259 : (LArMCParticleHelper::IsBeamParticle(pMCParticle) ? LArFormattingHelper::LIGHT_BLUE : LArFormattingHelper::LIGHT_RED));
262 table.
AddElement(mcParticleId + 1, LArFormattingHelper::REGULAR, mcCol);
265 unsigned int nPfosShown(0);
266 unsigned int nOtherHits(0);
267 for (
const auto &pfoNSharedHitsPair : pfoToSharedHitsVector)
269 for (
unsigned int pfoId = 0; pfoId < orderedPfoVector.size(); ++pfoId)
271 if (pfoNSharedHitsPair.first != orderedPfoVector.at(pfoId))
274 if (nPfosShown < nMatchesToShow)
278 LArPfoHelper::IsNeutrinoFinalState(pfoNSharedHitsPair.first) ? LArFormattingHelper::LIGHT_GREEN : LArFormattingHelper::LIGHT_RED);
279 table.
AddElement(pfoId + 1, LArFormattingHelper::REGULAR, pfoCol);
280 table.
AddElement(pfoNSharedHitsPair.second.size(), LArFormattingHelper::REGULAR, pfoCol);
285 nOtherHits += pfoNSharedHitsPair.second.size();
292 for (
unsigned int i = 0; i < nMatchesToShow - nPfosShown; ++i)
299 if (!showOthersColumn)
304 table.
AddElement(pfoToSharedHitsVector.size() - nPfosShown);
318 template <
typename Ti,
typename Tj>
319 float LArMonitoringHelper::CalcRandIndex(
const std::map<
const Ti, std::map<const Tj, int>> &cTable)
323 for (
const auto &[i, jToVal] : cTable)
326 for (
const auto &[j, val] : jToVal)
331 aTerm +=
static_cast<double>(a * (a - 1)) / 2.;
333 if (
n == 0 ||
n == 1)
338 for (
const auto &[i, jToVal] : cTable)
340 for (
const auto &[j, val] : jToVal)
345 for (
const auto j : js)
348 for (
const auto &[i, jToVal] : cTable)
350 if (jToVal.find(j) != jToVal.end())
351 b += cTable.at(i).at(j);
353 bTerm +=
static_cast<double>(b * (b - 1)) / 2.;
356 double indexTerm{0.};
357 for (
const auto &[i, jToVal] : cTable)
359 for (
const auto &[j, val] : jToVal)
361 indexTerm +=
static_cast<double>(val * (val - 1)) / 2.;
365 double expIndexTerm{(aTerm * bTerm) / static_cast<double>(
n * (
n - 1)) / 2.};
366 double maxIndexTerm{0.5 * (aTerm + bTerm)};
367 if (
std::abs(maxIndexTerm - expIndexTerm) < std::numeric_limits<double>::epsilon())
368 return indexTerm >= expIndexTerm ? 1.
f : -1.
f;
369 double adjustedRandIndex{(indexTerm - expIndexTerm) / (maxIndexTerm - expIndexTerm)};
371 return adjustedRandIndex;
376 float LArMonitoringHelper::CalcRandIndex(
const CaloHitList &caloHits,
const ClusterList &clusters)
378 std::map<const Cluster *const, std::map<const MCParticle *const, int>> cTable;
379 FillContingencyTable(caloHits, clusters, cTable);
380 return CalcRandIndex(cTable);
385 void LArMonitoringHelper::FillContingencyTable(
386 const CaloHitList &caloHits,
const ClusterList &clusters, std::map<
const Cluster *
const, std::map<const MCParticle *const, int>> &cTable)
388 struct CaloHitParents
390 const pandora::MCParticle *m_pMainMC;
391 const pandora::Cluster *m_pCluster;
395 m_pCluster{
nullptr} {};
397 std::map<const CaloHit *const, CaloHitParents> hitParents;
400 for (
const CaloHit *
const pCaloHit : caloHits)
402 const MCParticle *pMainMC{
nullptr};
403 const MCParticleWeightMap &weightMap{pCaloHit->GetMCParticleWeightMap()};
404 float maxWeight{std::numeric_limits<float>::lowest()};
405 for (
const auto &[pMC,
weight] : weightMap)
415 hitParents[pCaloHit] = CaloHitParents();
416 hitParents[pCaloHit].m_pMainMC = pMainMC;
421 for (
const Cluster *
const pCluster : clusters)
423 const CaloHitList &isolatedHits{pCluster->GetIsolatedCaloHitList()};
424 CaloHitList clusterCaloHits;
425 pCluster->GetOrderedCaloHitList().FillCaloHitList(clusterCaloHits);
426 clusterCaloHits.insert(clusterCaloHits.end(), isolatedHits.begin(), isolatedHits.end());
427 for (
const CaloHit *
const pCaloHit : clusterCaloHits)
429 if (hitParents.find(pCaloHit) == hitParents.end())
431 hitParents[pCaloHit].m_pCluster = pCluster;
436 for (
const auto &[pCaloHit, parents] : hitParents)
438 const MCParticle *
const pMC = parents.m_pMainMC;
439 const Cluster *
const pCluster = parents.m_pCluster;
441 if (cTable.find(pCluster) == cTable.end() || cTable.at(pCluster).find(pMC) == cTable.at(pCluster).end())
442 cTable[pCluster][pMC] = 0;
443 cTable.at(pCluster).at(pMC)++;
449 template float LArMonitoringHelper::CalcRandIndex(
const std::map<
const Cluster *
const, std::map<const MCParticle *const, int>> &cTable);
Header file for the pfo helper class.
std::unordered_map< const pandora::MCParticle *, pandora::CaloHitList > MCContributionMap
std::pair< const pandora::MCParticle *, pandora::CaloHitList > MCParticleCaloHitListPair
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::map< const pandora::MCParticle *, PfoToSharedHitsVector > MCParticleToPfoHitSharingMap
std::vector< PfoCaloHitListPair > PfoToSharedHitsVector
Header file for the lar monitoring helper helper class.
Color
Style code enumeration.
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
void AddElement(const T &value, const Style style=REGULAR, const Color color=DEFAULT)
Add an element to the table into the next (non-separator) column.
std::vector< MCContributionMap > MCContributionMapVector
std::pair< const pandora::ParticleFlowObject *, pandora::CaloHitList > PfoCaloHitListPair
void Print() const
Print the table.
std::unordered_map< const pandora::ParticleFlowObject *, pandora::CaloHitList > PfoContributionMap