10 #include "art/Framework/Core/EDAnalyzer.h"
11 #include "art/Framework/Core/ModuleMacros.h"
12 #include "art/Framework/Principal/Event.h"
13 #include "art/Framework/Principal/Handle.h"
14 #include "art/Framework/Principal/Run.h"
15 #include "art/Framework/Principal/SubRun.h"
16 #include "art_root_io/TFileService.h"
17 #include "canvas/Persistency/Common/FindManyP.h"
18 #include "canvas/Persistency/Common/FindOneP.h"
19 #include "canvas/Persistency/Common/Ptr.h"
20 #include "canvas/Persistency/Common/PtrVector.h"
21 #include "canvas/Utilities/InputTag.h"
22 #include "fhiclcpp/ParameterSet.h"
23 #include "messagefacility/MessageLogger/MessageLogger.h"
36 #include "nusimdata/SimulationBase/MCTruth.h"
44 class PFPSliceValidation;
64 std::map<art::Ptr<simb::MCTruth>,
int>
66 const sim::ParticleList &trueParticlesMap,
67 const std::map<
int, art::Ptr<simb::MCTruth>> &particleTruthMap,
72 art::Ptr<simb::MCTruth>
75 const std::map<
int, art::Ptr<simb::MCTruth>> &particleTruthMap,
76 const std::map<art::Ptr<simb::MCTruth>,
int> &truthHitMap,
77 float &completeness,
float &purity);
86 void initTree(TTree *Tree, std::string branchName, std::map<std::string, T> &
Metric,
102 SliceMatch(
int recoId,
int recoPdg,
float comp,
float purity,
float nuScore,
double vtx[3])
127 art::ServiceHandle<art::TFileService>
tfs;
128 art::ServiceHandle<cheat::BackTrackerService>
bt_serv;
156 , fVerbose(pset.get<
int>(
"Verbose", 0))
157 , fHitLabel(pset.get<std::string>(
"HitLabel"))
158 , fGenieGenModuleLabel(pset.get<std::string>(
"GenieGenModuleLabel"))
159 , fPFParticleLabels(pset.get<std::vector<std::string>>(
"PFParticleLabels")) {}
162 trueTree =
tfs->make<TTree>(
"trueTree",
"Tree with true neutrino metrics");
163 eventTree =
tfs->make<TTree>(
"eventTree",
"Tree with event wide metrics");
165 eventTree->Branch(
"trueNeutrinos", &eventTrueNeutrinos);
167 initTree(eventTree,
"pfpNeutrinos", eventPFPNeutrinos, fPFParticleLabels);
168 initTree(eventTree,
"pfpSlices", eventPFPSlices, fPFParticleLabels);
170 initTree(eventTree,
"cosmicScores", eventCosmicScores, fPFParticleLabels);
172 initTree(eventTree,
"nuScores", eventNeutrinoScores, fPFParticleLabels);
175 trueTree->Branch(
"intType", &intType);
176 trueTree->Branch(
"CCNC", &CCNC);
177 trueTree->Branch(
"neutrinoPDG", &neutrinoPDG);
178 trueTree->Branch(
"numProtons", &numProtons);
179 trueTree->Branch(
"numPi", &numPi);
180 trueTree->Branch(
"numPi0", &numPi0);
181 trueTree->Branch(
"numTrueHits", &numTrueHits);
182 trueTree->Branch(
"W", &W);
183 trueTree->Branch(
"X", &
X);
184 trueTree->Branch(
"Y", &Y);
185 trueTree->Branch(
"QSqr", &QSqr);
186 trueTree->Branch(
"Pt", &Pt);
187 trueTree->Branch(
"Theta", &Theta);
188 trueTree->Branch(
"neutrinoE", &neutrinoE);
189 trueTree->Branch(
"leptonP", &leptonP);
192 initTree(trueTree,
"numSlices", nuSlices, fPFParticleLabels);
193 initTree(trueTree,
"numNeutrinos", nuNeutrinos, fPFParticleLabels);
195 initTree(trueTree,
"bestMatchNeutrino", nuMatchNeutrino, fPFParticleLabels);
196 initTree(trueTree,
"purity", bestNuPurity, fPFParticleLabels);
197 initTree(trueTree,
"comp", bestNuComp, fPFParticleLabels);
198 initTree(trueTree,
"score", bestNuScore, fPFParticleLabels);
199 initTree(trueTree,
"recoPdg", bestNuPdg, fPFParticleLabels);
201 trueTree->Branch(
"trueVertexX", &trueVertexX);
202 trueTree->Branch(
"trueVertexY", &trueVertexY);
203 trueTree->Branch(
"trueVertexZ", &trueVertexZ);
205 initTree(trueTree,
"pfpVertexX", pfpVertexX, fPFParticleLabels);
206 initTree(trueTree,
"pfpVertexY", pfpVertexY, fPFParticleLabels);
207 initTree(trueTree,
"pfpVertexZ", pfpVertexZ, fPFParticleLabels);
208 initTree(trueTree,
"pfpVertexDistX", pfpVertexDistX, fPFParticleLabels);
209 initTree(trueTree,
"pfpVertexDistY", pfpVertexDistY, fPFParticleLabels);
210 initTree(trueTree,
"pfpVertexDistZ", pfpVertexDistZ, fPFParticleLabels);
211 initTree(trueTree,
"pfpVertexDistMag", pfpVertexDistMag, fPFParticleLabels);
218 const std::vector<art::Ptr<simb::MCTruth>> truthVec = particleInventory->MCTruthVector_Ps();
220 std::cout << std::setprecision(1) << std::fixed;
222 for (
auto const &truth : truthVec) {
223 std::cout <<
"Truth: " << truth << std::endl;
224 if (truth->NeutrinoSet()) {
225 const simb::MCNeutrino neutrino = truth->GetNeutrino();
226 std::cout <<
"Neutrino: " << neutrino << std::endl;
228 const simb::MCParticle
nu = neutrino.Nu();
229 std::cout <<
"X: " << nu.Vx() <<
" Y: " << nu.Vy() <<
" Z " << nu.Vz() << std::endl;
233 std::cout << std::setprecision(2) << std::fixed;
236 std::map<int, art::Ptr<simb::MCTruth>> particleTruthMap;
237 const sim::ParticleList &trueParticlesMap = particleInventory->ParticleList();
238 for (
auto const &[trackId, particle] : trueParticlesMap) {
239 particleTruthMap[trackId] = particleInventory->ParticleToMCTruth_P(particle);
241 eventTrueNeutrinos = truthVec.size();
246 auto hitHandles = evt.getMany<std::vector<recob::Hit>>();
249 auto vertexHandles = evt.getMany<std::vector<recob::Vertex>>();
252 art::Handle<std::vector<recob::Hit>> hitHandle;
253 art::Handle<std::vector<recob::PFParticle>> pfpHandle;
254 art::Handle<std::vector<recob::Slice>> sliceHandle;
255 art::Handle<std::vector<recob::Vertex>> vertexHandle;
258 std::vector<art::Ptr<recob::Hit>> allHits;
259 if (evt.getByLabel(fHitLabel, hitHandle))
260 art::fill_ptr_vector(allHits, hitHandle);
263 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
264 std::map<art::Ptr<simb::MCTruth>,
int> truthHitMap =
265 GetTruthHitMap(clockData, trueParticlesMap, particleTruthMap, allHits);
268 std::map<std::string, std::map<art::Ptr<simb::MCTruth>,
unsigned int>> pfpTruthNuCounterMap;
269 std::map<std::string, std::map<art::Ptr<simb::MCTruth>,
unsigned int>> pfpTruthSliceCounterMap;
270 std::map<std::string, std::map<art::Ptr<simb::MCTruth>,
SliceMatch>> pfpTruthSliceMatchMap;
273 for (
auto const fPFParticleLabel : fPFParticleLabels) {
274 for (
auto const &truth : truthVec) {
275 pfpTruthNuCounterMap[fPFParticleLabel][truth] = 0;
276 pfpTruthSliceCounterMap[fPFParticleLabel][truth] = 0;
280 for (
auto const fPFParticleLabel : fPFParticleLabels) {
283 std::cout <<
"On PFParticleLabel: " << fPFParticleLabel << std::endl;
287 std::vector<art::Ptr<recob::Slice>> pfpSliceVec;
288 if (evt.getByLabel(fPFParticleLabel, sliceHandle))
289 art::fill_ptr_vector(pfpSliceVec, sliceHandle);
291 std::vector<art::Ptr<recob::PFParticle>> pfps;
292 if (evt.getByLabel(fPFParticleLabel, pfpHandle))
293 art::fill_ptr_vector(pfps, pfpHandle);
295 art::FindOneP<recob::Vertex> fopfv(pfpHandle, evt, fPFParticleLabel);
296 if (fopfv.isValid() && fopfv.size() > 0) {
297 evt.get(fopfv.at(0).id(), vertexHandle);
298 if (!vertexHandle.isValid()) {
299 std::cout <<
"Vertex handle not valid" << std::endl;
304 art::FindManyP<recob::Hit> fmSliceHits(pfpSliceVec, evt, fPFParticleLabel);
305 if (!fmSliceHits.isValid() || fmSliceHits.size() == 0) {
306 std::cout <<
"FindMany Slice Hits not valid" << std::endl;
309 art::FindManyP<recob::PFParticle> fmSlicePFPs(pfpSliceVec, evt, fPFParticleLabel);
310 if (!fmSlicePFPs.isValid()) {
311 std::cout <<
"FindMany Slice PFPs not valid" << std::endl;
315 art::FindManyP<larpandoraobj::PFParticleMetadata> fmpfpmd(pfps, evt, fPFParticleLabel);
316 if (!fmpfpmd.isValid()) {
317 std::cout <<
"PFP MetaData handle not valid" << std::endl;
323 std::map<long unsigned int, art::Ptr<recob::PFParticle>> pfpMap;
324 std::map<long unsigned int, float> pfpNuScoreMap;
325 std::vector<art::Ptr<recob::PFParticle>> pfpNeutrinoVec;
327 for (
auto const &pfp : pfps) {
329 long unsigned int pfpID = pfp->Self();
333 if (pfp->PdgCode() == 12 || pfp->PdgCode() == 14) {
334 pfpNeutrinoVec.push_back(pfp);
335 if (fmpfpmd.size() == 0) {
336 std::cout <<
"PFP neutrino has no metadata" << std::endl;
341 const std::vector<art::Ptr<larpandoraobj::PFParticleMetadata>> pfpMetaVec =
343 for (
auto const pfpMeta : pfpMetaVec) {
345 pfpMeta->GetPropertiesMap();
346 pfpNuScoreMap[pfpID] = propertiesMap.at(
"NuScore");
351 eventPFPSlices[fPFParticleLabel] = pfpSliceVec.size();
352 eventPFPNeutrinos[fPFParticleLabel] = pfpNeutrinoVec.size();
354 for (
const auto &pfpSlice : pfpSliceVec) {
356 std::vector<art::Ptr<recob::Hit>> sliceHits = fmSliceHits.at(pfpSlice.key());
357 std::vector<art::Ptr<recob::PFParticle>> slicePFPs = fmSlicePFPs.at(pfpSlice.key());
359 bool isNeutrinoSlice(
false);
361 long unsigned int pfpNu(-999);
363 for (
auto const &pfp : slicePFPs) {
364 if (pfp->PdgCode() == 12 || pfp->PdgCode() == 14) {
366 nuScore = pfpNuScoreMap[pfpNu];
367 isNeutrinoSlice =
true;
373 float purity(-999), completeness(-999);
374 art::Ptr<simb::MCTruth> trueMatch = GetSliceTruthMatchHits(
375 clockData, sliceHits, particleTruthMap, truthHitMap, completeness, purity);
378 if (trueMatch.isNull())
381 if (fVerbose && isNeutrinoSlice)
382 std::cout <<
"True Match: " << trueMatch <<
" with completeness: " << completeness
383 <<
" and purity: " << purity <<
" and score: " << nuScore << std::endl;
386 ++pfpTruthSliceCounterMap[fPFParticleLabel][trueMatch];
387 if (isNeutrinoSlice) {
388 ++pfpTruthNuCounterMap[fPFParticleLabel][trueMatch];
389 if (trueMatch->NeutrinoSet()) {
390 eventNeutrinoScores[fPFParticleLabel].push_back(nuScore);
392 eventCosmicScores[fPFParticleLabel].push_back(nuScore);
397 if (completeness > pfpTruthSliceMatchMap[fPFParticleLabel][trueMatch].mComp) {
398 if (isNeutrinoSlice) {
400 art::Ptr<recob::PFParticle> pfpNeutrino = pfpMap.at(pfpNu);
401 art::Ptr<recob::Vertex> pfpVertex = fopfv.at(pfpNeutrino.key());
402 double pfpVtx[3] = {-999, -999, -999};
403 pfpVertex->XYZ(pfpVtx);
405 SliceMatch match(pfpNu, pfpNeutrino->PdgCode(), completeness, purity, nuScore, pfpVtx);
407 pfpTruthSliceMatchMap[fPFParticleLabel][trueMatch] = match;
410 double pfpVtx[3] = {-999, -999, -999};
411 SliceMatch match(-999, -999, completeness, purity, -999, pfpVtx);
412 pfpTruthSliceMatchMap[fPFParticleLabel][trueMatch] = match;
421 for (
auto const &truth : truthVec) {
426 if (!truth->NeutrinoSet())
430 const simb::MCNeutrino neutrino = truth->GetNeutrino();
431 const simb::MCParticle
nu = neutrino.Nu();
432 const simb::MCParticle lepton = neutrino.Lepton();
434 intType = neutrino.Mode();
435 CCNC = neutrino.CCNC();
436 neutrinoPDG = nu.PdgCode();
440 QSqr = neutrino.QSqr();
442 Theta = neutrino.Theta();
444 leptonP = lepton.P();
446 trueVertexX = nu.Vx();
447 trueVertexY = nu.Vy();
448 trueVertexZ = nu.Vz();
451 numTrueHits = truthHitMap.at(truth);
454 for (
auto const &[particleId, truthIter] : particleTruthMap) {
455 if (truthIter != truth)
457 const simb::MCParticle *particle = trueParticlesMap.at(particleId);
459 if (particle->Process() !=
"primary")
462 if (particle->PdgCode() == 2212 && (particle->E() - particle->Mass()) > 0.021) {
464 }
else if (
std::abs(particle->PdgCode()) == 211) {
466 }
else if (
std::abs(particle->PdgCode()) == 111) {
472 std::cout <<
"\nTruth: " << truth << std::endl;
475 for (
auto const fPFParticleLabel : fPFParticleLabels) {
478 if (pfpTruthSliceCounterMap[fPFParticleLabel].at(truth)) {
480 SliceMatch match = pfpTruthSliceMatchMap[fPFParticleLabel][truth];
482 nuSlices[fPFParticleLabel] = pfpTruthSliceCounterMap[fPFParticleLabel][truth];
483 nuNeutrinos[fPFParticleLabel] = pfpTruthNuCounterMap[fPFParticleLabel][truth];
484 bestNuComp[fPFParticleLabel] = match.
mComp;
485 bestNuPurity[fPFParticleLabel] = match.
mPurity;
486 bestNuScore[fPFParticleLabel] = match.
mNuScore;
487 bestNuPdg[fPFParticleLabel] = match.
mRecoPdg;
488 nuMatchNeutrino[fPFParticleLabel] = (match.
mRecoId != -999);
491 if (nuMatchNeutrino[fPFParticleLabel]) {
493 pfpVertexX[fPFParticleLabel] = match.
mVtxX;
494 pfpVertexY[fPFParticleLabel] = match.
mVtxY;
495 pfpVertexZ[fPFParticleLabel] = match.
mVtxZ;
497 pfpVertexDistX[fPFParticleLabel] = pfpVertexX[fPFParticleLabel] - nu.Vx();
498 pfpVertexDistY[fPFParticleLabel] = pfpVertexY[fPFParticleLabel] - nu.Vy();
499 pfpVertexDistZ[fPFParticleLabel] = pfpVertexZ[fPFParticleLabel] - nu.Vz();
501 pfpVertexDistMag[fPFParticleLabel] =
502 std::hypot(pfpVertexDistX[fPFParticleLabel], pfpVertexDistY[fPFParticleLabel],
503 pfpVertexDistZ[fPFParticleLabel]);
508 std::cout <<
"PFParticleLabel: " << fPFParticleLabel << std::endl;
510 std::cout <<
"Nu Slices: " << nuSlices[fPFParticleLabel]
511 <<
" and Nu Neutrinos: " << nuNeutrinos[fPFParticleLabel]
512 <<
" with best Nu Pdg: " << bestNuPdg[fPFParticleLabel]
513 <<
"\nCompleteness: " << bestNuComp[fPFParticleLabel]
514 <<
" and purity: " << bestNuPurity[fPFParticleLabel]
515 <<
" and score: " << bestNuScore[fPFParticleLabel] << std::endl;
525 const std::map<
int, art::Ptr<simb::MCTruth>> &particleTruthMap,
526 const std::vector<art::Ptr<recob::Hit>> &allHits) {
529 std::map<int, int> trueParticleHits;
530 for (
const auto &
hit : allHits) {
535 std::vector<sim::TrackIDE> trackIDEs = bt_serv->HitToTrackIDEs(clockData,
hit);
536 for (
const auto &ide : trackIDEs) {
537 if (ide.energy > hitEnergy) {
538 hitEnergy = ide.energy;
542 ++trueParticleHits[trackID];
546 std::map<art::Ptr<simb::MCTruth>,
int> truthHitMap;
547 for (
const auto &[trueParticle, truth] : particleTruthMap) {
548 truthHitMap[truth] += trueParticleHits[trueParticle];
556 const std::vector<art::Ptr<recob::Hit>> &sliceHits,
557 const std::map<
int, art::Ptr<simb::MCTruth>> &particleTruthMap,
558 const std::map<art::Ptr<simb::MCTruth>,
int> &truthHitMap,
float &completeness,
float &purity) {
561 std::map<int, int> trueParticleHits;
562 for (
const auto &
hit : sliceHits) {
567 std::vector<sim::TrackIDE> trackIDEs = bt_serv->HitToTrackIDEs(clockData,
hit);
568 for (
const auto &ide : trackIDEs) {
569 if (ide.energy > hitEnergy) {
570 hitEnergy = ide.energy;
574 ++trueParticleHits[trackID];
578 std::map<art::Ptr<simb::MCTruth>,
int> sliceTruthHitMap;
579 for (
const auto &[trueParticle, truth] : particleTruthMap) {
580 sliceTruthHitMap[truth] += trueParticleHits[trueParticle];
585 art::Ptr<simb::MCTruth> bestTruthMatch;
586 for (
const auto &[truth, truthHits] : sliceTruthHitMap) {
587 if (truthHits > maxHits) {
589 bestTruthMatch = truth;
595 if (!bestTruthMatch.isNull()) {
596 purity = (float)maxHits / sliceHits.size();
597 completeness = (float)maxHits / truthHitMap.at(bestTruthMatch);
600 return bestTruthMatch;
626 for (
auto const fPFParticleLabel : fPFParticleLabels) {
628 nuMatchNeutrino[fPFParticleLabel] =
false;
629 nuSlices[fPFParticleLabel] = -99999;
630 nuNeutrinos[fPFParticleLabel] = -99999;
631 bestNuPurity[fPFParticleLabel] = -99999;
632 bestNuComp[fPFParticleLabel] = -99999;
633 bestNuScore[fPFParticleLabel] = -99999;
634 bestNuPdg[fPFParticleLabel] = -99999;
636 pfpVertexX[fPFParticleLabel] = -99999;
637 pfpVertexY[fPFParticleLabel] = -99999;
638 pfpVertexZ[fPFParticleLabel] = -99999;
640 pfpVertexDistX[fPFParticleLabel] = -99999;
641 pfpVertexDistY[fPFParticleLabel] = -99999;
642 pfpVertexDistZ[fPFParticleLabel] = -99999;
643 pfpVertexDistMag[fPFParticleLabel] = -99999;
648 eventTrueNeutrinos = -999;
649 for (
auto const fPFParticleLabel : fPFParticleLabels) {
650 eventPFPNeutrinos[fPFParticleLabel] = -999;
651 eventPFPSlices[fPFParticleLabel] = -999;
652 eventCosmicScores[fPFParticleLabel].clear();
653 eventNeutrinoScores[fPFParticleLabel].clear();
659 std::map<std::string, T> &
Metric,
660 std::vector<std::string> fPFParticleLabels) {
662 for (
auto const &fPFParticleLabel : fPFParticleLabels) {
663 std::string branchString = branchName +
"_" + fPFParticleLabel;
664 const char *branchChar = branchString.c_str();
665 Tree->Branch(branchChar, &Metric[fPFParticleLabel], 32000, 0);
std::map< std::string, float > pfpVertexDistZ
std::vector< std::string > fPFParticleLabels
art::ServiceHandle< cheat::ParticleInventoryService > particleInventory
void initTree(TTree *Tree, std::string branchName, std::map< std::string, T > &Metric, std::vector< std::string > fPFParticleLabels)
std::map< std::string, int > eventPFPSlices
std::string fGenieGenModuleLabel
Declaration of signal hit object.
std::map< art::Ptr< simb::MCTruth >, int > GetTruthHitMap(const detinfo::DetectorClocksData &clockData, const sim::ParticleList &trueParticlesMap, const std::map< int, art::Ptr< simb::MCTruth >> &particleTruthMap, const std::vector< art::Ptr< recob::Hit >> &allHits)
std::map< std::string, float > PropertiesMap
art::ServiceHandle< cheat::BackTrackerService > bt_serv
std::map< std::string, float > pfpVertexDistX
process_name opflashCryoW ana
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
std::map< std::string, std::vector< float > > eventNeutrinoScores
SliceMatch(int recoId, int recoPdg, float comp, float purity, float nuScore, double vtx[3])
art::Ptr< simb::MCTruth > GetSliceTruthMatchHits(const detinfo::DetectorClocksData &clockData, const std::vector< art::Ptr< recob::Hit >> &sliceHits, const std::map< int, art::Ptr< simb::MCTruth >> &particleTruthMap, const std::map< art::Ptr< simb::MCTruth >, int > &truthHitMap, float &completeness, float &purity)
void analyze(art::Event const &evt) override
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
std::map< std::string, float > bestNuPurity
std::map< std::string, std::vector< float > > eventCosmicScores
double Metric(double q, double p)
std::map< std::string, float > pfpVertexDistMag
Declaration of cluster object.
art::ServiceHandle< art::TFileService > tfs
std::map< std::string, int > nuNeutrinos
std::map< std::string, float > pfpVertexDistY
std::map< std::string, float > bestNuComp
std::map< std::string, float > pfpVertexZ
std::map< std::string, bool > nuMatchNeutrino
std::map< std::string, float > bestNuScore
Contains all timing reference information for the detector.
std::map< std::string, int > nuSlices
PFPSliceValidation(fhicl::ParameterSet const &pset)
std::map< std::string, float > pfpVertexX
object containing MC truth information necessary for making RawDigits and doing back tracking ...
art::ServiceHandle< art::TFileService > tfs
PFPSliceValidation & operator=(PFPSliceValidation const &)=delete
std::map< std::string, float > pfpVertexY
std::map< std::string, int > eventPFPNeutrinos
BEGIN_PROLOG could also be cout
std::map< std::string, int > bestNuPdg