All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CosmicIdTree_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: CosmicIdTree
3 // Module Type: analyzer
4 // File: CosmicIdTree_module.cc
5 //
6 // Tom Brooks (tbrooks@fnal.gov)
7 ////////////////////////////////////////////////////////////////////////
8 
9 // sbndcode includes
17 
18 // LArSoft includes
24 #include "nusimdata/SimulationBase/MCParticle.h"
27 
28 // Framework includes
29 #include "art/Framework/Core/EDAnalyzer.h"
30 #include "art/Framework/Principal/Event.h"
31 #include "art/Framework/Principal/Handle.h"
32 #include "art_root_io/TFileService.h"
33 #include "canvas/Persistency/Common/FindManyP.h"
34 #include "fhiclcpp/ParameterSet.h"
35 #include "fhiclcpp/types/Table.h"
36 #include "fhiclcpp/types/Atom.h"
37 
38 #include "Pandora/PdgTable.h"
39 
40 // ROOT includes. Note: To look up the properties of the ROOT classes,
41 // use the ROOT web site; e.g.,
42 // <https://root.cern.ch/doc/master/annotated.html>
43 #include "TVector3.h"
44 
45 // C++ includes
46 #include <map>
47 #include <vector>
48 #include <string>
49 
50 namespace sbnd {
51 
52  class CosmicIdTree : public art::EDAnalyzer {
53  public:
54 
55  struct BeamTime {
56  using Name = fhicl::Name;
57  using Comment = fhicl::Comment;
58 
59  fhicl::Atom<double> BeamTimeMin {
60  Name("BeamTimeMin"),
61  Comment("")
62  };
63 
64  fhicl::Atom<double> BeamTimeMax {
65  Name("BeamTimeMax"),
66  Comment("")
67  };
68 
69  };
70 
71  // Describes configuration parameters of the module
72  struct Config {
73  using Name = fhicl::Name;
74  using Comment = fhicl::Comment;
75 
76  // One Atom for each parameter
77  fhicl::Atom<art::InputTag> SimModuleLabel {
78  Name("SimModuleLabel"),
79  Comment("tag of detector simulation data product")
80  };
81 
82  fhicl::Atom<art::InputTag> CRTHitLabel {
83  Name("CRTHitLabel"),
84  Comment("tag of CRT hit producer data product")
85  };
86 
87  fhicl::Atom<art::InputTag> CRTTrackLabel {
88  Name("CRTTrackLabel"),
89  Comment("tag of CRT track producer data product")
90  };
91 
92  fhicl::Atom<art::InputTag> TPCTrackLabel {
93  Name("TPCTrackLabel"),
94  Comment("tag of tpc track producer data product")
95  };
96 
97  fhicl::Atom<art::InputTag> CaloModuleLabel {
98  Name("CaloModuleLabel"),
99  Comment("tag of tpc calorimetry data product")
100  };
101 
102  fhicl::Atom<art::InputTag> PandoraLabel {
103  Name("PandoraLabel"),
104  Comment("tag of pandora data product")
105  };
106 
107  fhicl::Atom<bool> Verbose {
108  Name("Verbose"),
109  Comment("Print information about what's going on")
110  };
111 
112  fhicl::Table<CRTBackTracker::Config> CrtBackTrack {
113  Name("CrtBackTrack"),
114  };
115 
116  fhicl::Table<CosmicIdAlg::Config> CosIdAlg {
117  Name("CosIdAlg"),
118  };
119 
120  fhicl::Table<BeamTime> BeamTimeLimits {
121  Name("BeamTimeLimits"),
122  Comment("")
123  };
124 
125  }; // Config
126 
127  using Parameters = art::EDAnalyzer::Table<Config>;
128 
129  // Constructor: configures module
130  explicit CosmicIdTree(Parameters const& config);
131 
132  // Called once, at start of the job
133  virtual void beginJob() override;
134 
135  // Called once per event
136  virtual void analyze(const art::Event& event) override;
137 
138  // Called once, at end of the job
139  virtual void endJob() override;
140 
141  // Reset variables in each loop
142  void ResetTrackVars();
143  void ResetPfpVars();
144 
145  typedef art::Handle< std::vector<recob::PFParticle> > PFParticleHandle;
146  typedef std::map< size_t, art::Ptr<recob::PFParticle> > PFParticleIdMap;
147 
148  private:
149 
150  void GetPFParticleIdMap(const PFParticleHandle &pfParticleHandle, PFParticleIdMap &pfParticleMap);
151 
152  // fcl file parameters
153  art::InputTag fSimModuleLabel; ///< name of detsim producer
154  art::InputTag fCRTHitLabel; ///< name of CRT producer
155  art::InputTag fCRTTrackLabel; ///< name of CRT producer
156  art::InputTag fTPCTrackLabel; ///< name of CRT producer
157  art::InputTag fCaloModuleLabel; ///< name of CRT producer
158  art::InputTag fPandoraLabel;
159  bool fVerbose; ///< print information about what's going on
160  double fBeamTimeMin;
161  double fBeamTimeMax;
162 
164 
166 
168 
169  // Trees
170  TTree *fTrackTree;
171  TTree *fPfpTree;
172 
173  // Track tree parameters
174  std::string track_type;
178  double track_time;
179  double track_length;
181  double track_theta;
182  double track_phi;
198 
199  // PFParticle tree parameters
200  std::string pfp_type;
201  bool pfp_nu;
204  int pfp_pdg;
205  double pfp_time;
206  double pfp_length;
207  double pfp_momentum;
208  double pfp_theta;
209  double pfp_phi;
218  bool pfp_stops;
227  int pfp_tpc;
229  double pfp_apa_dist;
233 
234  }; // class CosmicIdTree
235 
236 
237  // Constructor
239  : EDAnalyzer(config)
240  , fSimModuleLabel (config().SimModuleLabel())
241  , fCRTHitLabel (config().CRTHitLabel())
242  , fCRTTrackLabel (config().CRTTrackLabel())
243  , fTPCTrackLabel (config().TPCTrackLabel())
244  , fCaloModuleLabel (config().CaloModuleLabel())
245  , fPandoraLabel (config().PandoraLabel())
246  , fVerbose (config().Verbose())
247  , fBeamTimeMin (config().BeamTimeLimits().BeamTimeMin())
248  , fBeamTimeMax (config().BeamTimeLimits().BeamTimeMax())
249  , fCrtBackTrack (config().CrtBackTrack())
250  , fCosId (config().CosIdAlg())
251  {
252 
253  } //CosmicIdTree()
254 
255 
257  {
258 
259  // Access tfileservice to handle creating and writing histograms
260  art::ServiceHandle<art::TFileService> tfs;
261 
262  // Track tree
263  fTrackTree = tfs->make<TTree>("tracks", "tracks");
264 
265  fTrackTree->Branch("track_type", &track_type);
266  fTrackTree->Branch("track_pfp_nu", &track_pfp_nu, "track_pfp_nu/O");
267  fTrackTree->Branch("track_nu_tpc", &track_nu_tpc, "track_nu_tpc/I");
268  fTrackTree->Branch("track_pdg", &track_pdg, "track_pdg/I");
269  fTrackTree->Branch("track_time", &track_time, "track_time/D");
270  fTrackTree->Branch("track_length", &track_length, "track_length/D");
271  fTrackTree->Branch("track_momentum", &track_momentum, "track_momentum/D");
272  fTrackTree->Branch("track_theta", &track_theta, "track_theta/D");
273  fTrackTree->Branch("track_phi", &track_phi, "track_phi/D");
274  fTrackTree->Branch("track_crt_hit_true_match", &track_crt_hit_true_match, "track_crt_hit_true_match/O");
275  fTrackTree->Branch("track_crt_hit_dca", &track_crt_hit_dca, "track_crt_hit_dca/D");
276  fTrackTree->Branch("track_crt_track_true_match", &track_crt_track_true_match, "track_crt_track_true_match/O");
277  fTrackTree->Branch("track_crt_track_dca", &track_crt_track_dca, "track_crt_track_dca/D");
278  fTrackTree->Branch("track_crt_track_angle", &track_crt_track_angle, "track_crt_track_angle/D");
279  fTrackTree->Branch("track_stops", &track_stops, "track_stops/O");
280  fTrackTree->Branch("track_stop_ratio_start", &track_stop_ratio_start, "track_stop_ratio_start/D");
281  fTrackTree->Branch("track_stop_ratio_end", &track_stop_ratio_end, "track_stop_ratio_end/D");
282  fTrackTree->Branch("track_fiducial_dist_start", &track_fiducial_dist_start, "track_fiducial_dist_start/D");
283  fTrackTree->Branch("track_fiducial_dist_end", &track_fiducial_dist_end, "track_fiducial_dist_end/D");
284  fTrackTree->Branch("track_tpc", &track_tpc, "track_tpc/I");
285  fTrackTree->Branch("track_apa_cross", &track_apa_cross, "track_apa_cross/O");
286  fTrackTree->Branch("track_apa_dist", &track_apa_dist, "track_apa_dist/D");
287  fTrackTree->Branch("track_apa_min_dist", &track_apa_min_dist, "track_apa_min_dist/D");
288  fTrackTree->Branch("track_pandora_nu_score", &track_pandora_nu_score, "track_pandora_nu_score/D");
289 
290  // PFParticle tree
291  fPfpTree = tfs->make<TTree>("pfps", "pfps");
292 
293  fPfpTree->Branch("pfp_type", &pfp_type);
294  fPfpTree->Branch("pfp_nu", &pfp_nu, "pfp_nu/O");
295  fPfpTree->Branch("pfp_nu_tpc", &pfp_nu_tpc, "pfp_nu_tpc/I");
296  fPfpTree->Branch("pfp_n_tracks", &pfp_n_tracks, "pfp_n_tracks/I");
297  fPfpTree->Branch("pfp_pdg", &pfp_pdg, "pfp_pdg/I");
298  fPfpTree->Branch("pfp_time", &pfp_time, "pfp_time/D");
299  fPfpTree->Branch("pfp_length", &pfp_length, "pfp_length/D");
300  fPfpTree->Branch("pfp_momentum", &pfp_momentum, "pfp_momentum/D");
301  fPfpTree->Branch("pfp_theta", &pfp_theta, "pfp_theta/D");
302  fPfpTree->Branch("pfp_phi", &pfp_phi, "pfp_phi/D");
303  fPfpTree->Branch("pfp_tracks_angle", &pfp_tracks_angle, "pfp_tracks_angle/D");
304  fPfpTree->Branch("pfp_second_length", &pfp_second_length, "pfp_second_length/D");
305  fPfpTree->Branch("pfp_crt_hit_true_match", &pfp_crt_hit_true_match, "pfp_crt_hit_true_match/O");
306  fPfpTree->Branch("pfp_crt_hit_dca", &pfp_crt_hit_dca, "pfp_crt_hit_dca/D");
307  fPfpTree->Branch("pfp_sec_crt_hit_dca", &pfp_sec_crt_hit_dca, "pfp_sec_crt_hit_dca/D");
308  fPfpTree->Branch("pfp_crt_track_true_match", &pfp_crt_track_true_match, "pfp_crt_track_true_match/O");
309  fPfpTree->Branch("pfp_crt_track_dca", &pfp_crt_track_dca, "pfp_crt_track_dca/D");
310  fPfpTree->Branch("pfp_crt_track_angle", &pfp_crt_track_angle, "pfp_crt_track_angle/D");
311  fPfpTree->Branch("pfp_stops", &pfp_stops, "pfp_stops/O");
312  fPfpTree->Branch("pfp_stop_ratio_start", &pfp_stop_ratio_start, "pfp_stop_ratio_start/D");
313  fPfpTree->Branch("pfp_stop_ratio_end", &pfp_stop_ratio_end, "pfp_stop_ratio_end/D");
314  fPfpTree->Branch("pfp_sec_stop_ratio_start", &pfp_sec_stop_ratio_start, "pfp_sec_stop_ratio_start/D");
315  fPfpTree->Branch("pfp_sec_stop_ratio_end", &pfp_sec_stop_ratio_end, "pfp_sec_stop_ratio_end/D");
316  fPfpTree->Branch("pfp_fiducial_dist_start", &pfp_fiducial_dist_start, "pfp_fiducial_dist_start/D");
317  fPfpTree->Branch("pfp_fiducial_dist_end", &pfp_fiducial_dist_end, "pfp_fiducial_dist_end/D");
318  fPfpTree->Branch("pfp_sec_fiducial_dist_start", &pfp_sec_fiducial_dist_start, "pfp_sec_fiducial_dist_start/D");
319  fPfpTree->Branch("pfp_sec_fiducial_dist_end", &pfp_sec_fiducial_dist_end, "pfp_sec_fiducial_dist_end/D");
320  fPfpTree->Branch("pfp_tpc", &pfp_tpc, "pfp_tpc/I");
321  fPfpTree->Branch("pfp_apa_cross", &pfp_apa_cross, "pfp_apa_cross/O");
322  fPfpTree->Branch("pfp_apa_dist", &pfp_apa_dist, "pfp_apa_dist/D");
323  fPfpTree->Branch("pfp_apa_min_dist", &pfp_apa_min_dist, "pfp_apa_min_dist/D");
324  fPfpTree->Branch("pfp_sec_apa_min_dist", &pfp_sec_apa_min_dist, "pfp_sec_apa_min_dist/D");
325  fPfpTree->Branch("pfp_pandora_nu_score", &pfp_pandora_nu_score, "pfp_pandora_nu_score/D");
326 
327  // Initial output
328  if(fVerbose) std::cout<<"----------------- Cosmic ID Tree Module -------------------"<<std::endl;
329 
330  } // CosmicIdTree::beginJob()
331 
332 
333  void CosmicIdTree::analyze(const art::Event& event)
334  {
335 
336  // Fetch basic event info
337  if(fVerbose){
338  std::cout<<"============================================"<<std::endl
339  <<"Run = "<<event.run()<<", SubRun = "<<event.subRun()<<", Event = "<<event.id().event()<<std::endl
340  <<"============================================"<<std::endl;
341  }
342 
343  //----------------------------------------------------------------------------------------------------------
344  // GETTING PRODUCTS
345  //----------------------------------------------------------------------------------------------------------
346  // Get g4 particles
347  art::ServiceHandle<cheat::ParticleInventoryService> pi_serv;
348  auto particleHandle = event.getValidHandle<std::vector<simb::MCParticle>>(fSimModuleLabel);
349 
350  // Get CRT hits from the event
351  art::Handle< std::vector<sbn::crt::CRTHit>> crtHitHandle;
352  std::vector<art::Ptr<sbn::crt::CRTHit> > crtHitList;
353  if (event.getByLabel(fCRTHitLabel, crtHitHandle))
354  art::fill_ptr_vector(crtHitList, crtHitHandle);
355 
356  // Initialize the CRT backtracker for speed
357  fCrtBackTrack.Initialize(event);
358 
359  // Loop over the CRT hits and match them to true particles
360  std::vector<sbn::crt::CRTHit> crtHits;
361  std::map<int, int> numHitMap;
362  int hit_i = 0;
363  for(auto const& hit : (crtHitList)){
364  // Don't try to match CRT hits in time with the beam
365  double hitTime = hit->ts1_ns * 1e-3;
366  if(hitTime > fBeamTimeMin && hitTime < fBeamTimeMax) continue;
367  crtHits.push_back(*hit);
368  int hitTrueID = fCrtBackTrack.TrueIdFromHitId(event, hit_i);
369  hit_i++;
370  numHitMap[hitTrueID]++;
371  }
372 
373  // Get CRT tracks from the event
374  art::Handle< std::vector<sbn::crt::CRTTrack>> crtTrackHandle;
375  std::vector<art::Ptr<sbn::crt::CRTTrack> > crtTrackList;
376  if (event.getByLabel(fCRTTrackLabel, crtTrackHandle))
377  art::fill_ptr_vector(crtTrackList, crtTrackHandle);
378 
379  // Loop over the CRT tracks and match them to true particles
380  std::vector<sbn::crt::CRTTrack> crtTracks;
381  std::map<int, int> numTrackMap;
382  int track_i = 0;
383  for(auto const& track : (crtTrackList)){
384  // Don't try to match CRT tracks in time with the beam
385  double trackTime = track->ts1_ns * 1e-3;
386  if(trackTime > fBeamTimeMin && trackTime < fBeamTimeMax) continue;
387  crtTracks.push_back(*track);
388  int trackTrueID = fCrtBackTrack.TrueIdFromTrackId(event, track_i);
389  track_i++;
390  numTrackMap[trackTrueID]++;
391  }
392 
393  // Get reconstructed tracks from the event and hit/calorimetry associations
394  auto tpcTrackHandle = event.getValidHandle<std::vector<recob::Track>>(fTPCTrackLabel);
395  art::FindManyP<recob::Hit> findManyHits(tpcTrackHandle, event, fTPCTrackLabel);
396  art::FindManyP<anab::Calorimetry> findManyCalo(tpcTrackHandle, event, fCaloModuleLabel);
397 
398  // Get PFParticles from pandora
399  PFParticleHandle pfParticleHandle;
400  event.getByLabel(fPandoraLabel, pfParticleHandle);
401  if( !pfParticleHandle.isValid() ){
402  if(fVerbose) std::cout<<"Failed to find the PFParticles."<<std::endl;
403  return;
404  }
405  PFParticleIdMap pfParticleMap;
406  this->GetPFParticleIdMap(pfParticleHandle, pfParticleMap);
407  // Get PFParticle to track associations
408  art::FindManyP< recob::Track > pfPartToTrackAssoc(pfParticleHandle, event, fTPCTrackLabel);
409  art::FindManyP<larpandoraobj::PFParticleMetadata> findManyPFPMetadata(pfParticleHandle,
410  event, fPandoraLabel);
411 
412  //----------------------------------------------------------------------------------------------------------
413  // TRUTH MATCHING
414  //----------------------------------------------------------------------------------------------------------
415 
416  // Sort the true particles by type
417  std::map<int, simb::MCParticle> particles;
418  std::vector<simb::MCParticle> parts;
419  std::vector<int> nuParticleIds;
420  std::vector<int> lepParticleIds;
421  std::vector<int> dirtParticleIds;
422  std::vector<int> crParticleIds;
423  // Record where the beam activity occurs
424  int nuTpc = -2;
425  // Loop over the true particles
426  for (auto const& particle: (*particleHandle)){
427 
428  // Make map with ID
429  int partID = particle.TrackId();
430  particles[partID] = particle;
431  parts.push_back(particle);
432 
433  // Get MCTruth
434  art::Ptr<simb::MCTruth> truth = pi_serv->TrackIdToMCTruth_P(partID);
435  int pdg = std::abs(particle.PdgCode());
436  double time = particle.T() * 1e-3; //[us]
437 
438  // If origin is a neutrino
439  if(truth->Origin() == simb::kBeamNeutrino){
440  geo::Point_t vtx;
441  vtx.SetX(truth->GetNeutrino().Nu().Vx()); vtx.SetY(truth->GetNeutrino().Nu().Vy()); vtx.SetZ(truth->GetNeutrino().Nu().Vz());
442  // If neutrino vertex is not inside the TPC then call it a dirt particle
443  if(!fTpcGeo.InFiducial(vtx, 0.)){
444  dirtParticleIds.push_back(partID);
445  }
446  // If it's a primary muon
447  else if(pdg==13 && particle.Mother()==0){
448  lepParticleIds.push_back(partID);
449  }
450  // Other nu particles
451  else{
452  nuParticleIds.push_back(partID);
453  }
454  }
455 
456  // If origin is a cosmic ray
457  else if(truth->Origin() == simb::kCosmicRay){
458  crParticleIds.push_back(partID);
459 
460  }
461 
462  // If particle is primary, charged and in time with the beam get the TPC
463  if(particle.Mother()==0 &&
464  (pdg==13||pdg==111||pdg==211||pdg==2212||pdg==11) &&
465  time > fBeamTimeMin && time < fBeamTimeMax){
466  std::pair<TVector3, TVector3> cross = fTpcGeo.CrossingPoints(particle);
467  if(cross.first.X() != cross.second.X()){
468  if(cross.first.X() < 0 && cross.second.X() < 0 && (nuTpc == 0 || nuTpc == -2)) nuTpc = 0;
469  else if(cross.first.X() > 0 && cross.second.X() > 0 && (nuTpc == 1 || nuTpc == -2)) nuTpc = 1;
470  else nuTpc = -1;
471  }
472  }
473 
474  }
475 
476  //----------------------------------------------------------------------------------------------------------
477  // FAKE PDS RECONSTRUCTION
478  //----------------------------------------------------------------------------------------------------------
479 
480  // Create fake flashes in each tpc
481  std::pair<std::vector<double>, std::vector<double>> fakeFlashes = CosmicIdUtils::FakeTpcFlashes(parts);
482  std::vector<double> fakeTpc0Flashes = fakeFlashes.first;
483  std::vector<double> fakeTpc1Flashes = fakeFlashes.second;
484  bool tpc0BeamFlash = CosmicIdUtils::BeamFlash(fakeTpc0Flashes, fBeamTimeMin, fBeamTimeMax);
485  bool tpc1BeamFlash = CosmicIdUtils::BeamFlash(fakeTpc1Flashes, fBeamTimeMin, fBeamTimeMax);
486 
487  // If there are no flashes in time with the beam then ignore the event
488  if(!tpc0BeamFlash && !tpc1BeamFlash) return;
489 
490  //----------------------------------------------------------------------------------------------------------
491  // FILLING THE PFPARTICLE TREE
492  //----------------------------------------------------------------------------------------------------------
493 
494  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
495  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(event, clockData);
496 
497  //Loop over the pfparticle map
498  std::map<int, bool> isPfpNu;
499  for (PFParticleIdMap::const_iterator it = pfParticleMap.begin(); it != pfParticleMap.end(); ++it){
500 
501  const art::Ptr<recob::PFParticle> pParticle(it->second);
502  // Only look for primary particles
503  if (!pParticle->IsPrimary()) continue;
504 
505  ResetPfpVars();
506  pfp_nu_tpc = nuTpc;
507 
508  // Check if this particle is identified as the neutrino
509  const int pdg(pParticle->PdgCode());
510  const bool isNeutrino(std::abs(pdg) == pandora::NU_E || std::abs(pdg) == pandora::NU_MU || std::abs(pdg) == pandora::NU_TAU);
511 
512  // FIXME Won't ever look at cosmic pfps as they don't have daughters
513  pfp_nu = isNeutrino;
514 
515  std::vector<recob::Track> nuTracks;
516  // Loop over daughters of pfparticle
517  for (const size_t daughterId : pParticle->Daughters()){
518 
519  // Get tracks associated with daughter
520  art::Ptr<recob::PFParticle> pDaughter = pfParticleMap.at(daughterId);
521  const std::vector< art::Ptr<recob::Track> > associatedTracks(pfPartToTrackAssoc.at(pDaughter.key()));
522  if(associatedTracks.size() != 1) continue;
523 
524  // Get the first associated track
525  recob::Track tpcTrack = *associatedTracks.front();
526  nuTracks.push_back(tpcTrack);
527 
528  isPfpNu[tpcTrack.ID()] = isNeutrino;
529 
530  // Truth match muon tracks and pfps
531  std::vector<art::Ptr<recob::Hit>> hits = findManyHits.at(tpcTrack.ID());
532  int trueId = RecoUtils::TrueParticleIDFromTotalRecoHits(clockData, hits, false);
533  if(std::find(lepParticleIds.begin(), lepParticleIds.end(), trueId) != lepParticleIds.end()){
534  pfp_type = "NuMu";
535  }
536  else if(std::find(nuParticleIds.begin(), nuParticleIds.end(), trueId) != nuParticleIds.end()){
537  if(pfp_type != "NuMu") pfp_type = "Nu";
538  }
539  else if(std::find(dirtParticleIds.begin(), dirtParticleIds.end(), trueId) != dirtParticleIds.end()){
540  if(pfp_type != "NuMu" && pfp_type != "Nu") pfp_type = "Dirt";
541  }
542  else if(std::find(crParticleIds.begin(), crParticleIds.end(), trueId) != crParticleIds.end()){
543  if(pfp_type != "NuMu" && pfp_type != "Nu" && pfp_type != "Dirt") pfp_type = "Cr";
544  }
545 
546  // Get the TPC the pfp was detected in
547  std::vector<art::Ptr<recob::Hit>> tpcHits = findManyHits.at(tpcTrack.ID());
548  int tpc = fTpcGeo.DetectedInTPC(tpcHits);
549  if(tpc == pfp_tpc || pfp_tpc == -99999) pfp_tpc = tpc;
550  else if(pfp_tpc != tpc) pfp_tpc = -1;
551  }
552 
553  // Don't consider PFParticles with no associated tracks
554  if(nuTracks.size() == 0) continue;
555 
556  pfp_n_tracks = nuTracks.size();
557 
558  // Sort tracks by length
559  std::sort(nuTracks.begin(), nuTracks.end(), [](auto& left, auto& right){
560  return left.Length() > right.Length();});
561 
562  // Choose longest track as cosmic muon candidate
563  recob::Track tpcTrack = nuTracks[0];
564  std::vector<art::Ptr<recob::Hit>> hits = findManyHits.at(tpcTrack.ID());
565  int trueId = RecoUtils::TrueParticleIDFromTotalRecoHits(clockData, hits, false);
566 
567  std::vector<art::Ptr<anab::Calorimetry>> calos = findManyCalo.at(tpcTrack.ID());
568 
569  // Get truth variables
570  if(particles.find(trueId) != particles.end()){
571  pfp_pdg = particles[trueId].PdgCode();
572  pfp_momentum = particles[trueId].P();
573  pfp_time = particles[trueId].T();
574  // Does the true particle match any CRT hits or tracks?
575  if(numHitMap.find(trueId) != numHitMap.end()){
576  if(numHitMap[trueId] > 0) pfp_crt_hit_true_match = true;
577  }
578  if(numTrackMap.find(trueId) != numTrackMap.end()){
579  if(numTrackMap[trueId] > 0) pfp_crt_track_true_match = true;
580  }
581  // Does particle stop in the TPC?
582  geo::Point_t end {particles[trueId].EndX(), particles[trueId].EndY(), particles[trueId].EndZ()};
583  if(fTpcGeo.InFiducial(end, 0.)) pfp_stops = true;
584  // Does the true particle cross the APA?
585  pfp_apa_cross = fTpcGeo.CrossesApa(particles[trueId]);
586  // Distance from the APA of the reco track at the true time
587  pfp_apa_dist = fCosId.ApaAlg().ApaDistance(detProp, tpcTrack, pfp_time/1e3, hits);
588  }
589 
590  pfp_length = tpcTrack.Length();
591  pfp_theta = tpcTrack.Theta();
592  pfp_phi = tpcTrack.Phi();
593 
594  // Get the second longest track originating from the same vertex
595  recob::Track secTrack = tpcTrack;
596  bool useSecTrack = false;
597  if(nuTracks.size() > 1){
598  TVector3 start = tpcTrack.Vertex<TVector3>();
599  TVector3 end = tpcTrack.End<TVector3>();
600 
601  for(size_t i = 1; i < nuTracks.size(); i++){
602  recob::Track track2 = nuTracks[i];
603  TVector3 start2 = track2.Vertex<TVector3>();
604  TVector3 end2 = track2.End<TVector3>();
605  // Do they share the same vertex? (no delta rays)
606  if((start-start2).Mag() > 5.) continue;
607  // Get the angle between the two longest tracks
608  pfp_tracks_angle = (end - start).Angle(end2 - start2);
609  pfp_second_length = track2.Length();
610  useSecTrack = true;
611  secTrack = track2;
612  break;
613  }
614 
615  }
616 
617  // CRT hit cut - get the distance of closest approach for the nearest CRT hit
618  std::pair<sbn::crt::CRTHit, double> closestHit = fCosId.CrtHitAlg().T0Alg().ClosestCRTHit(detProp, tpcTrack, crtHits, event);
619  pfp_crt_hit_dca = closestHit.second;
620  if(useSecTrack){
621  std::pair<sbn::crt::CRTHit, double> closestSecHit = fCosId.CrtHitAlg().T0Alg().ClosestCRTHit(detProp, secTrack, crtHits, event);
622  pfp_sec_crt_hit_dca = closestHit.second;
623  }
624 
625  // CRT track cut - get the average distance of closest approach and angle between tracks for the nearest CRT track
626  std::pair<sbn::crt::CRTTrack, double> closestTrackDca = fCosId.CrtTrackAlg().TrackAlg().ClosestCRTTrackByDCA(detProp, tpcTrack, crtTracks, event);
627  pfp_crt_track_dca = closestTrackDca.second;
628  std::pair<sbn::crt::CRTTrack, double> closestTrackAngle = fCosId.CrtTrackAlg().TrackAlg().ClosestCRTTrackByAngle(detProp, tpcTrack, crtTracks, event);
629  pfp_crt_track_angle = closestTrackAngle.second;
630 
631  // Stopping cut - get the chi2 ratio of the start and end of the track
632  pfp_stop_ratio_start = fCosId.StoppingAlg().StoppingChiSq(tpcTrack.Vertex(), calos);
633  pfp_stop_ratio_end = fCosId.StoppingAlg().StoppingChiSq(tpcTrack.End(), calos);
634  if(useSecTrack){
635  std::vector<art::Ptr<anab::Calorimetry>> secCalos = findManyCalo.at(secTrack.ID());
637  pfp_sec_stop_ratio_end = fCosId.StoppingAlg().StoppingChiSq(secTrack.End(), secCalos);
638  }
639 
640  // Fiducial cut - Get the fiducial volume the start and end points are contained in
641  pfp_fiducial_dist_start = fTpcGeo.MinDistToWall(tpcTrack.Vertex());
642  pfp_fiducial_dist_end = fTpcGeo.MinDistToWall(tpcTrack.End());
643  if(useSecTrack){
646  }
647 
648  // APA cut - get the minimum distance to the APA at all PDS times
649  std::pair<double, double> ApaMin = fCosId.ApaAlg().MinApaDistance(detProp, tpcTrack, hits, fakeTpc0Flashes, fakeTpc1Flashes);
650  pfp_apa_min_dist = ApaMin.first;
651  if(useSecTrack){
652  std::vector<art::Ptr<recob::Hit>> secHits = findManyHits.at(secTrack.ID());
653  std::pair<double, double> ApaMin = fCosId.ApaAlg().MinApaDistance(detProp, secTrack, hits, fakeTpc0Flashes, fakeTpc1Flashes);
654  pfp_sec_apa_min_dist = ApaMin.first;
655  }
656 
657  // Get the PFParticle Nu Score for the PFP Neutrino
658  pfp_pandora_nu_score = fCosId.PandoraNuScoreAlg().GetPandoraNuScore(*pParticle, findManyPFPMetadata);
659 
660  // Fill the PFParticle tree
661  fPfpTree->Fill();
662 
663  }
664 
665  //----------------------------------------------------------------------------------------------------------
666  // FILLING THE TRACK TREE
667  //----------------------------------------------------------------------------------------------------------
668 
669  // Loop over reconstructed tracks
670  for (auto const& tpcTrack : (*tpcTrackHandle)){
671 
672  ResetTrackVars();
673  track_nu_tpc = nuTpc;
674 
675  // Get the associated hits
676  std::vector<art::Ptr<recob::Hit>> hits = findManyHits.at(tpcTrack.ID());
677  int trueId = RecoUtils::TrueParticleIDFromTotalRecoHits(clockData, hits, false);
678 
679  std::vector<art::Ptr<anab::Calorimetry>> calos = findManyCalo.at(tpcTrack.ID());
680 
681  // Determine the type of the track
682  if(std::find(lepParticleIds.begin(), lepParticleIds.end(), trueId) != lepParticleIds.end()) track_type = "NuMu";
683  if(std::find(nuParticleIds.begin(), nuParticleIds.end(), trueId) != nuParticleIds.end()) track_type = "Nu";
684  if(std::find(crParticleIds.begin(), crParticleIds.end(), trueId) != crParticleIds.end()) track_type = "Cr";
685  if(std::find(dirtParticleIds.begin(), dirtParticleIds.end(), trueId) != dirtParticleIds.end()) track_type = "Dirt";
686 
687  // Check if it belongs to a neutrino tagged PFP
688  if(isPfpNu.find(tpcTrack.ID()) != isPfpNu.end()){
689  if(isPfpNu[tpcTrack.ID()]) track_pfp_nu = true;
690  }
691 
692  // Get truth variables
693  if(particles.find(trueId) != particles.end()){
694  track_pdg = particles[trueId].PdgCode();
695  track_momentum = particles[trueId].P();
696  track_time = particles[trueId].T();
697  // Does the true particle match any CRT hits or tracks?
698  if(numHitMap.find(trueId) != numHitMap.end()){
699  if(numHitMap[trueId] > 0) track_crt_hit_true_match = true;
700  }
701  if(numTrackMap.find(trueId) != numTrackMap.end()){
702  if(numTrackMap[trueId] > 0) track_crt_track_true_match = true;
703  }
704  // Does particle stop in the TPC?
705  geo::Point_t end {particles[trueId].EndX(), particles[trueId].EndY(), particles[trueId].EndZ()};
706  if(fTpcGeo.InFiducial(end, 0.)) track_stops = true;
707  // Does the true particle cross the APA?
708  track_apa_cross = fTpcGeo.CrossesApa(particles[trueId]);
709  // Distance from the APA of the reco track at the true time
710  track_apa_dist = fCosId.ApaAlg().ApaDistance(detProp, tpcTrack, track_time/1e3, hits);
711  }
712 
713  track_length = tpcTrack.Length();
714  track_theta = tpcTrack.Theta();
715  track_phi = tpcTrack.Phi();
716 
717  // CRT hit cut - get the distance of closest approach for the nearest CRT hit
718  std::pair<sbn::crt::CRTHit, double> closestHit = fCosId.CrtHitAlg().T0Alg().ClosestCRTHit(detProp, tpcTrack, crtHits, event);
719  track_crt_hit_dca = closestHit.second;
720 
721  // CRT track cut - get the average distance of closest approach and angle between tracks for the nearest CRT track
722  std::pair<sbn::crt::CRTTrack, double> closestTrackDca = fCosId.CrtTrackAlg().TrackAlg().ClosestCRTTrackByDCA(detProp, tpcTrack, crtTracks, event);
723  track_crt_track_dca = closestTrackDca.second;
724  std::pair<sbn::crt::CRTTrack, double> closestTrackAngle = fCosId.CrtTrackAlg().TrackAlg().ClosestCRTTrackByAngle(detProp, tpcTrack, crtTracks, event);
725  track_crt_track_angle = closestTrackAngle.second;
726 
727  // Stopping cut - get the chi2 ratio of the start and end of the track
728  track_stop_ratio_start = fCosId.StoppingAlg().StoppingChiSq(tpcTrack.Vertex(), calos);
729  track_stop_ratio_end = fCosId.StoppingAlg().StoppingChiSq(tpcTrack.End(), calos);
730 
731  // Fiducial cut - Get the fiducial volume the start and end points are contained in
732  track_fiducial_dist_start = fTpcGeo.MinDistToWall(tpcTrack.Vertex());
734 
735  // Geometry cut - get the TPC the track was detected in
737 
738  // APA cut - get the minimum distance to the APA at all PDS times
739  std::pair<double, double> ApaMin = fCosId.ApaAlg().MinApaDistance(detProp, tpcTrack, hits, fakeTpc0Flashes, fakeTpc1Flashes);
740  track_apa_min_dist = ApaMin.first;
741 
742  // The PFP Nu Score only exists for PFP Neutrinos
743  if (track_pfp_nu){
744  for(auto const pfp : (*pfParticleHandle)){
745  // Get the associated track if there is one
746  const std::vector< art::Ptr<recob::Track> > associatedTracks(pfPartToTrackAssoc.at(pfp.Self()));
747  if(associatedTracks.size() != 1) continue;
748  recob::Track trk = *associatedTracks.front();
749  if(trk.ID() != tpcTrack.ID()) continue;
750 
751  recob::PFParticle PFPNeutrino = fCosId.PandoraNuScoreAlg().GetPFPNeutrino(pfp, (*pfParticleHandle));
752  track_pandora_nu_score = fCosId.PandoraNuScoreAlg().GetPandoraNuScore(PFPNeutrino, findManyPFPMetadata);
753  break;
754  }
755  }
756  // Fill the Track tree
757  fTrackTree->Fill();
758  }
759 
760  } // CosmicIdTree::analyze()
761 
762 
764 
765 
766  } // CosmicIdTree::endJob()
767 
768  void CosmicIdTree::GetPFParticleIdMap(const PFParticleHandle &pfParticleHandle, PFParticleIdMap &pfParticleMap){
769  for (unsigned int i = 0; i < pfParticleHandle->size(); ++i){
770  const art::Ptr<recob::PFParticle> pParticle(pfParticleHandle, i);
771  if (!pfParticleMap.insert(PFParticleIdMap::value_type(pParticle->Self(), pParticle)).second){
772  std::cout << " Unable to get PFParticle ID map, the input PFParticle collection has repeat IDs!" <<"\n";
773  }
774  }
775  }
776 
778  track_type = "none";
779  track_pfp_nu = false;
780  track_nu_tpc = -99999;
781  track_pdg = -99999;
782  track_length = -99999;
783  track_momentum = -99999;
784  track_theta = -99999;
785  track_phi = -99999;
786  track_crt_hit_true_match = false;
787  track_crt_hit_dca = -99999;
789  track_crt_track_dca = -99999;
790  track_crt_track_angle = -99999;
791  track_stops = false;
792  track_stop_ratio_start = -99999;
793  track_stop_ratio_end = -99999;
794  track_fiducial_dist_start = -99999;
795  track_fiducial_dist_end = -99999;
796  track_tpc = -99999;
797  track_apa_cross = false;
798  track_apa_dist = -99999;
799  track_apa_min_dist = -99999;
800  track_pandora_nu_score = -99999;
801  }
802 
804  pfp_type = "none";
805  pfp_nu = false;
806  pfp_nu_tpc = -99999;
807  pfp_n_tracks = 0;
808  pfp_pdg = -99999;
809  pfp_length = -99999;
810  pfp_momentum = -99999;
811  pfp_theta = -99999;
812  pfp_phi = -99999;
813  pfp_tracks_angle = -99999;
814  pfp_second_length = -99999;
815  pfp_crt_hit_true_match = false;
816  pfp_crt_hit_dca = -99999;
817  pfp_sec_crt_hit_dca = -99999;
818  pfp_crt_track_true_match = false;
819  pfp_crt_track_dca = -99999;
820  pfp_crt_track_angle = -99999;
821  pfp_stops = false;
822  pfp_stop_ratio_start = -99999;
823  pfp_stop_ratio_end = -99999;
824  pfp_sec_stop_ratio_start = -99999;
825  pfp_sec_stop_ratio_end = -99999;
826  pfp_fiducial_dist_start = -99999;
827  pfp_fiducial_dist_end = -99999;
829  pfp_sec_fiducial_dist_end = -99999;
830  pfp_tpc = -99999;
831  pfp_apa_cross = false;
832  pfp_apa_dist = -99999;
833  pfp_apa_min_dist = -99999;
834  pfp_sec_apa_min_dist = -99999;
835  pfp_pandora_nu_score = -99999;
836  }
837 
838  DEFINE_ART_MODULE(CosmicIdTree)
839 } // namespace sbnd
BEGIN_PROLOG Verbose
int TrueIdFromTrackId(const art::Event &event, int track_i)
var pdg
Definition: selectors.fcl:14
bool BeamFlash(std::vector< double > flashes, double beamTimeMin, double beamTimeMax)
std::map< size_t, art::Ptr< recob::PFParticle > > PFParticleIdMap
StoppingParticleCosmicIdAlg StoppingAlg() const
art::InputTag fCRTHitLabel
name of CRT producer
Declaration of signal hit object.
walls no right
Definition: selectors.fcl:105
art::InputTag fCRTTrackLabel
name of CRT producer
fhicl::Atom< art::InputTag > PandoraLabel
process_name use argoneut_mc_hitfinder track
process_name hit
Definition: cheaterreco.fcl:51
double StoppingChiSq(geo::Point_t end, std::vector< art::Ptr< anab::Calorimetry >> calos)
int TrueIdFromHitId(const art::Event &event, int hit_i)
art::InputTag fSimModuleLabel
name of detsim producer
art::InputTag fTPCTrackLabel
name of CRT producer
double ApaDistance(detinfo::DetectorPropertiesData const &detProp, recob::Track track, double t0, std::vector< art::Ptr< recob::Hit >> hits)
T abs(T value)
art::InputTag fCaloModuleLabel
name of CRT producer
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)
double Length(size_t p=0) const
Access to various track properties.
fhicl::Table< CRTBackTracker::Config > CrtBackTrack
recob::PFParticle GetPFPNeutrino(recob::PFParticle pfparticle, std::map< size_t, art::Ptr< recob::PFParticle > > &pfParticleMap)
std::pair< sbn::crt::CRTTrack, double > ClosestCRTTrackByDCA(detinfo::DetectorPropertiesData const &detProp, recob::Track tpcTrack, std::vector< sbn::crt::CRTTrack > crtTracks, const art::Event &event, double minAngle=0.)
float GetPandoraNuScore(recob::PFParticle pfparticle, art::FindManyP< larpandoraobj::PFParticleMetadata > PFPMetaDataAssoc)
fhicl::Table< BeamTime > BeamTimeLimits
fhicl::Atom< double > BeamTimeMax
bool CrossesApa(const simb::MCParticle &particle)
fhicl::Table< CosmicIdAlg::Config > CosIdAlg
Point_t const & Vertex() const
void GetPFParticleIdMap(const PFParticleHandle &pfParticleHandle, PFParticleIdMap &pfParticleMap)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
art::Handle< std::vector< recob::PFParticle > > PFParticleHandle
fhicl::Atom< double > BeamTimeMin
const Cut kCosmicRay
BEGIN_PROLOG vertical distance to the surface Name
std::pair< double, double > MinApaDistance(detinfo::DetectorPropertiesData const &detProp, recob::Track track, std::vector< double > t0List, int tpc)
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
Definition of data types for geometry description.
int DetectedInTPC(std::vector< art::Ptr< recob::Hit >> hits)
Provides recob::Track data product.
fhicl::Atom< art::InputTag > CRTTrackLabel
fhicl::Atom< art::InputTag > TPCTrackLabel
Hierarchical representation of particle flow.
Definition: PFParticle.h:44
virtual void endJob() override
virtual void analyze(const art::Event &event) override
fhicl::Atom< art::InputTag > CRTHitLabel
CRTBackTracker fCrtBackTrack
std::pair< sbn::crt::CRTTrack, double > ClosestCRTTrackByAngle(detinfo::DetectorPropertiesData const &detProp, recob::Track tpcTrack, std::vector< sbn::crt::CRTTrack > crtTracks, const art::Event &event, double minDCA=0.)
fhicl::Atom< art::InputTag > CaloModuleLabel
do i e
bool fVerbose
print information about what&#39;s going on
std::pair< std::vector< double >, std::vector< double > > FakeTpcFlashes(std::vector< simb::MCParticle > particles)
Definition: CosmicIdUtils.cc:8
Point_t const & End() const
stream1 can override from command line with o or output services user sbnd
art::ServiceHandle< art::TFileService > tfs
Vector cross(Vector const &a, Vector const &b)
Return cross product of two vectors.
fhicl::Atom< art::InputTag > SimModuleLabel
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
PandoraNuScoreCosmicIdAlg PandoraNuScoreAlg() const
art::EDAnalyzer::Table< Config > Parameters
virtual void beginJob() override
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:
CosmicIdTree(Parameters const &config)
std::pair< TVector3, TVector3 > CrossingPoints(const simb::MCParticle &particle)
bool InFiducial(geo::Point_t point, double fiducial)