22 #include "canvas/Persistency/Common/FindManyP.h" 37 #include "TEfficiency.h" 65 void AddHitPreClustering(
TrackID id);
66 void AddSignalHitPostClustering(
ClusterID id);
67 void AddNoiseHitPostClustering(
ClusterID id);
71 double GetEfficiency(
TrackID id);
74 int GetNumberHitsFromTrack(
TrackID id);
76 int GetNumberHitsInPlane();
77 std::vector<std::pair<TrackID, ClusterIDs>> GetPhotons();
84 unsigned int tpc, plane;
108 ++numHitsPreClustering[trackID];
114 ++numSignalHitsPostClustering[clusID];
120 ++numNoiseHitsPostClustering[clusID];
126 clusterToTrackID[clusID] = trackID;
127 trackToClusterIDs[trackID].push_back(clusID);
133 return (
double)numSignalHitsPostClustering[clusID] /
134 (double)numHitsPreClustering[clusterToTrackID[clusID]];
140 return (
double)numSignalHitsPostClustering[clusID] / (double)(GetNumberHitsInCluster(clusID));
146 return 1 / (double)trackToClusterIDs.at(trackID).size();
152 return numHitsPreClustering[trackID];
158 return numSignalHitsPostClustering[clusID] + numNoiseHitsPostClustering[clusID];
165 for (
auto& trackHits : numHitsPreClustering)
166 nHits += trackHits.second;
175 i != clusterToTrackID.end();
177 v.push_back(i->first);
186 i != trackToClusterIDs.end();
188 v.push_back(i->first);
192 std::vector<std::pair<TrackID, ClusterIDs>>
195 std::vector<std::pair<TrackID, ClusterIDs>> photonVector;
196 for (
unsigned int track = 0; track < GetListOfTrackIDs().size(); ++track)
197 if (!IsNoise(GetListOfTrackIDs().at(track)) &&
198 pi_serv->TrackIdToParticle_P((
int)GetListOfTrackIDs().at(track))->PdgCode() == 22)
199 photonVector.push_back(std::pair<TrackID, ClusterIDs>(
200 GetListOfTrackIDs().at(track), trackToClusterIDs.at(GetListOfTrackIDs().at(track))));
207 return clusterToTrackID.at(
id);
213 return IsNoise(clusterToTrackID.at(clusID));
219 return (
int)trackID == 0 ?
true :
false;
225 if (GetPhotons().
size() > 2 || GetPhotons().
size() == 0)
return false;
227 for (
unsigned int photon = 0; photon < GetPhotons().size(); ++photon)
229 if (GetCompleteness(GetPhotons().at(photon).
second.at(
cluster)) > 0.5)
230 goodPhotons.push_back(GetPhotons().at(photon).first);
231 if ((GetPhotons().
size() == 2 && goodPhotons.size() > 2) ||
232 (GetPhotons().size() == 1 && goodPhotons.size() > 1))
233 std::cout <<
"More than 2 with >50%?!" <<
std::endl;
234 bool pass = ((GetPhotons().size() == 2 && goodPhotons.size() == 2) ||
235 (GetPhotons().size() == 1 && goodPhotons.size() == 1));
247 const art::FindManyP<recob::Hit>& fmh,
252 double FindPhotonAngle();
255 TObjArray GetHistograms();
256 void MakeHistograms();
265 TH1 *hPi0Angle, *hPi0Energy, *hPi0ConversionDistance, *hPi0ConversionSeparation, *hPi0AngleCut,
266 *
hPi0EnergyCut, *hPi0ConversionDistanceCut, *hPi0ConversionSeparationCut;
269 *hCompletenessConversionSeparation;
271 *hCleanlinessConversionSeparation;
273 *hComplCleanlConversionSeparation;
275 *hEfficiencyConversionSeparation;
278 std::map<unsigned int, std::map<unsigned int, std::unique_ptr<ClusterCounter>>>
clusterMap;
290 fClusterLabel = clusterLabel;
293 hCompleteness =
new TH1D(
"Completeness",
";Completeness;", 101, 0, 1.01);
294 hCompletenessEnergy =
295 new TProfile(
"CompletenessEnergy",
";True Energy (GeV);Completeness", 100, 0, 2);
297 new TProfile(
"CompletenessAngle",
";True Angle (deg);Completeness;", 100, 0, 180);
298 hCompletenessConversionDistance =
new TProfile(
299 "CompletenessConversionDistance",
";True Distance from Vertex (cm);Completeness", 100, 0, 200);
300 hCompletenessConversionSeparation =
new TProfile(
"CompletenessConversionSeparation",
301 ";True Conversion Separation (cm);Completeness",
305 hCleanliness =
new TH1D(
"Cleanliness",
";Cleanliness;", 101, 0, 1.01);
307 new TProfile(
"CleanlinessEnergy",
";True Energy (GeV);Cleanliness", 100, 0, 2);
309 new TProfile(
"CleanlinessAngle",
";True Angle (deg);Cleanliness;", 100, 0, 180);
310 hCleanlinessConversionDistance =
new TProfile(
311 "CleanlinessConversionDistance",
";True Distance from Vertex (cm);Cleanliness", 100, 0, 200);
312 hCleanlinessConversionSeparation =
new TProfile(
313 "CleanlinessConversionSeparation",
";True Conversion Separation (cm);Cleanliness", 100, 0, 200);
314 hComplCleanl =
new TH1D(
"CompletenessCleanliness",
";Completeness * Cleanliness;", 101, 0, 1.01);
315 hComplCleanlEnergy =
new TProfile(
316 "CompletenessCleanlinessEnergy",
";True Energy (GeV);Completeness * Cleanliness", 100, 0, 2);
317 hComplCleanlAngle =
new TProfile(
318 "CompletenessCleanlinessAngle",
";True Angle (deg);Completeness * Cleanliness;", 100, 0, 180);
319 hComplCleanlConversionDistance =
320 new TProfile(
"CompletenessCleanlinessConversionDistance",
321 ";True Distance from Vertex (cm);Completeness * Cleanliness",
325 hComplCleanlConversionSeparation =
326 new TProfile(
"CompletenessCleanlinessConversionSeparation",
327 ";True Conversion Separation (cm);Completeness * Cleanliness",
331 hPi0Energy =
new TH1D(
"Pi0EnergyCut",
";True Energy (GeV);", 25, 0, 2);
333 hPi0Angle =
new TH1D(
"Pi0AngleCut",
";True Angle (deg);", 25, 0, 180);
335 hPi0ConversionDistance =
336 new TH1D(
"Pi0ConversionDistanceCut",
";True Distance from Vertex (cm);", 25, 0, 200);
337 hPi0ConversionDistance->Sumw2();
338 hPi0ConversionSeparation =
339 new TH1D(
"Pi0ConversionSeparationCut",
";True Separation from Vertex (cm);", 25, 0, 200);
340 hPi0ConversionSeparation->Sumw2();
341 hPi0EnergyCut =
new TH1D(
"Pi0EnergyCut",
";True Energy (GeV);Efficiency", 25, 0, 2);
342 hPi0EnergyCut->Sumw2();
343 hPi0AngleCut =
new TH1D(
"Pi0AngleCut",
";True Angle (deg);Efficiency", 25, 0, 180);
344 hPi0AngleCut->Sumw2();
345 hPi0ConversionDistanceCut =
346 new TH1D(
"Pi0ConversionDistanceCut",
";True Distance from Vertex (cm);Efficiency", 25, 0, 200);
347 hPi0ConversionDistanceCut->Sumw2();
348 hPi0ConversionSeparationCut =
new TH1D(
349 "Pi0ConversionSeparationCut",
";True Separation from Vertex (cm);Efficiency", 25, 0, 200);
350 hPi0ConversionSeparationCut->Sumw2();
351 hNumHitsCompleteness =
352 new TH2D(
"NumHitsCompleteness",
";Completeness;Size of Cluster", 101, 0, 1.01, 100, 0, 100);
354 new TH2D(
"NumHitsEnergy",
";True Energy (GeV);Size of Cluster", 100, 0, 2, 100, 0, 100);
361 const art::FindManyP<recob::Hit>& fmh,
366 for (
unsigned int tpc = 0; tpc < geometry->NTPC(0); ++tpc) {
367 for (
unsigned int plane = 0; plane < geometry->Nplanes(tpc, 0); ++plane) {
368 clusterMap[tpc][plane] = (std::unique_ptr<ClusterCounter>)
new ClusterCounter(tpc, plane);
373 for (
size_t hitIt = 0; hitIt < hits.size(); ++hitIt) {
375 TrackID trackID = FindTrackID(clockData, hit);
380 trueParticles.clear();
381 const sim::ParticleList& particles = pi_serv->ParticleList();
383 particleIt != particles.end();
390 for (
size_t clusIt = 0; clusIt < clusters.size(); ++clusIt) {
393 unsigned int tpc = clusters.at(clusIt)->Plane().TPC % 2;
394 unsigned int plane = clusters.at(clusIt)->Plane().Plane;
398 if (clusterMap[tpc][plane]->GetNumberHitsInPlane() < minHits)
continue;
401 std::vector<art::Ptr<recob::Hit>> clusterHits = fmh.at(clusIt);
403 if (clusterHits.size() < 10)
continue;
406 TrackID trueTrackID = FindTrueTrack(clockData, clusterHits);
409 clusterMap[tpc][plane]->AssociateClusterAndTrack(
id, trueTrackID);
411 clusHitIt != clusterHits.end();
414 TrackID trackID = FindTrackID(clockData, hit);
415 if (trackID == trueTrackID)
416 clusterMap[tpc][plane]->AddSignalHitPostClustering(
id);
418 clusterMap[tpc][plane]->AddNoiseHitPostClustering(
id);
422 this->MakeHistograms();
429 double particleEnergy = 0;
431 std::vector<sim::TrackIDE> trackIDs = bt_serv->HitToTrackIDEs(clockData, hit);
432 for (
unsigned int idIt = 0; idIt < trackIDs.size(); ++idIt) {
433 if (trackIDs.at(idIt).energy > particleEnergy) {
434 particleEnergy = trackIDs.at(idIt).energy;
435 likelyTrackID = (
TrackID)TMath::Abs(trackIDs.at(idIt).trackID);
438 return likelyTrackID;
445 std::map<TrackID, double> trackMap;
447 clusHitIt != clusterHits.end();
450 TrackID trackID = FindTrackID(clockData, hit);
451 trackMap[trackID] += hit->
Integral();
454 double highestCharge = 0;
458 if (trackIt->second > highestCharge) {
459 highestCharge = trackIt->second;
460 clusterTrack = trackIt->first;
473 (180 / TMath::Pi()));
482 particleIt != trueParticles.end();
484 if (particleIt->second->PdgCode() == 111) pi0 = particleIt->second;
493 trueParticles.at(id1)->EndPosition().X() - trueParticles.at(id2)->EndPosition().X(), 2) +
495 trueParticles.at(id1)->EndPosition().Y() - trueParticles.at(id2)->EndPosition().Y(), 2) +
497 trueParticles.at(id1)->EndPosition().Z() - trueParticles.at(id2)->EndPosition().Z(), 2));
505 hEfficiencyEnergy =
new TEfficiency(*hPi0EnergyCut, *hPi0Energy);
506 hEfficiencyAngle =
new TEfficiency(*hPi0AngleCut, *hPi0Angle);
507 hEfficiencyConversionDistance =
508 new TEfficiency(*hPi0ConversionDistanceCut, *hPi0ConversionDistance);
509 hEfficiencyConversionSeparation =
510 new TEfficiency(*hPi0ConversionSeparationCut, *hPi0ConversionSeparation);
512 hEfficiencyEnergy->SetName(
"EfficiencyEnergy");
513 hEfficiencyAngle->SetName(
"EnergyAngle");
514 hEfficiencyConversionDistance->SetName(
"EfficiencyConversionDistance");
515 hEfficiencyConversionSeparation->SetName(
"EfficiencyConversionSeparation");
518 fHistArray.Add(hCompleteness);
519 fHistArray.Add(hCompletenessEnergy);
520 fHistArray.Add(hCompletenessAngle);
521 fHistArray.Add(hCompletenessConversionDistance);
522 fHistArray.Add(hCompletenessConversionSeparation);
523 fHistArray.Add(hCleanliness);
524 fHistArray.Add(hCleanlinessEnergy);
525 fHistArray.Add(hCleanlinessAngle);
526 fHistArray.Add(hCleanlinessConversionDistance);
527 fHistArray.Add(hCleanlinessConversionSeparation);
528 fHistArray.Add(hComplCleanl);
529 fHistArray.Add(hComplCleanlEnergy);
530 fHistArray.Add(hComplCleanlAngle);
531 fHistArray.Add(hComplCleanlConversionDistance);
532 fHistArray.Add(hComplCleanlConversionSeparation);
533 fHistArray.Add(hEfficiencyEnergy);
534 fHistArray.Add(hEfficiencyAngle);
535 fHistArray.Add(hEfficiencyConversionDistance);
536 fHistArray.Add(hEfficiencyConversionSeparation);
537 fHistArray.Add(hNumHitsCompleteness);
538 fHistArray.Add(hNumHitsEnergy);
548 for (
unsigned int tpc = 0; tpc < geometry->NTPC(0); ++tpc) {
549 for (
unsigned int plane = 0; plane < geometry->Nplanes(tpc, 0); ++plane) {
551 ClusterIDs clusterIDs = clusterMap[tpc][plane]->GetListOfClusterIDs();
554 if (clusterMap[tpc][plane]->GetPhotons().
size() == 2) {
555 hPi0Angle->Fill(FindPhotonAngle());
556 hPi0Energy->Fill(GetPi0()->
Momentum().
E());
557 hPi0ConversionDistance->Fill(
558 std::min(GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first,
560 GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(1).first,
561 (
TrackID)GetPi0()->TrackId())));
562 hPi0ConversionSeparation->Fill(
563 GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first,
564 clusterMap[tpc][plane]->GetPhotons().at(1).first));
565 if (clusterMap[tpc][plane]->PassesCut()) {
566 hPi0AngleCut->Fill(FindPhotonAngle());
567 hPi0EnergyCut->Fill(GetPi0()->
Momentum().
E());
568 hPi0ConversionDistanceCut->Fill(
569 std::min(GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first,
571 GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(1).first,
572 (
TrackID)GetPi0()->TrackId())));
573 hPi0ConversionSeparationCut->Fill(
574 GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first,
575 clusterMap[tpc][plane]->GetPhotons().at(1).first));
578 std::cout <<
"TPC " << tpc <<
", Plane " << plane <<
" fails the cut" <<
std::endl;
585 double completeness = clusterMap[tpc][plane]->GetCompleteness(clusID);
586 double cleanliness = clusterMap[tpc][plane]->GetCleanliness(clusID);
587 int numClusterHits = clusterMap[tpc][plane]->GetNumberHitsInCluster(clusID);
590 hCompleteness->Fill(completeness, numClusterHits);
591 hCleanliness->Fill(cleanliness, numClusterHits);
592 hComplCleanl->Fill(completeness * cleanliness, numClusterHits);
593 hNumHitsCompleteness->Fill(completeness, numClusterHits);
596 if (clusterMap[tpc][plane]->IsNoise(clusID))
continue;
598 double pi0Energy = GetPi0()->Momentum().E();
599 double pi0DecayAngle = FindPhotonAngle();
600 double conversionDistance = GetEndTrackDistance(clusterMap[tpc][plane]->GetTrack(clusID),
603 hCompletenessEnergy->Fill(pi0Energy, completeness, numClusterHits);
604 hCompletenessAngle->Fill(pi0DecayAngle, completeness, numClusterHits);
605 hCompletenessConversionDistance->Fill(conversionDistance, completeness, numClusterHits);
606 hCleanlinessEnergy->Fill(pi0Energy, cleanliness, numClusterHits);
607 hCleanlinessAngle->Fill(pi0DecayAngle, cleanliness, numClusterHits);
608 hCleanlinessConversionDistance->Fill(conversionDistance, cleanliness, numClusterHits);
609 hComplCleanlEnergy->Fill(pi0Energy, cleanliness * completeness, numClusterHits);
610 hComplCleanlAngle->Fill(pi0DecayAngle, cleanliness * completeness, numClusterHits);
611 hComplCleanlConversionDistance->Fill(
612 conversionDistance, cleanliness * completeness, numClusterHits);
613 hNumHitsEnergy->Fill(pi0Energy, numClusterHits);
616 if (clusterMap[tpc][plane]->GetPhotons().
size() != 2)
continue;
618 double conversionSeparation =
619 GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first,
620 clusterMap[tpc][plane]->GetPhotons().at(1).first);
622 hCompletenessConversionSeparation->Fill(conversionSeparation, completeness, numClusterHits);
623 hCleanlinessConversionSeparation->Fill(conversionSeparation, cleanliness, numClusterHits);
634 double avCompleteness = hCompleteness->GetMean();
635 double avCleanliness = hCleanliness->GetMean();
638 std::ofstream
outFile(
"effpur");
639 outFile << avCompleteness <<
" " << avCleanliness;
671 fMinHitsInPlane = pset.
get<
int>(
"MinHitsInPlane");
672 fClusterModuleLabels = pset.
get<std::vector<std::string>>(
"ClusterModuleLabels");
675 fCanvas =
new TCanvas(
"fCanvas",
"", 800, 600);
676 gStyle->SetOptStat(0);
684 std::vector<art::Ptr<recob::Hit>> hits;
689 for (
auto clustering : fClusterModuleLabels) {
693 std::vector<art::Ptr<recob::Cluster>> clusters;
697 art::FindManyP<recob::Hit> fmh(clusterHandle, evt, clustering);
701 clusterAnalysis.at(clustering)->Analyse(clockData, hits, clusters, fmh, fMinHitsInPlane);
711 for (
auto clustering : fClusterModuleLabels)
712 clusterAnalysis[clustering] = (std::unique_ptr<ClusterAnalyser>)
new ClusterAnalyser(clustering);
720 std::map<std::string, TObjArray> allHistograms;
721 for (
auto clustering : fClusterModuleLabels)
722 allHistograms[clustering] = clusterAnalysis.at(clustering)->GetHistograms();
725 TFile*
file = TFile::Open(
"validationHistograms.root",
"RECREATE");
726 for (
auto clustering : fClusterModuleLabels) {
728 file->mkdir(clustering.c_str());
729 file->cd(clustering.c_str());
730 for (
int histIt = 0; histIt < allHistograms.begin()->second.GetEntriesFast(); ++histIt)
731 allHistograms.at(clustering).At(histIt)->Write();
735 for (
int histIt = 0; histIt < allHistograms.begin()->second.GetEntriesFast(); ++histIt) {
738 const char*
name = allHistograms.begin()->second.At(histIt)->GetName();
739 TLegend*
l =
new TLegend(0.6, 0.8, 0.8, 0.9, name,
"brNDC");
742 clusteringIt != allHistograms.end();
743 ++clusteringIt, ++clusterings) {
744 TH1*
h = (TH1*)allHistograms.at(clusteringIt->first).At(histIt);
745 h->SetLineColor(clusterings);
746 h->SetMarkerColor(clusterings);
747 if (clusterings == 1)
751 l->AddEntry(h, clusteringIt->first.c_str(),
"lp");
756 fCanvas->Write(name);
762 if (clusterAnalysis.find(
"blurredclusteringdc") != clusterAnalysis.end())
763 clusterAnalysis.at(
"blurredclusteringdc")->WriteFile();
void AddHitPreClustering(TrackID id)
def analyze(root, level, gtrees, gbranches, doprint)
art::ServiceHandle< cheat::BackTrackerService const > bt_serv
int GetNumberHitsFromTrack(TrackID id)
bool IsNoise(ClusterID id)
std::map< ClusterID, int > numNoiseHitsPostClustering
double GetCompleteness(ClusterID id)
TProfile * hComplCleanlEnergy
void cluster(In first, In last, Out result, Pred *pred)
std::string fClusterLabel
art::ServiceHandle< cheat::BackTrackerService const > bt_serv
ClusteringValidation(fhicl::ParameterSet const &p)
std::vector< TrackID > TrackIDs
geo::WireID WireID() const
art::ServiceHandle< geo::Geometry const > geometry
double GetEndTrackDistance(TrackID id1, TrackID id2)
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
double GetEfficiency(TrackID id)
std::map< TrackID, ClusterIDs > trackToClusterIDs
std::map< TrackID, std::map< std::string, double > > particleProperties
std::string fHitsModuleLabel
Cluster finding and building.
std::map< TrackID, int > numHitsPreClustering
TrackIDs GetListOfTrackIDs()
int NumberDaughters() const
ClusterAnalyser(std::string &label)
art framework interface to geometry description
ClusterCounter(unsigned int &tpc, unsigned int &plane)
int Daughter(const int i) const
std::map< ClusterID, int > numSignalHitsPostClustering
int GetNumberHitsInPlane()
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
void AddNoiseHitPostClustering(ClusterID id)
TrackID FindTrackID(detinfo::DetectorClocksData const &clockData, art::Ptr< recob::Hit > &hit)
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
#define DEFINE_ART_MODULE(klass)
std::vector< std::pair< TrackID, ClusterIDs > > GetPhotons()
T get(std::string const &key) const
art::ServiceHandle< cheat::ParticleInventoryService const > pi_serv
TrackID FindTrueTrack(detinfo::DetectorClocksData const &clockData, std::vector< art::Ptr< recob::Hit >> &clusterHits)
std::vector< ClusterID > ClusterIDs
void AddSignalHitPostClustering(ClusterID id)
PlaneID_t Plane
Index of the plane within its TPC.
TEfficiency * hEfficiencyEnergy
std::map< unsigned int, std::map< unsigned int, std::unique_ptr< ClusterCounter > > > clusterMap
Detector simulation of raw signals on wires.
TProfile * hCleanlinessEnergy
std::vector< std::string > fClusterModuleLabels
TProfile * hCompletenessEnergy
double GetCleanliness(ClusterID id)
const simb::MCParticle * GetPi0()
Declaration of signal hit object.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
std::map< TrackID, const simb::MCParticle * > trueParticles
Contains all timing reference information for the detector.
TrackID GetTrack(ClusterID id)
std::map< TrackID, simb::MCParticle > trueParticles
void AssociateClusterAndTrack(ClusterID clusID, TrackID trackID)
TObjArray GetHistograms()
void analyze(art::Event const &evt)
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
TPCID_t TPC
Index of the TPC within its cryostat.
void Analyse(detinfo::DetectorClocksData const &clockData, std::vector< art::Ptr< recob::Hit >> &hits, std::vector< art::Ptr< recob::Cluster >> &clusters, const art::FindManyP< recob::Hit > &fmh, int numHits)
second_as<> second
Type of time stored in seconds, in double precision.
std::map< ClusterID, TrackID > clusterToTrackID
ClusterIDs GetListOfClusterIDs()
QTextStream & endl(QTextStream &s)
std::map< std::string, std::unique_ptr< ClusterAnalyser > > clusterAnalysis
int GetNumberHitsInCluster(ClusterID id)
art::ServiceHandle< cheat::ParticleInventoryService > pi_serv
art::ServiceHandle< geo::Geometry const > geometry