All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRTHitCosmicIdAna_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: CRTHitCosmicIdAna
3 // Module Type: analyzer
4 // File: CRTHitCosmicIdAna_module.cc
5 //
6 // Tom Brooks (tbrooks@fnal.gov)
7 ////////////////////////////////////////////////////////////////////////
8 
9 // sbndcode includes
16 
17 // LArSoft includes
24 #include "nusimdata/SimulationBase/MCParticle.h"
25 
26 // Framework includes
27 #include "art/Framework/Core/EDAnalyzer.h"
28 #include "art/Framework/Principal/Event.h"
29 #include "art/Framework/Principal/Handle.h"
30 #include "art/Framework/Services/Registry/ServiceHandle.h"
31 #include "art_root_io/TFileService.h"
32 #include "canvas/Persistency/Common/FindManyP.h"
35 
36 // Utility libraries
37 #include "fhiclcpp/ParameterSet.h"
38 #include "fhiclcpp/types/Table.h"
39 #include "fhiclcpp/types/Atom.h"
40 
41 #include "Pandora/PdgTable.h"
42 
43 // ROOT includes. Note: To look up the properties of the ROOT classes,
44 // use the ROOT web site; e.g.,
45 // <https://root.cern.ch/doc/master/annotated.html>
46 #include "TH1.h"
47 #include "TVector3.h"
48 
49 // C++ includes
50 #include <map>
51 #include <vector>
52 #include <string>
53 
54 namespace sbnd {
55 
56  class CRTHitCosmicIdAna : public art::EDAnalyzer {
57  public:
58 
59  // Describes configuration parameters of the module
60  struct Config {
61  using Name = fhicl::Name;
62  using Comment = fhicl::Comment;
63 
64  // One Atom for each parameter
65  fhicl::Atom<art::InputTag> SimModuleLabel {
66  Name("SimModuleLabel"),
67  Comment("tag of detector simulation data product")
68  };
69 
70  fhicl::Atom<art::InputTag> CRTHitLabel {
71  Name("CRTHitLabel"),
72  Comment("tag of CRT hit producer data product")
73  };
74 
75  fhicl::Atom<art::InputTag> TPCTrackLabel {
76  Name("TPCTrackLabel"),
77  Comment("tag of tpc track producer data product")
78  };
79 
80  fhicl::Atom<art::InputTag> PandoraLabel {
81  Name("PandoraLabel"),
82  Comment("tag of pandora data product")
83  };
84 
85  fhicl::Atom<bool> Verbose {
86  Name("Verbose"),
87  Comment("Print information about what's going on")
88  };
89 
90  fhicl::Table<CRTT0MatchAlg::Config> CRTT0Alg {
91  Name("CRTT0Alg"),
92  };
93 
94  fhicl::Table<CRTBackTracker::Config> CrtBackTrack {
95  Name("CrtBackTrack"),
96  };
97 
98  fhicl::Table<CrtHitCosmicIdAlg::Config> CHTagAlg {
99  Name("CHTagAlg"),
100  };
101 
102  }; // Config
103 
104  using Parameters = art::EDAnalyzer::Table<Config>;
105 
106  // Constructor: configures module
107  explicit CRTHitCosmicIdAna(Parameters const& config);
108 
109  // Called once, at start of the job
110  virtual void beginJob() override;
111 
112  // Called once per event
113  virtual void analyze(const art::Event& event) override;
114 
115  // Called once, at end of the job
116  virtual void endJob() override;
117 
118  typedef art::Handle< std::vector<recob::PFParticle> > PFParticleHandle;
119  typedef std::map< size_t, art::Ptr<recob::PFParticle> > PFParticleIdMap;
120 
121  private:
122 
123  void GetPFParticleIdMap(const PFParticleHandle &pfParticleHandle, PFParticleIdMap &pfParticleMap);
124 
125  // fcl file parameters
126  art::InputTag fSimModuleLabel; ///< name of detsim producer
127  art::InputTag fCRTHitLabel; ///< name of CRT producer
128  art::InputTag fTPCTrackLabel; ///< name of CRT producer
129  art::InputTag fPandoraLabel;
130  bool fVerbose; ///< print information about what's going on
131 
133 
135 
138 
139  // Histograms
140  std::vector<std::string> types {"NuMuTrack", "CrTrack", "DirtTrack", "NuTrack", "NuMuPfp", "CrPfp", "DirtPfp", "NuPfp"};
141  std::map<std::string, TH1D*> hNumTrueMatches;
142  std::map<std::string, TH1D*> hMatchDCA;
143  std::map<std::string, TH1D*> hNoMatchDCA;
144  std::map<std::string, TH1D*> hDCATotal;
145  std::map<std::string, TH1D*> hDCATag;
146  std::map<std::string, TH1D*> hLengthTotal;
147  std::map<std::string, TH1D*> hLengthTag;
148 
149  }; // class CRTHitCosmicIdAna
150 
151 
152  // Constructor
154  : EDAnalyzer(config)
155  , fSimModuleLabel (config().SimModuleLabel())
156  , fCRTHitLabel (config().CRTHitLabel())
157  , fTPCTrackLabel (config().TPCTrackLabel())
158  , fPandoraLabel (config().PandoraLabel())
159  , fVerbose (config().Verbose())
160  , t0Alg (config().CRTT0Alg())
161  , fCrtBackTrack (config().CrtBackTrack())
162  , chTag (config().CHTagAlg())
163  {
164 
165  } //CRTHitCosmicIdAna()
166 
167 
169  {
170 
171  // Access tfileservice to handle creating and writing histograms
172  art::ServiceHandle<art::TFileService> tfs;
173  for(auto type : types){
174  hNumTrueMatches[type] = tfs->make<TH1D>(Form("%sNumTrueMatches", type.c_str()), "", 10, 0, 10);
175  hMatchDCA[type] = tfs->make<TH1D>(Form("%sMatchDCA", type.c_str()), "", 60, 0, 100);
176  hNoMatchDCA[type] = tfs->make<TH1D>(Form("%sNoMatchDCA", type.c_str()), "", 60, 0, 100);
177  hDCATotal[type] = tfs->make<TH1D>(Form("%sDCATotal", type.c_str()), "", 20, 0, 80);
178  hDCATag[type] = tfs->make<TH1D>(Form("%sDCATag", type.c_str()), "", 20, 0, 80);
179  hLengthTotal[type] = tfs->make<TH1D>(Form("%sLengthTotal", type.c_str()), "", 20, 0, 400);
180  hLengthTag[type] = tfs->make<TH1D>(Form("%sLengthTag", type.c_str()), "", 20, 0, 400);
181  }
182 
183  // Initial output
184  if(fVerbose) std::cout<<"----------------- CRT T0 Matching Ana Module -------------------"<<std::endl;
185 
186  } // CRTHitCosmicIdAna::beginJob()
187 
188 
189  void CRTHitCosmicIdAna::analyze(const art::Event& event)
190  {
191 
192  // Fetch basic event info
193  if(fVerbose){
194  std::cout<<"============================================"<<std::endl
195  <<"Run = "<<event.run()<<", SubRun = "<<event.subRun()<<", Event = "<<event.id().event()<<std::endl
196  <<"============================================"<<std::endl;
197  }
198 
199  //----------------------------------------------------------------------------------------------------------
200  // GETTING PRODUCTS
201  //----------------------------------------------------------------------------------------------------------
202 
203  // Get g4 particles
204  art::ServiceHandle<cheat::ParticleInventoryService> pi_serv;
205  auto particleHandle = event.getValidHandle<std::vector<simb::MCParticle>>(fSimModuleLabel);
206 
207  // Get CRT hits from the event
208  art::Handle< std::vector<sbn::crt::CRTHit>> crtHitHandle;
209  std::vector<art::Ptr<sbn::crt::CRTHit> > crtHitList;
210  if (event.getByLabel(fCRTHitLabel, crtHitHandle))
211  art::fill_ptr_vector(crtHitList, crtHitHandle);
212 
213  fCrtBackTrack.Initialize(event);
214  std::vector<sbn::crt::CRTHit> crtHits;
215  std::map<int, int> numHitMap;
216  int hit_i = 0;
217  for(auto const& hit : (crtHitList)){
218  crtHits.push_back(*hit);
219  int hitTrueID = fCrtBackTrack.TrueIdFromHitId(event, hit_i);
220  hit_i++;
221  double hitTime = hit->ts1_ns * 1e-3;
222  if(hitTime > 0 && hitTime < 4) continue;
223  numHitMap[hitTrueID]++;
224  }
225 
226  // Get reconstructed tracks from the event
227  auto tpcTrackHandle = event.getValidHandle<std::vector<recob::Track>>(fTPCTrackLabel);
228  art::FindManyP<recob::Hit> findManyHits(tpcTrackHandle, event, fTPCTrackLabel);
229 
230  // Get PFParticles from pandora
231  PFParticleHandle pfParticleHandle;
232  event.getByLabel(fPandoraLabel, pfParticleHandle);
233  if( !pfParticleHandle.isValid() ){
234  if(fVerbose) std::cout<<"Failed to find the PFParticles."<<std::endl;
235  return;
236  }
237  PFParticleIdMap pfParticleMap;
238  this->GetPFParticleIdMap(pfParticleHandle, pfParticleMap);
239  // Get PFParticle to track associations
240  art::FindManyP< recob::Track > pfPartToTrackAssoc(pfParticleHandle, event, fTPCTrackLabel);
241 
242  //----------------------------------------------------------------------------------------------------------
243  // TRUTH MATCHING
244  //----------------------------------------------------------------------------------------------------------
245 
246  std::map<int, simb::MCParticle> particles;
247  std::vector<int> nuParticleIds;
248  std::vector<int> lepParticleIds;
249  std::vector<int> dirtParticleIds;
250  std::vector<int> crParticleIds;
251  // Loop over the true particles
252  for (auto const& particle: (*particleHandle)){
253 
254  // Make map with ID
255  int partID = particle.TrackId();
256  particles[partID] = particle;
257 
258  // Get MCTruth
259  art::Ptr<simb::MCTruth> truth = pi_serv->TrackIdToMCTruth_P(partID);
260  int pdg = std::abs(particle.PdgCode());
261 
262  // If origin is a neutrino
263  if(truth->Origin() == simb::kBeamNeutrino){
264  geo::Point_t vtx;
265  vtx.SetX(truth->GetNeutrino().Nu().Vx()); vtx.SetY(truth->GetNeutrino().Nu().Vy()); vtx.SetZ(truth->GetNeutrino().Nu().Vz());
266  // If neutrino vertex is not inside the TPC then call it a dirt particle
267  if(!fTpcGeo.InFiducial(vtx, 0, 0)){
268  dirtParticleIds.push_back(partID);
269  }
270  // If it's a primary muon
271  else if(pdg==13 && particle.Mother()==0){
272  lepParticleIds.push_back(partID);
273  }
274  // Other nu particles
275  else{
276  nuParticleIds.push_back(partID);
277  }
278  }
279 
280  // If origin is a cosmic ray
281  else if(truth->Origin() == simb::kCosmicRay){
282  crParticleIds.push_back(partID);
283  }
284 
285  }
286 
287  //----------------------------------------------------------------------------------------------------------
288  // DISTANCE OF CLOSEST APPROACH ANALYSIS
289  //----------------------------------------------------------------------------------------------------------
290  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
291  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(event, clockData);
292 
293  // Loop over reconstructed tracks
294  for (auto const& tpcTrack : (*tpcTrackHandle)){
295  // Get the associated hits
296  std::vector<art::Ptr<recob::Hit>> hits = findManyHits.at(tpcTrack.ID());
297  int trackTrueID = RecoUtils::TrueParticleIDFromTotalRecoHits(clockData, hits, false);
298  std::string type = "none";
299  if(std::find(lepParticleIds.begin(), lepParticleIds.end(), trackTrueID) != lepParticleIds.end()) type = "NuMuTrack";
300  if(std::find(nuParticleIds.begin(), nuParticleIds.end(), trackTrueID) != nuParticleIds.end()) type = "NuTrack";
301  if(std::find(crParticleIds.begin(), crParticleIds.end(), trackTrueID) != crParticleIds.end()) type = "CrTrack";
302  if(std::find(dirtParticleIds.begin(), dirtParticleIds.end(), trackTrueID) != dirtParticleIds.end()) type = "DirtTrack";
303  if(type == "none") continue;
304 
305  // Calculate t0 from CRT Hit matching
306  std::pair<sbn::crt::CRTHit, double> closest = t0Alg.ClosestCRTHit(detProp, tpcTrack, crtHits, event);
307 
308  if(closest.second != -99999){
309  int hitTrueID = fCrtBackTrack.TrueIdFromTotalEnergy(event, closest.first);
310  if(hitTrueID == trackTrueID && hitTrueID != -99999){
311  hMatchDCA[type]->Fill(closest.second);
312  }
313  else{
314  hNoMatchDCA[type]->Fill(closest.second);
315  }
316  }
317 
318  if(numHitMap.find(trackTrueID) != numHitMap.end()){
319  hNumTrueMatches[type]->Fill(numHitMap[trackTrueID]);
320  }
321  else{
322  hNumTrueMatches[type]->Fill(0);
323  }
324 
325  int nbins = hDCATotal.begin()->second->GetNbinsX();
326  for(int i = 0; i < nbins; i++){
327  double DCAcut = hDCATotal.begin()->second->GetBinCenter(i);
328 
329  hDCATotal[type]->Fill(DCAcut);
330 
331  // If closest hit is below limit and track matches any hits then fill efficiency
332  if(closest.second < DCAcut && closest.second != -99999){
333  double hitTime = closest.first.ts1_ns * 1e-3;
334  if(hitTime > 0 && hitTime < 4) continue;
335  hDCATag[type]->Fill(DCAcut);
336  }
337 
338  }
339 
340  hLengthTotal[type]->Fill(tpcTrack.Length());
341  if(chTag.CrtHitCosmicId(detProp, tpcTrack, crtHits, event)){
342  hLengthTag[type]->Fill(tpcTrack.Length());
343  }
344  }
345 
346  //Loop over the pfparticle map
347  for (PFParticleIdMap::const_iterator it = pfParticleMap.begin(); it != pfParticleMap.end(); ++it){
348 
349  const art::Ptr<recob::PFParticle> pParticle(it->second);
350  // Only look for primary particles
351  if (!pParticle->IsPrimary()) continue;
352  // Check if this particle is identified as the neutrino
353  const int pdg(pParticle->PdgCode());
354  const bool isNeutrino(std::abs(pdg) == pandora::NU_E || std::abs(pdg) == pandora::NU_MU || std::abs(pdg) == pandora::NU_TAU);
355  //Find neutrino pfparticle
356  if(!isNeutrino) continue;
357 
358  std::string type = "none";
359  std::vector<recob::Track> nuTracks;
360 
361  // Loop over daughters of pfparticle
362  for (const size_t daughterId : pParticle->Daughters()){
363 
364  // Get tracks associated with daughter
365  art::Ptr<recob::PFParticle> pDaughter = pfParticleMap.at(daughterId);
366  const std::vector< art::Ptr<recob::Track> > associatedTracks(pfPartToTrackAssoc.at(pDaughter.key()));
367  if(associatedTracks.size() != 1) continue;
368 
369  // Get the first associated track
370  recob::Track tpcTrack = *associatedTracks.front();
371  nuTracks.push_back(tpcTrack);
372 
373  // Truth match muon tracks and pfps
374  std::vector<art::Ptr<recob::Hit>> hits = findManyHits.at(tpcTrack.ID());
375  int trueId = RecoUtils::TrueParticleIDFromTotalRecoHits(clockData, hits, false);
376  if(std::find(lepParticleIds.begin(), lepParticleIds.end(), trueId) != lepParticleIds.end()){
377  type = "NuMuPfp";
378  }
379  else if(std::find(nuParticleIds.begin(), nuParticleIds.end(), trueId) != nuParticleIds.end()){
380  if(type != "NuMuPfp") type = "NuPfp";
381  }
382  else if(std::find(dirtParticleIds.begin(), dirtParticleIds.end(), trueId) != dirtParticleIds.end()){
383  if(type != "NuMuPfp" && type != "NuPfp") type = "DirtPfp";
384  }
385  else if(std::find(crParticleIds.begin(), crParticleIds.end(), trueId) != crParticleIds.end()){
386  if(type != "NuMuPfp" && type != "NuPfp" && type != "DirtPfp") type = "CrPfp";
387  }
388  }
389 
390  if(nuTracks.size() == 0) continue;
391 
392  std::sort(nuTracks.begin(), nuTracks.end(), [](auto& left, auto& right){
393  return left.Length() > right.Length();});
394 
395  recob::Track tpcTrack = nuTracks[0];
396  std::vector<art::Ptr<recob::Hit>> hits = findManyHits.at(tpcTrack.ID());
397  int trackTrueID = RecoUtils::TrueParticleIDFromTotalRecoHits(clockData, hits, false);
398 
399  if(numHitMap.find(trackTrueID) != numHitMap.end()){
400  hNumTrueMatches[type]->Fill(numHitMap[trackTrueID]);
401  }
402  else{
403  hNumTrueMatches[type]->Fill(0);
404  }
405 
406  // Calculate t0 from CRT Hit matching
407  std::pair<sbn::crt::CRTHit, double> closest = t0Alg.ClosestCRTHit(detProp, tpcTrack, crtHits, event);
408 
409  if(closest.second != -99999){
410  int hitTrueID = fCrtBackTrack.TrueIdFromTotalEnergy(event, closest.first);
411  if(hitTrueID == trackTrueID && hitTrueID != -99999){
412  hMatchDCA[type]->Fill(closest.second);
413  }
414  else{
415  hNoMatchDCA[type]->Fill(closest.second);
416  }
417  }
418 
419 
420  int nbins = hDCATotal.begin()->second->GetNbinsX();
421  for(int i = 0; i < nbins; i++){
422  double DCAcut = hDCATotal.begin()->second->GetBinCenter(i);
423 
424  hDCATotal[type]->Fill(DCAcut);
425 
426  // If closest hit is below limit and track matches any hits then fill efficiency
427  if(closest.second < DCAcut && closest.second != -99999){
428  double hitTime = closest.first.ts1_ns * 1e-3;
429  if(hitTime > 0 && hitTime < 4) continue;
430  hDCATag[type]->Fill(DCAcut);
431  }
432 
433  }
434 
435  hLengthTotal[type]->Fill(tpcTrack.Length());
436  if(chTag.CrtHitCosmicId(detProp, tpcTrack, crtHits, event)){
437  hLengthTag[type]->Fill(tpcTrack.Length());
438  }
439  }
440 
441  } // CRTHitCosmicIdAna::analyze()
442 
443 
445 
446 
447  } // CRTHitCosmicIdAna::endJob()
448 
449  void CRTHitCosmicIdAna::GetPFParticleIdMap(const PFParticleHandle &pfParticleHandle, PFParticleIdMap &pfParticleMap){
450  for (unsigned int i = 0; i < pfParticleHandle->size(); ++i){
451  const art::Ptr<recob::PFParticle> pParticle(pfParticleHandle, i);
452  if (!pfParticleMap.insert(PFParticleIdMap::value_type(pParticle->Self(), pParticle)).second){
453  std::cout << " Unable to get PFParticle ID map, the input PFParticle collection has repeat IDs!" <<"\n";
454  }
455  }
456  }
457 
458  DEFINE_ART_MODULE(CRTHitCosmicIdAna)
459 } // namespace sbnd
BEGIN_PROLOG Verbose
std::map< size_t, art::Ptr< recob::PFParticle > > PFParticleIdMap
var pdg
Definition: selectors.fcl:14
art::InputTag fCRTHitLabel
name of CRT producer
virtual void endJob() override
std::vector< std::string > types
fhicl::Atom< art::InputTag > SimModuleLabel
Declaration of signal hit object.
walls no right
Definition: selectors.fcl:105
bool fVerbose
print information about what&#39;s going on
void GetPFParticleIdMap(const PFParticleHandle &pfParticleHandle, PFParticleIdMap &pfParticleMap)
process_name hit
Definition: cheaterreco.fcl:51
int TrueIdFromTotalEnergy(const art::Event &event, const sbnd::crt::CRTData &data)
int TrueIdFromHitId(const art::Event &event, int hit_i)
std::map< std::string, TH1D * > hDCATotal
std::map< std::string, TH1D * > hNoMatchDCA
art::EDAnalyzer::Table< Config > Parameters
T abs(T value)
std::pair< sbn::crt::CRTHit, double > ClosestCRTHit(detinfo::DetectorPropertiesData const &detProp, recob::Track tpcTrack, std::pair< double, double > t0MinMax, std::vector< sbn::crt::CRTHit > crtHits, int driftDirection)
std::map< std::string, TH1D * > hLengthTotal
fhicl::Table< CRTT0MatchAlg::Config > CRTT0Alg
art::InputTag fTPCTrackLabel
name of CRT producer
std::map< std::string, TH1D * > hNumTrueMatches
std::map< std::string, TH1D * > hDCATag
virtual void beginJob() override
const Cut kCosmicRay
BEGIN_PROLOG vertical distance to the surface Name
walls no left
Definition: selectors.fcl:105
int TrueParticleIDFromTotalRecoHits(detinfo::DetectorClocksData const &clockData, const std::vector< art::Ptr< recob::Hit > > &hits, bool rollup_unsaved_ids=1)
BEGIN_PROLOG don t mess with this TPCTrackLabel
bool CrtHitCosmicId(detinfo::DetectorPropertiesData const &detProp, recob::Track track, std::vector< sbn::crt::CRTHit > crtHits, const art::Event &event)
Definition of data types for geometry description.
std::map< std::string, TH1D * > hMatchDCA
Provides recob::Track data product.
CRTHitCosmicIdAna(Parameters const &config)
fhicl::Table< CRTBackTracker::Config > CrtBackTrack
fhicl::Atom< art::InputTag > PandoraLabel
fhicl::Atom< art::InputTag > TPCTrackLabel
virtual void analyze(const art::Event &event) override
do i e
stream1 can override from command line with o or output services user sbnd
art::ServiceHandle< art::TFileService > tfs
fhicl::Atom< art::InputTag > CRTHitLabel
art::Handle< std::vector< recob::PFParticle > > PFParticleHandle
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
BEGIN_PROLOG could also be cout
auto const detProp
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a &quot;fitted&quot; track:
fhicl::Table< CrtHitCosmicIdAlg::Config > CHTagAlg
bool InFiducial(geo::Point_t point, double fiducial)
art::InputTag fSimModuleLabel
name of detsim producer
std::map< std::string, TH1D * > hLengthTag