LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
ClusteringValidation_module.cc
Go to the documentation of this file.
1 // Class: ClusteringValidation
3 // Module type: analyser
4 // File: ClusteringValidation_module.cc
5 // Author: Mike Wallbank (m.wallbank@sheffied.ac.uk), May 2015
6 //
7 // A module to validate clustering algorithms.
8 // Compares the output of different clustering algorithms run over a pi0 sample.
9 //
10 // Usage: Specify the hit finder (HitsModuleLabel) and the clustering outputs
11 // to validate (ClusterModuleLabels) in the fhicl file.
12 // Module will make validation plots for all clusterings specified and also
13 // produce comparison plots. Number of clusterings to analyse can be one or more.
14 // Saves everything in the file validationHistograms.root.
16 
20 #include "fhiclcpp/ParameterSet.h"
29 
30 // LArSoft includes
45 
46 // ROOT & STL includes
47 #include "TTree.h"
48 #include "TTimeStamp.h"
49 #include "TLorentzVector.h"
50 #include "TH2F.h"
51 #include "TFile.h"
52 #include "TH1.h"
53 #include "TCanvas.h"
54 #include "TProfile.h"
55 #include "TEfficiency.h"
56 #include "TLegend.h"
57 #include "TFolder.h"
58 #include "TStyle.h"
59 
60 #include <map>
61 #include <iostream>
62 #include <algorithm>
63 #include <iostream>
64 #include <fstream>
65 
68  class ClusterAnalyser;
69  class ClusterCounter;
70 }
71 
72 enum class ClusterID : int { };
73 enum class TrackID : int { };
74 typedef std::vector<ClusterID> ClusterIDs;
75 typedef std::vector<TrackID> TrackIDs;
76 
78 public:
79 
80  explicit ClusterCounter(unsigned int &tpc, unsigned int &plane);
81 
82  void AddHitPreClustering (TrackID id);
83  void AddSignalHitPostClustering(ClusterID id);
84  void AddNoiseHitPostClustering (ClusterID id);
85  void AssociateClusterAndTrack (ClusterID clusID, TrackID trackID);
86  double GetCompleteness (ClusterID id);
87  double GetCleanliness (ClusterID id);
88  double GetEfficiency (TrackID id);
89  ClusterIDs GetListOfClusterIDs ();
90  TrackIDs GetListOfTrackIDs ();
91  int GetNumberHitsFromTrack (TrackID id);
92  int GetNumberHitsInCluster (ClusterID id);
93  int GetNumberHitsInPlane ();
94  std::vector<std::pair<TrackID,ClusterIDs> > GetPhotons ();
95  TrackID GetTrack (ClusterID id);
96  bool IsNoise (ClusterID id);
97  bool IsNoise (TrackID id);
98  bool PassesCut ();
99 
100 private:
101 
102  unsigned int tpc, plane;
103 
104  std::map<TrackID,int> numHitsPreClustering;
105  std::map<ClusterID,int> numSignalHitsPostClustering;
106  std::map<ClusterID,int> numNoiseHitsPostClustering;
107  std::map<ClusterID,TrackID> clusterToTrackID;
108  std::map<TrackID,ClusterIDs> trackToClusterIDs;
109  std::map<TrackID,std::map<std::string,double> > particleProperties;
110  std::map<TrackID,simb::MCParticle> trueParticles;
111 
115 
116 };
117 
118 ClusteringValidation::ClusterCounter::ClusterCounter(unsigned int &t, unsigned int &p) {
119  tpc = t;
120  plane = p;
121 }
122 
123 void ClusteringValidation::ClusterCounter::AddHitPreClustering(TrackID trackID) { ++numHitsPreClustering[trackID]; }
124 
125 void ClusteringValidation::ClusterCounter::AddSignalHitPostClustering(ClusterID clusID) { ++numSignalHitsPostClustering[clusID]; }
126 
127 void ClusteringValidation::ClusterCounter::AddNoiseHitPostClustering(ClusterID clusID) { ++numNoiseHitsPostClustering[clusID]; }
128 
129 void ClusteringValidation::ClusterCounter::AssociateClusterAndTrack(ClusterID clusID, TrackID trackID) { clusterToTrackID[clusID] = trackID; trackToClusterIDs[trackID].push_back(clusID); }
130 
131 double ClusteringValidation::ClusterCounter::GetCompleteness(ClusterID clusID) { return (double)numSignalHitsPostClustering[clusID]/(double)numHitsPreClustering[clusterToTrackID[clusID]]; }
132 
133 double ClusteringValidation::ClusterCounter::GetCleanliness(ClusterID clusID) { return (double)numSignalHitsPostClustering[clusID]/(double)(GetNumberHitsInCluster(clusID)); }
134 
135 double ClusteringValidation::ClusterCounter::GetEfficiency(TrackID trackID) { return 1/(double)trackToClusterIDs.at(trackID).size(); }
136 
137 int ClusteringValidation::ClusterCounter::GetNumberHitsFromTrack(TrackID trackID) { return numHitsPreClustering[trackID]; }
138 
139 int ClusteringValidation::ClusterCounter::GetNumberHitsInCluster(ClusterID clusID) { return numSignalHitsPostClustering[clusID] + numNoiseHitsPostClustering[clusID]; }
140 
141 int ClusteringValidation::ClusterCounter::GetNumberHitsInPlane() { int nHits = 0; for (auto &trackHits : numHitsPreClustering) nHits += trackHits.second; return nHits; }
142 
143 ClusterIDs ClusteringValidation::ClusterCounter::GetListOfClusterIDs() { ClusterIDs v; for (std::map<ClusterID,TrackID>::iterator i = clusterToTrackID.begin(); i != clusterToTrackID.end(); i++) v.push_back(i->first); return v; }
144 
145 TrackIDs ClusteringValidation::ClusterCounter::GetListOfTrackIDs() { TrackIDs v; for (std::map<TrackID,ClusterIDs>::iterator i = trackToClusterIDs.begin(); i != trackToClusterIDs.end(); i++) v.push_back(i->first); return v; }
146 
147 std::vector<std::pair<TrackID,ClusterIDs> > ClusteringValidation::ClusterCounter::GetPhotons() {
148  std::vector<std::pair<TrackID,ClusterIDs> > photonVector;
149  for (unsigned int track = 0; track < GetListOfTrackIDs().size(); ++track)
150  if (!IsNoise(GetListOfTrackIDs().at(track)) && pi_serv->TrackIdToParticle_P((int)GetListOfTrackIDs().at(track))->PdgCode() == 22)
151  photonVector.push_back(std::pair<TrackID,ClusterIDs>(GetListOfTrackIDs().at(track),trackToClusterIDs.at(GetListOfTrackIDs().at(track))));
152  return photonVector;
153 }
154 
155 TrackID ClusteringValidation::ClusterCounter::GetTrack(ClusterID id) { return clusterToTrackID.at(id); }
156 
157 bool ClusteringValidation::ClusterCounter::IsNoise(ClusterID clusID) { return IsNoise(clusterToTrackID.at(clusID)); }
158 
159 bool ClusteringValidation::ClusterCounter::IsNoise(TrackID trackID) { return (int)trackID == 0 ? true : false; }
160 
162  if (GetPhotons().size() > 2 || GetPhotons().size() == 0) return false;
163  TrackIDs goodPhotons;
164  for (unsigned int photon = 0; photon < GetPhotons().size(); ++photon)
165  for (unsigned int cluster = 0; cluster < GetPhotons().at(photon).second.size(); ++cluster)
166  if (GetCompleteness(GetPhotons().at(photon).second.at(cluster)) > 0.5) goodPhotons.push_back(GetPhotons().at(photon).first);
167  if ( (GetPhotons().size() == 2 && goodPhotons.size() > 2) || (GetPhotons().size() == 1 && goodPhotons.size() > 1) ) std::cout << "More than 2 with >50%?!" << std::endl;
168  bool pass = ( (GetPhotons().size() == 2 && goodPhotons.size() == 2) || (GetPhotons().size() == 1 && goodPhotons.size() == 1) );
169  return pass;
170 }
171 
172 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
174 public:
175 
176  explicit ClusterAnalyser(std::string &label);
177 
178  void Analyse(std::vector<art::Ptr<recob::Hit> > &hits, std::vector<art::Ptr<recob::Cluster> > &clusters, const art::FindManyP<recob::Hit> &fmh, int numHits);
179  TrackID FindTrackID(art::Ptr<recob::Hit> &hit);
180  TrackID FindTrueTrack(std::vector<art::Ptr<recob::Hit> > &clusterHits);
181  double FindPhotonAngle();
182  double GetEndTrackDistance(TrackID id1, TrackID id2);
183  const simb::MCParticle* GetPi0();
184  TObjArray GetHistograms();
185  void MakeHistograms();
186  void WriteFile();
187 
188 private:
189 
190  // Clustering properties
191  std::string fClusterLabel;
192 
193  // hists
194  TH1 *hCompleteness, *hCleanliness, *hComplCleanl;
195  TH1 *hPi0Angle, *hPi0Energy, *hPi0ConversionDistance, *hPi0ConversionSeparation, *hPi0AngleCut, *hPi0EnergyCut, *hPi0ConversionDistanceCut, *hPi0ConversionSeparationCut;
196  TH2 *hNumHitsCompleteness, *hNumHitsEnergy;
197  TProfile *hCompletenessEnergy, *hCompletenessAngle, *hCompletenessConversionDistance, *hCompletenessConversionSeparation;
198  TProfile *hCleanlinessEnergy, *hCleanlinessAngle, *hCleanlinessConversionDistance, *hCleanlinessConversionSeparation;
199  TProfile *hComplCleanlEnergy, *hComplCleanlAngle, *hComplCleanlConversionDistance, *hComplCleanlConversionSeparation;
200  TEfficiency *hEfficiencyAngle, *hEfficiencyEnergy, *hEfficiencyConversionDistance, *hEfficiencyConversionSeparation;
201  TObjArray fHistArray;
202 
203  std::map<unsigned int,std::map<unsigned int,std::unique_ptr<ClusterCounter> > > clusterMap;
204  std::map<TrackID,const simb::MCParticle*> trueParticles;
205 
206  // Services
210 
211 };
212 
214 
215  fClusterLabel = clusterLabel;
216 
217  // Make the histograms
218  hCompleteness = new TH1D("Completeness",";Completeness;",101,0,1.01);
219  hCompletenessEnergy = new TProfile("CompletenessEnergy",";True Energy (GeV);Completeness",100,0,2);
220  hCompletenessAngle = new TProfile("CompletenessAngle",";True Angle (deg);Completeness;",100,0,180);
221  hCompletenessConversionDistance = new TProfile("CompletenessConversionDistance",";True Distance from Vertex (cm);Completeness",100,0,200);
222  hCompletenessConversionSeparation = new TProfile("CompletenessConversionSeparation",";True Conversion Separation (cm);Completeness",100,0,200);
223  hCleanliness = new TH1D("Cleanliness",";Cleanliness;",101,0,1.01);
224  hCleanlinessEnergy = new TProfile("CleanlinessEnergy",";True Energy (GeV);Cleanliness",100,0,2);
225  hCleanlinessAngle = new TProfile("CleanlinessAngle",";True Angle (deg);Cleanliness;",100,0,180);
226  hCleanlinessConversionDistance = new TProfile("CleanlinessConversionDistance",";True Distance from Vertex (cm);Cleanliness",100,0,200);
227  hCleanlinessConversionSeparation = new TProfile("CleanlinessConversionSeparation",";True Conversion Separation (cm);Cleanliness",100,0,200);
228  hComplCleanl = new TH1D("CompletenessCleanliness",";Completeness * Cleanliness;",101,0,1.01);
229  hComplCleanlEnergy = new TProfile("CompletenessCleanlinessEnergy",";True Energy (GeV);Completeness * Cleanliness",100,0,2);
230  hComplCleanlAngle = new TProfile("CompletenessCleanlinessAngle",";True Angle (deg);Completeness * Cleanliness;",100,0,180);
231  hComplCleanlConversionDistance = new TProfile("CompletenessCleanlinessConversionDistance",";True Distance from Vertex (cm);Completeness * Cleanliness",100,0,200);
232  hComplCleanlConversionSeparation = new TProfile("CompletenessCleanlinessConversionSeparation",";True Conversion Separation (cm);Completeness * Cleanliness",100,0,200);
233  hPi0Energy = new TH1D("Pi0EnergyCut",";True Energy (GeV);",25,0,2); hPi0Energy ->Sumw2();
234  hPi0Angle = new TH1D("Pi0AngleCut",";True Angle (deg);",25,0,180); hPi0Angle ->Sumw2();
235  hPi0ConversionDistance = new TH1D("Pi0ConversionDistanceCut",";True Distance from Vertex (cm);",25,0,200); hPi0ConversionDistance ->Sumw2();
236  hPi0ConversionSeparation = new TH1D("Pi0ConversionSeparationCut",";True Separation from Vertex (cm);",25,0,200); hPi0ConversionSeparation ->Sumw2();
237  hPi0EnergyCut = new TH1D("Pi0EnergyCut",";True Energy (GeV);Efficiency",25,0,2); hPi0EnergyCut ->Sumw2();
238  hPi0AngleCut = new TH1D("Pi0AngleCut",";True Angle (deg);Efficiency",25,0,180); hPi0AngleCut ->Sumw2();
239  hPi0ConversionDistanceCut = new TH1D("Pi0ConversionDistanceCut",";True Distance from Vertex (cm);Efficiency",25,0,200); hPi0ConversionDistanceCut ->Sumw2();
240  hPi0ConversionSeparationCut = new TH1D("Pi0ConversionSeparationCut",";True Separation from Vertex (cm);Efficiency",25,0,200); hPi0ConversionSeparationCut->Sumw2();
241  hNumHitsCompleteness = new TH2D("NumHitsCompleteness",";Completeness;Size of Cluster",101,0,1.01,100,0,100);
242  hNumHitsEnergy = new TH2D("NumHitsEnergy",";True Energy (GeV);Size of Cluster",100,0,2,100,0,100);
243 
244 }
245 
247 
248  // Make a map of cluster counters in TPC/plane space
249  for (unsigned int tpc = 0; tpc < geometry->NTPC(0); ++tpc) {
250  for (unsigned int plane = 0; plane < geometry->Nplanes(tpc,0); ++plane) {
251  clusterMap[tpc][plane] = (std::unique_ptr<ClusterCounter>) new ClusterCounter(tpc, plane);
252  }
253  }
254 
255  // Save preclustered hits
256  for (size_t hitIt = 0; hitIt < hits.size(); ++hitIt) {
257  art::Ptr<recob::Hit> hit = hits.at(hitIt);
258  TrackID trackID = FindTrackID(hit);
259  clusterMap[hit->WireID().TPC%2][hit->WireID().Plane]->AddHitPreClustering(trackID);
260  }
261 
262  // Save true tracks
263  trueParticles.clear();
264  const sim::ParticleList& particles = pi_serv->ParticleList();
265  for (sim::ParticleList::const_iterator particleIt = particles.begin(); particleIt != particles.end(); ++particleIt) {
266  const simb::MCParticle *particle = particleIt->second;
267  trueParticles[(TrackID)particle->TrackId()] = particle;
268  }
269 
270  // Save the clustered hits
271  for (size_t clusIt = 0; clusIt < clusters.size(); ++clusIt) {
272 
273  // Get cluster information
274  unsigned int tpc = clusters.at(clusIt)->Plane().TPC%2;
275  unsigned int plane = clusters.at(clusIt)->Plane().Plane;
276  ClusterID id = (ClusterID)clusters.at(clusIt)->ID();
277 
278  // Only analyse planes with enough hits in to fairly represent the clustering
279  if (clusterMap[tpc][plane]->GetNumberHitsInPlane() < minHits) continue;
280 
281  // Get the hits from the cluster
282  std::vector<art::Ptr<recob::Hit> > clusterHits = fmh.at(clusIt);
283 
284  if (clusterHits.size() < 10) continue;
285 
286  // Find which track this cluster belongs to
287  TrackID trueTrackID = FindTrueTrack(clusterHits);
288 
289  // Save the info for this cluster
290  clusterMap[tpc][plane]->AssociateClusterAndTrack(id, trueTrackID);
291  for (std::vector<art::Ptr<recob::Hit> >::iterator clusHitIt = clusterHits.begin(); clusHitIt != clusterHits.end(); ++clusHitIt) {
292  art::Ptr<recob::Hit> hit = *clusHitIt;
293  TrackID trackID = FindTrackID(hit);
294  if (trackID == trueTrackID) clusterMap[tpc][plane]->AddSignalHitPostClustering(id);
295  else clusterMap[tpc][plane]->AddNoiseHitPostClustering (id);
296  }
297  }
298 
299  this->MakeHistograms();
300 
301 }
302 
304  double particleEnergy = 0;
305  TrackID likelyTrackID = (TrackID)0;
306  std::vector<sim::TrackIDE> trackIDs = bt_serv->HitToTrackIDEs(hit);
307  for (unsigned int idIt = 0; idIt < trackIDs.size(); ++idIt) {
308  if (trackIDs.at(idIt).energy > particleEnergy) {
309  particleEnergy = trackIDs.at(idIt).energy;
310  likelyTrackID = (TrackID)TMath::Abs(trackIDs.at(idIt).trackID);
311  }
312  }
313  return likelyTrackID;
314 }
315 
317  std::map<TrackID,double> trackMap;
318  for (std::vector<art::Ptr<recob::Hit> >::iterator clusHitIt = clusterHits.begin(); clusHitIt != clusterHits.end(); ++clusHitIt) {
319  art::Ptr<recob::Hit> hit = *clusHitIt;
320  TrackID trackID = FindTrackID(hit);
321  trackMap[trackID] += hit->Integral();
322  }
323  //return std::max_element(trackMap.begin(), trackMap.end(), [](const std::pair<int,double>& p1, const std::pair<int,double>& p2) {return p1.second < p2.second;} )->first;
324  double highestCharge = 0;
325  TrackID clusterTrack = (TrackID)0;
326  for (std::map<TrackID,double>::iterator trackIt = trackMap.begin(); trackIt != trackMap.end(); ++trackIt)
327  if (trackIt->second > highestCharge) {
328  highestCharge = trackIt->second;
329  clusterTrack = trackIt->first;
330  }
331  return clusterTrack;
332 }
333 
335  const simb::MCParticle* pi0 = GetPi0();
336  if (pi0->NumberDaughters() != 2) return -999;
337  double angle = (trueParticles.at((TrackID)pi0->Daughter(0))->Momentum().Angle(trueParticles.at((TrackID)pi0->Daughter(1))->Momentum().Vect()) * (180/TMath::Pi()));
338  return angle;
339 }
340 
342  const simb::MCParticle* pi0 = nullptr;
343  for (std::map<TrackID,const simb::MCParticle*>::iterator particleIt = trueParticles.begin(); particleIt != trueParticles.end(); ++particleIt)
344  if (particleIt->second->PdgCode() == 111)
345  pi0 = particleIt->second;
346  return pi0;
347 }
348 
350  return TMath::Sqrt(TMath::Power(trueParticles.at(id1)->EndPosition().X() - trueParticles.at(id2)->EndPosition().X(),2)+
351  TMath::Power(trueParticles.at(id1)->EndPosition().Y() - trueParticles.at(id2)->EndPosition().Y(),2)+
352  TMath::Power(trueParticles.at(id1)->EndPosition().Z() - trueParticles.at(id2)->EndPosition().Z(),2));
353 }
354 
356 
357  // Make efficiency histograms
358  hEfficiencyEnergy = new TEfficiency(*hPi0EnergyCut,*hPi0Energy);
359  hEfficiencyAngle = new TEfficiency(*hPi0AngleCut,*hPi0Angle);
360  hEfficiencyConversionDistance = new TEfficiency(*hPi0ConversionDistanceCut,*hPi0ConversionDistance);
361  hEfficiencyConversionSeparation = new TEfficiency(*hPi0ConversionSeparationCut,*hPi0ConversionSeparation);
362 
363  hEfficiencyEnergy ->SetName("EfficiencyEnergy");
364  hEfficiencyAngle ->SetName("EnergyAngle");
365  hEfficiencyConversionDistance ->SetName("EfficiencyConversionDistance");
366  hEfficiencyConversionSeparation->SetName("EfficiencyConversionSeparation");
367 
368  // Add all the histograms to the object array
369  fHistArray.Add(hCompleteness); fHistArray.Add(hCompletenessEnergy); fHistArray.Add(hCompletenessAngle); fHistArray.Add(hCompletenessConversionDistance); fHistArray.Add(hCompletenessConversionSeparation);
370  fHistArray.Add(hCleanliness); fHistArray.Add(hCleanlinessEnergy); fHistArray.Add(hCleanlinessAngle); fHistArray.Add(hCleanlinessConversionDistance); fHistArray.Add(hCleanlinessConversionSeparation);
371  fHistArray.Add(hComplCleanl); fHistArray.Add(hComplCleanlEnergy); fHistArray.Add(hComplCleanlAngle); fHistArray.Add(hComplCleanlConversionDistance); fHistArray.Add(hComplCleanlConversionSeparation);
372  fHistArray.Add(hEfficiencyEnergy); fHistArray.Add(hEfficiencyAngle); fHistArray.Add(hEfficiencyConversionDistance); fHistArray.Add(hEfficiencyConversionSeparation);
373  fHistArray.Add(hNumHitsCompleteness); fHistArray.Add(hNumHitsEnergy);
374 
375  return fHistArray;
376 }
377 
379 
380  // Loop over the tpcs and planes in the geometry
381  for (unsigned int tpc = 0; tpc < geometry->NTPC(0); ++tpc) {
382  for (unsigned int plane = 0; plane < geometry->Nplanes(tpc,0); ++plane) {
383 
384  ClusterIDs clusterIDs = clusterMap[tpc][plane]->GetListOfClusterIDs();
385 
386  // Fill histograms for the efficiency
387  if (clusterMap[tpc][plane]->GetPhotons().size() == 2) {
388  hPi0Angle ->Fill(FindPhotonAngle());
389  hPi0Energy ->Fill(GetPi0()->Momentum().E());
390  hPi0ConversionDistance ->Fill(std::min(GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first, (TrackID)GetPi0()->TrackId()),
391  GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(1).first, (TrackID)GetPi0()->TrackId())));
392  hPi0ConversionSeparation->Fill(GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first, clusterMap[tpc][plane]->GetPhotons().at(1).first));
393  if (clusterMap[tpc][plane]->PassesCut()) {
394  hPi0AngleCut ->Fill(FindPhotonAngle());
395  hPi0EnergyCut ->Fill(GetPi0()->Momentum().E());
396  hPi0ConversionDistanceCut ->Fill(std::min(GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first, (TrackID)GetPi0()->TrackId()),
397  GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(1).first, (TrackID)GetPi0()->TrackId())));
398  hPi0ConversionSeparationCut->Fill(GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first, clusterMap[tpc][plane]->GetPhotons().at(1).first));
399  }
400  else
401  std::cout << "TPC " << tpc << ", Plane " << plane << " fails the cut" << std::endl;
402  }
403 
404  // Look at all the clusters
405  for (unsigned int cluster = 0; cluster < clusterIDs.size(); ++cluster) {
406 
407  ClusterID clusID = clusterIDs.at(cluster);
408  double completeness = clusterMap[tpc][plane]->GetCompleteness(clusID);
409  double cleanliness = clusterMap[tpc][plane]->GetCleanliness(clusID);
410  int numClusterHits = clusterMap[tpc][plane]->GetNumberHitsInCluster(clusID);
411 
412  // Fill histograms for this cluster
413  hCompleteness ->Fill(completeness, numClusterHits);
414  hCleanliness ->Fill(cleanliness, numClusterHits);
415  hComplCleanl ->Fill(completeness*cleanliness, numClusterHits);
416  hNumHitsCompleteness ->Fill(completeness, numClusterHits);
417 
418  // Is this cluster doesn't correspond to a true particle continue
419  if (clusterMap[tpc][plane]->IsNoise(clusID)) continue;
420 
421  double pi0Energy = GetPi0()->Momentum().E();
422  double pi0DecayAngle = FindPhotonAngle();
423  double conversionDistance = GetEndTrackDistance(clusterMap[tpc][plane]->GetTrack(clusID), (TrackID)GetPi0()->TrackId());
424 
425  hCompletenessEnergy ->Fill(pi0Energy, completeness, numClusterHits);
426  hCompletenessAngle ->Fill(pi0DecayAngle, completeness, numClusterHits);
427  hCompletenessConversionDistance->Fill(conversionDistance, completeness, numClusterHits);
428  hCleanlinessEnergy ->Fill(pi0Energy, cleanliness, numClusterHits);
429  hCleanlinessAngle ->Fill(pi0DecayAngle, cleanliness, numClusterHits);
430  hCleanlinessConversionDistance ->Fill(conversionDistance, cleanliness, numClusterHits);
431  hComplCleanlEnergy ->Fill(pi0Energy, cleanliness * completeness, numClusterHits);
432  hComplCleanlAngle ->Fill(pi0DecayAngle, cleanliness * completeness, numClusterHits);
433  hComplCleanlConversionDistance ->Fill(conversionDistance, cleanliness * completeness, numClusterHits);
434  hNumHitsEnergy ->Fill(pi0Energy, numClusterHits);
435 
436  // Continue if there are not two photons in the view
437  if (clusterMap[tpc][plane]->GetPhotons().size() != 2) continue;
438 
439  double conversionSeparation = GetEndTrackDistance(clusterMap[tpc][plane]->GetPhotons().at(0).first, clusterMap[tpc][plane]->GetPhotons().at(1).first);
440 
441  hCompletenessConversionSeparation->Fill(conversionSeparation, completeness, numClusterHits);
442  hCleanlinessConversionSeparation ->Fill(conversionSeparation, cleanliness, numClusterHits);
443  }
444 
445  }
446  }
447 
448 }
449 
451 
452  // Average completeness/cleanliness
453  double avCompleteness = hCompleteness->GetMean();
454  double avCleanliness = hCleanliness ->GetMean();
455 
456  // Write file
457  std::ofstream outFile("effpur");
458  outFile << avCompleteness << " " << avCleanliness;
459  outFile.close();
460 
461 }
462 
463 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
465 public:
466 
467  explicit ClusteringValidation(fhicl::ParameterSet const &p);
468 
469  void analyze(art::Event const &evt);
470  void beginJob();
471  void endJob();
472  void reconfigure(fhicl::ParameterSet const &p);
473 
474 private:
475 
476  // Clusterings to compare and the hits which the clustering was run over
477  std::vector<std::string> fClusterModuleLabels;
478  std::string fHitsModuleLabel;
479 
480  // Minimum hits needed to analyse a plane
482 
483  // Canvas on which to save histograms
484  TCanvas *fCanvas;
485 
486  // The cluster analysers
487  // -- one for each clustering type being compared
488  std::map<std::string,std::unique_ptr<ClusterAnalyser> > clusterAnalysis;
489 
490 };
491 
493  this->reconfigure(pset);
494  fCanvas = new TCanvas("fCanvas","",800,600);
495  gStyle->SetOptStat(0);
496 }
497 
499  fMinHitsInPlane = p.get<int> ("MinHitsInPlane");
500  fClusterModuleLabels = p.get<std::vector<std::string> >("ClusterModuleLabels");
501  fHitsModuleLabel = p.get<std::string> ("HitsModuleLabel");
502 }
503 
505 {
506  // Get the hits from the event
508  std::vector<art::Ptr<recob::Hit> > hits;
509  if (evt.getByLabel(fHitsModuleLabel,hitHandle))
510  art::fill_ptr_vector(hits, hitHandle);
511 
512  // Get clustering information from event
513  // and give to the ClusterAnalyser to analyse
514  for (auto clustering : fClusterModuleLabels) {
515 
516  // Get the clusters from the event
518  std::vector<art::Ptr<recob::Cluster> > clusters;
519  if (evt.getByLabel(clustering,clusterHandle))
520  art::fill_ptr_vector(clusters, clusterHandle);
521 
522  // Find the associations (the hits) for the clusters
523  art::FindManyP<recob::Hit> fmh(clusterHandle,evt,clustering);
524 
525  // Analyse this particular clustering
526  clusterAnalysis.at(clustering)->Analyse(hits, clusters, fmh, fMinHitsInPlane);
527 
528  }
529 }
530 
532 
533  // Construct the cluster analysers here
534  // -- one for each of the clustering types to compare
535  for (auto clustering : fClusterModuleLabels)
536  clusterAnalysis[clustering] = (std::unique_ptr<ClusterAnalyser>) new ClusterAnalyser(clustering);
537 
538 }
539 
541 
542  // Make a map of all the histograms for each clustering
543  std::map<std::string,TObjArray> allHistograms;
544  for (auto clustering : fClusterModuleLabels)
545  allHistograms[clustering] = clusterAnalysis.at(clustering)->GetHistograms();
546 
547  // Write histograms to file
548  TFile *file = TFile::Open("validationHistograms.root","RECREATE");
549  for (auto clustering : fClusterModuleLabels) {
550  file->cd();
551  file->mkdir(clustering.c_str());
552  file->cd(clustering.c_str());
553  for (int histIt = 0; histIt < allHistograms.begin()->second.GetEntriesFast(); ++histIt)
554  allHistograms.at(clustering).At(histIt)->Write();
555  }
556 
557  // Write images of overlaid histograms
558  for (int histIt = 0; histIt < allHistograms.begin()->second.GetEntriesFast(); ++histIt) {
559  fCanvas->cd();
560  fCanvas->Clear();
561  const char *name = allHistograms.begin()->second.At(histIt)->GetName();
562  TLegend *l = new TLegend(0.6,0.8,0.8,0.9,name,"brNDC");
563  int clusterings = 1;
564  for (std::map<std::string,TObjArray>::iterator clusteringIt = allHistograms.begin(); clusteringIt != allHistograms.end(); ++clusteringIt, ++clusterings) {
565  TH1* h = (TH1*)allHistograms.at(clusteringIt->first).At(histIt);
566  h->SetLineColor(clusterings);
567  h->SetMarkerColor(clusterings);
568  if (clusterings == 1) h->Draw();
569  else h->Draw("same");
570  l->AddEntry(h,clusteringIt->first.c_str(),"lp");
571  }
572  l->Draw("same");
573  //fCanvas->SaveAs(name+TString(".png"));
574  file->cd();
575  fCanvas->Write(name);
576  }
577 
578  file->Close();
579  delete file;
580 
581  if (clusterAnalysis.find("blurredclusteringdc") != clusterAnalysis.end())
582  clusterAnalysis.at("blurredclusteringdc")->WriteFile();
583 
584 }
585 
Float_t E
Definition: plot.C:23
intermediate_table::iterator iterator
art::ServiceHandle< cheat::BackTrackerService > bt_serv
std::vector< TrackID > TrackIDs
geo::WireID WireID() const
Initial tdc tick for hit.
Definition: Hit.h:234
Declaration of signal hit object.
list_type::const_iterator const_iterator
Definition: ParticleList.h:132
std::map< TrackID, const simb::MCParticle * > trueParticles
double GetEndTrackDistance(TrackID id1, TrackID id2)
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
Definition: Hit.h:225
Cluster finding and building.
std::map< TrackID, simb::MCParticle > trueParticles
Particle class.
void Analyse(std::vector< art::Ptr< recob::Hit > > &hits, std::vector< art::Ptr< recob::Cluster > > &clusters, const art::FindManyP< recob::Hit > &fmh, int numHits)
int NumberDaughters() const
Definition: MCParticle.h:221
ClusterCounter(unsigned int &tpc, unsigned int &plane)
int TrackId() const
Definition: MCParticle.h:214
int Daughter(const int i) const
Definition: MCParticle.cxx:112
art::ServiceHandle< geo::Geometry > geometry
std::map< unsigned int, std::map< unsigned int, std::unique_ptr< ClusterCounter > > > clusterMap
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
void hits()
Definition: readHits.C:15
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
Provides recob::Track data product.
void beginJob()
Definition: Breakpoints.cc:14
std::map< TrackID, ClusterIDs > trackToClusterIDs
std::vector< std::pair< TrackID, ClusterIDs > > GetPhotons()
T get(std::string const &key) const
Definition: ParameterSet.h:231
art::ServiceHandle< cheat::BackTrackerService > bt_serv
std::map< ClusterID, int > numSignalHitsPostClustering
std::map< TrackID, std::map< std::string, double > > particleProperties
iterator begin()
Definition: ParticleList.h:305
std::vector< ClusterID > ClusterIDs
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
Declaration of cluster object.
Detector simulation of raw signals on wires.
Encapsulate the geometry of a wire.
art::ServiceHandle< geo::Geometry > geometry
TrackID FindTrackID(art::Ptr< recob::Hit > &hit)
Utility object to perform functions of association.
Encapsulate the construction of a single detector plane.
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
Int_t min
Definition: plot.C:26
TFile * file
void AssociateClusterAndTrack(ClusterID clusID, TrackID trackID)
std::map< ClusterID, TrackID > clusterToTrackID
TrackID FindTrueTrack(std::vector< art::Ptr< recob::Hit > > &clusterHits)
TCEvent evt
Definition: DataStructs.cxx:5
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:464
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
Float_t track
Definition: plot.C:34
std::map< std::string, std::unique_ptr< ClusterAnalyser > > clusterAnalysis
art framework interface to geometry description
art::ServiceHandle< cheat::ParticleInventoryService > pi_serv
art::ServiceHandle< cheat::ParticleInventoryService > pi_serv