StructuredTree_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 // Class:
3 // Plugin Type: analyzer (art v2_11_02)
4 // File: StructuredTree_module.cc
5 //
6 // Copied from anatree_module.cc on 2020 Dec 18 by C. Hilgenberg (chilgenb@fnal.gov)
7 // This module extracts info useful for general analysis or reco R&D based
8 // on the fcl config. Several class based trees are writen to file.
9 //
10 ////////////////////////////////////////////////////////////////////////////////
11 
12 // framework includes
21 #include "art_root_io/TFileService.h"
23 #include "fhiclcpp/ParameterSet.h"
26 #include "canvas/Persistency/Common/FindOne.h"
27 #include "canvas/Persistency/Common/FindOneP.h"
28 #include "canvas/Persistency/Common/FindMany.h"
29 #include "canvas/Persistency/Common/FindManyP.h"
30 
31 //simb::
35 
36 //garsoft includes
40 
50 
54 
55 #include "AnaUtils.cxx"
56 
57 #include "MCCheater/BackTracker.h"
58 
59 // nutools extensions
60 #include "nurandom/RandomUtils/NuRandomService.h"
61 
62 #include "CoreUtils/ServiceUtil.h"
63 #include "Geometry/GeometryGAr.h"
64 
65 #include "TTree.h"
66 #include "TDatabasePDG.h"
67 #include "TParticlePDG.h"
68 #include "TH2.h"
69 #include "TFile.h"
70 
71 #include "CLHEP/Random/RandFlat.h"
72 
73 #include <string>
74 #include <vector>
75 #include <unordered_map>
76 #include <iostream>
77 
78 //save ourselves some typing
79 using std::vector;
80 using std::string;
81 using std::pair;
82 using simb::MCParticle;
83 using art::InputTag;
84 using art::Assns;
85 using art::Event;
86 using art::Handle;
87 using art::ValidHandle;
88 
89 namespace gar {
90 
91  typedef pair<float, string> P;
92 
94  public:
95  explicit StructuredTree(fhicl::ParameterSet const & p);
96  // The compiler-generated destructor is fine for non-base
97  // classes without bare pointers or other resource use.
98 
99  // Plugins should not be copied or assigned.
100  StructuredTree(StructuredTree const &) = delete;
101  StructuredTree(StructuredTree &&) = delete;
102  StructuredTree & operator = (StructuredTree const &) = delete;
104 
105  virtual void beginJob() override;
106  virtual void endRun(art::Run const& run) override;
107  virtual void endJob() override;
108 
109  // Required functions.
110  void analyze( Event const & e ) override;
111 
112  private:
113  void ClearVectors();///< clear all vectors and reset counters
114 
115  //Working Horses
116  void FillGenTree( Event const & e ); ///< extracts generator(truth) level sim products
117  void FillG4Tree( Event const & e ); ///< extracts G4(truth) level sim products
118  void FillDetTree( Event const & e ); ///< extracts readout sim products
119  void FillRecoInfo( Event const & e ); ///< extracts base level reco products
120  void FillHighLevelRecoInfo( Event const & e ); ///< extracts high level reco products
121 
122  //Helpers
123  std::string PointToRegion(const TVector3& point);
124  void processIonizationInfo(rec::TrackIoniz& ion, float ionizeTruncate,
125  float& forwardIonVal, float& backwardIonVal);
126  float processOneDirection(vector<pair<float,float>> SigData,
127  float ionizeTruncate);
128  // Helper method for processOneDirection
129  static bool lessThan_byE(std::pair<float,float> a, std::pair<float,float> b)
130  {return a.first < b.first;}
131 
132  // Calculate the track PID based on reco momentum and Tom's parametrization
133  vector< pair<int, float> > processPIDInfo( float p );
134 
135  float xTPC;
136  float rTPC;
137 
138  // Input data labels
139  string fPOTtag;
140  string fGeantLabel; ///< module label for geant4 simulated hits
141  string fGeantInstanceCalo; ///< Instance name ECAL for sdp::CaloDeposit
142  string fGeantInstanceMuID; ///< Instance name MuID for sdp::CaloDeposit
143 
144  string fHitLabel; ///< module label for reco TPC hits rec::Hit
145  string fTPCClusterLabel; ///< module label for TPC Clusters rec::TPCCluster
146  string fTrackLabel; ///< module label for TPC Tracks rec:Track
147  string fVertexLabel; ///< module label for vertexes rec:Vertex
148  string fVeeLabel; ///< module label for conversion/decay vertexes rec:Vee
149 
150  string fTPCDigitLabel; ///< module label for digitized TPC hits raw::RawDigit
151  string fCalDigitLabel; ///< module label for digitized calo/muID hits raw::CaloRawDigit
152  string fCalDigitInstance; ///< Instance name ECAL for raw::CaloRawDigit
153  string fMuDigitInstance; ///< Instance name MuID for raw::CaloRawDigit
154 
155  string fCaloHitLabel; ///< module label for reco calo hits rec::CaloHit
156  string fCaloHitInstanceCalo; ///< Instance name ECAL for rec::CaloHit
158  string fCaloHitInstanceMuID; ///< Instance name MuID for rec::CaloHit
159 
160  string fClusterLabel; ///< module label for calo clusters rec::Cluster
161  string fPFLabel; ///< module label for reco particles rec::PFParticle
162  string fECALAssnLabel; ///< module label for track-clusters associations
163 
164  //config
165  string fAnaMode; ///< analysis configs: (gen)eral, (reco) R&D or (readout) sim R&D, default="gen"
166  bool fWriteDisplay; ///< include sim/reco traj points for event display, default=false
167 
168 
169  // Truncation parameter for dE/dx (average this fraction lowest readings)
170  float fIonizTruncate; ///< Default=1.00;
171 
172  // the analysis output trees
173  TTree* fHeaderTree;
174  TTree* fGenTree;
175  TTree* fG4Tree;
176  TTree* fDetTree;
177  TTree* fRecoTree;
178  TTree* fDisplayTree;
179 
180  //Geometry
181  const geo::GeometryCore* fGeo; ///< pointer to the geometry service
182 
183  //backtracker for determining inter product associations
185 
186  // global event info
187  Int_t fEvent; ///< number of the event being processed
188  Int_t fRun; ///< number of the run being processed
189  Int_t fSubRun; ///< number of the sub-run being processed
190  Int_t fPOT;
191  Int_t fNSpills;
192  TLorentzVector fTpcCenter;
194 
195  // headerTree
196  string fTreeType; ///<"structured" (in our case yes) or "flat" (no)
197 
198  // genTree
199  vector<Int_t> fGIndex; ///< index of GTruth object associated with MCTruth in this row (-1 if not associated, e.g. CRY event)
200  vector<garana::GTruth> fGTruth; ///< GENIE interction-level info
201  vector<vector<garana::FSParticle>> fFSParticles; ///< FS particles/4-vecs
202 
203  // g4Tree
204  vector<garana::G4Particle> fG4Particles; ///< 'condensed' MCParticles from G4
205  vector<UInt_t> fG4TruthIndex; ///< index of GTruth objects matched to this particle
206  vector<UInt_t> fG4FSIndex; ///< index of FSParticle objects matched to this particle
207  vector<vector<sdp::EnergyDeposit>> fSimTPCHits; ///< several "hits" per MCParticle
208  vector<vector<sdp::CaloDeposit>> fSimCalHits;
209  vector<vector<sdp::CaloDeposit>> fSimMuHits;
210  //vector<UInt_t> fSimTPCHitsG4P;
211  //vector<UInt_t> fSimCalHitsG4P;
212  //vector<UInt_t> fSimMuHitsG4P;
213 
214  // detTree
215  vector<raw::RawDigit> fTPCDigits;
216  vector<raw::CaloRawDigit> fCaloDigits;
217  vector<raw::CaloRawDigit> fMuDigits;
218  //TODO: add Assns digit -> simDeposit (need to add to BackTrackerCore)
219 
220  // recoTree
221  // Reco Hit data
222  vector<rec::Hit> fTPCHits;
223  vector<rec::CaloHit> fCalHits;
224  vector<rec::CaloHit> fMuHits;
225  //TODO: add Assns hit -> digit (need to add to BackTrackerCore)
226 
227  // Cluster data
228  vector<rec::TPCCluster> fTPCClusters; ///< reco TPC clusters
229  vector<garana::CaloCluster> fCalClusters; ///< reco ECal clusters
230  vector<garana::CaloCluster> fMuClusters; ///< reco MuID clusters
231  //TODO: add Assns Cluster->Hit
232 
233  // Track data
234  vector<garana::Track> fTracks; ///< reco TPC tracks
235  vector<vector<UInt_t>> fTrackG4PIndices; ///< index of fG4Particles associated with fTracks
236  //TODO: add Assns Track->Cluster
237 
238  // Vertex data
239  vector<garana::Vertex> fVertices; ///< reco TPC vertices
240  vector<vector<UInt_t>> fVertTrackIndices; ///< index of fTracks associated with fVertices
241  vector<vector<Int_t>> fVertTrackEnds; ///< which fTrack end belongs to this vertex
242 
243  // Vee data
244  vector<garana::Vee> fVees; ///< reco Vees (reco 4-mom, 4-pos from decay vertex)
245  vector<vector<UInt_t>> fVeeTrackIndices; ///< index of fTracks associated with fVees
246  vector<vector<Int_t>> fVeeTrackEnds; ///< track end associated with fVees
247 
248  // ECal cluster data
249  vector<vector<UInt_t>> fCalTrackIndices; ///< index of fTracks associated with fCalClusters
250  vector<vector<Int_t>> fCalTrackEnds; ///< Track end associated with the cluster
251  vector<vector<UInt_t>> fCalG4PIndices; ///< index of fG4Particles associated with fCalClusters
252 
253  // displayTree
254  //vector<adp::MCDisplayTrack> fMCDisplay; ///< sparsified MCTrajectory
255  vector<rec::TrackTrajectory> fRecoDisplay; ///< reconstructed track trajectory points
256 
257  //map of PID TH2 per momentum value
258  CLHEP::HepRandomEngine &fEngine; ///< random engine
259  std::unordered_map<int, TH2F*> m_pidinterp;
260 
261  //data members used for associations bookkeeping between fill methods
262  vector<const simb::MCTruth*> fMCTruths; //needed for G4Particle -> MCTruth (FS particles) matching
263  vector<const simb::MCParticle*> fMCParticles; //needed for reco object -> MCParticle matching
264 
265  std::map<std::string,int> fRegionNameToID;
266 
267  };//class
268 }//namespace gar
269 
270 //==============================================================================
271 //==============================================================================
272 //==============================================================================
273 // constructor
275  : EDAnalyzer(p),
276  fEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, p, "Seed"))
277 {
278  fGeo = providerFrom<geo::GeometryGAr>();
279 
280  //Sim Hits
281  fGeantLabel = p.get<string>("GEANTLabel","geant");
282  fGeantInstanceCalo = p.get<string>("GEANTInstanceCalo","ECAL");
283  fGeantInstanceMuID = p.get<string>("GEANTInstanceMuID","MuID");
284 
285  fHitLabel = p.get<string>("HitLabel","hit");
286  fTPCClusterLabel = p.get<string>("TPCClusterLabel","tpccluster");
287  fTrackLabel = p.get<string>("TrackLabel","track");
288  fVertexLabel = p.get<string>("VertexLabel","vertex");
289  fVeeLabel = p.get<string>("VeeLabel","veefinder1");
290 
291  //readout simulation labels
292  fTPCDigitLabel = p.get<string>("TPCDigitLabel","daq");
293  fCalDigitLabel = p.get<string>("CalDigitLabel","daqsipm"); //same label for ECal/MuID
294  fCalDigitInstance = p.get<string>("CalDigitInstance","ECAL");
295  fMuDigitInstance = p.get<string>("MuDigitInstance","MuID");
296 
297  fCaloHitLabel = p.get<string>("CaloHitLabel","sipmhit");
298  fCaloHitInstanceCalo = p.get<string>("CaloHitInstanceCalo","ECAL");
299  fMuIDHitLabel = p.get<string>("MuIDHitLabel","sipmhit");
300  fCaloHitInstanceMuID = p.get<string>("CaloHitInstanceMuID","MuID");
301 
302  fClusterLabel = p.get<string>("ClusterLabel","calocluster");
303  fPFLabel = p.get<string>("PFLabel","pandora");
304  fECALAssnLabel = p.get<string>("ECALAssnLabel","trkecalassn");
305 
306  // analysis configuration
307  fAnaMode = p.get<string>("AnalysisMode", "gen");
308  fWriteDisplay = p.get<bool>("WriteDisplay", false);
309 
310  fIonizTruncate = p.get<float>("IonizTruncate", 0.70);
311 
312  //required input products
313  // gen
314  consumesMany<vector<simb::MCTruth> >();
315  consumesMany<vector<simb::GTruth> >();
316 
317  // g4
318  consumes<Assns<simb::MCTruth, simb::MCParticle> >(fGeantLabel);
319  consumes<vector<simb::MCParticle> >(fGeantLabel);
320  consumes<vector<sdp::EnergyDeposit> >(fGeantLabel);
321  InputTag ecalgeanttag(fGeantLabel, fGeantInstanceCalo);
322  consumes<vector<sdp::CaloDeposit> >(ecalgeanttag);
323 
324  // reco
325  consumes<vector<rec::TPCCluster> >(fTPCClusterLabel);
326  consumes<Assns<rec::Track, rec::TPCCluster> >(fTPCClusterLabel);
327  consumes<vector<rec::Hit> >(fHitLabel);
328  consumes<vector<rec::Track> >(fTrackLabel);
329  consumes<vector<rec::Vertex> >(fVertexLabel);
330  consumes<Assns<rec::Track, rec::Vertex> >(fVertexLabel);
331  consumes<vector<rec::Vee> >(fVeeLabel);
332  consumes<Assns<rec::Track, rec::Vee> >(fVeeLabel);
333  consumes<vector<rec::TrackIoniz>>(fTrackLabel);
334  consumes<Assns<rec::TrackIoniz, rec::Track>>(fTrackLabel);
335 
336  // det
337  if(fAnaMode == "readout"){
338 
339  //TPC
340  InputTag tpcrawtag(fTPCDigitLabel);
341  consumes<vector<raw::RawDigit> >(tpcrawtag);
342 
343  //ECal
344  InputTag ecalrawtag(fCalDigitLabel, fCalDigitInstance);
345  consumes<vector<raw::CaloRawDigit> >(ecalrawtag);
346 
347  //MuonID system
348  if (fGeo->HasMuonDetector()) {
349  InputTag murawtag(fCalDigitLabel, fMuDigitInstance);
350  consumes<vector<raw::CaloRawDigit> >(murawtag);
351  }
352  }
353 
354  InputTag ecalhittag(fCaloHitLabel, fCaloHitInstanceCalo);
355  consumes<vector<rec::CaloHit> >(ecalhittag);
356 
357  //Muon system related
358  if (fGeo->HasMuonDetector()) {
359  InputTag muidgeanttag(fGeantLabel, fGeantInstanceMuID);
360  consumes<vector<sdp::CaloDeposit> >(muidgeanttag);
361 
362  InputTag muidhittag(fCaloHitLabel, fCaloHitInstanceMuID);
363  consumes<vector<rec::CaloHit> >(muidhittag);
364  }
365 
366  consumes<vector<rec::Cluster> >(fClusterLabel);
367  consumes<Assns<rec::Cluster, rec::Track>>(fECALAssnLabel);
368 
369  return;
370 } // end constructor
371 
372 //==============================================================================
373 //==============================================================================
374 //==============================================================================
376 
377  fTreeType = "structured";
378  fTpcCenter.SetXYZT(fGeo->TPCXCent(),fGeo->TPCYCent(),fGeo->TPCZCent(),0.);
379  xTPC = fGeo->TPCLength() / 2.;
380  rTPC = fGeo->TPCRadius();
381  fGeometry = fGeo->GDMLFile();
382 
384 
385  // headerTree
386  fHeaderTree = tfs->make<TTree>("headerTree", "sample provenance information");
387  fHeaderTree->Branch("Run", &fRun, "Run/I");
388  fHeaderTree->Branch("SubRun", &fSubRun, "SubRun/I");
389  fHeaderTree->Branch("TreeType", "std::string", &fTreeType);
390  fHeaderTree->Branch("POT", &fPOT, "POT/I");
391  fHeaderTree->Branch("NSpills", &fNSpills, "NSpills/I");
392  fHeaderTree->Branch("Geometry", "std::string", &fGeometry);
393  fHeaderTree->Branch("TpcCenter", "TLorentzVector", &fTpcCenter);
394 
395  // genTree
396  fGenTree = tfs->make<TTree>("genTree", "generator level info");
397  fGenTree->Branch("Event", &fEvent, "Event/I");
398  fGenTree->Branch("GIndex", "std::vector<Int_t>", &fGIndex);
399  fGenTree->Branch("GTruth", "std::vector<garana::GTruth>", &fGTruth);
400  fGenTree->Branch("FSParticles", "std::vector<std::vector<garana::FSParticle>>", &fFSParticles);
401 
402  // g4Tree
403  fG4Tree = tfs->make<TTree>("g4Tree", "GEANT4 level info");
404  fG4Tree->Branch("Event", &fEvent, "Event/I");
405  fG4Tree->Branch("TruthIndex", "std::vector<UInt_t>", &fG4TruthIndex);
406  fG4Tree->Branch("FSIndex", "std::vector<UInt_t>", &fG4FSIndex);
407  fG4Tree->Branch("G4Particles", "std::vector<garana::G4Particle>", &fG4Particles);
408  if(fAnaMode == "reco" || fAnaMode == "readout"){
409  fG4Tree->Branch("CalHits.", "std::vector<sdp::CaloDeposit>", &fSimCalHits);
410  fG4Tree->Branch("TPCHits", "std::vector<sdp::EnergyDeposit>", &fSimTPCHits);
411  //fG4Tree->Branch("CalHitsG4Indices.", "vector<UInt_t>", &fSimCalHitsG4P);
412  //fG4Tree->Branch("TPCHitsG4Indices", "vector<UInt_t>", &fSimTPCHitsG4P);
413  if(fGeo->HasMuonDetector()){
414  fG4Tree->Branch("MuIDHits.", "std::vector<sdp::CaloDeposit>", &fSimMuHits);
415  //fG4Tree->Branch("MuIDHitsG4Indices.", "vector<sdp::CaloDeposit>", &fSimMuHitsG4P);
416  }
417  }
418 
419  if (fWriteDisplay) {
420  fDisplayTree = tfs->make<TTree>("displayTree","truth/reco level traj points for event display");
421  fDisplayTree->Branch("Event", &fEvent, "Event/I");
422  //fDisplayTree->Branch("MCTracks", "std::vector<adp::MCDisplayTrack>", &fMCDisplay);
423  if(fAnaMode!="readout"){
424  fDisplayTree->Branch("RecoTracks", "std::vector<garana::Track>", &fRecoDisplay);
425  }
426 
427  }
428  //Digit. or Digit (no '.')??
429  if(fAnaMode=="readout"){
430  fDetTree = tfs->make<TTree>("detTree", "detector readout level info");
431  fDetTree->Branch("Event", &fEvent, "Event/I");
432  fDetTree->Branch("TPCDigits", "std::vector<gar::raw::RawDigit>", &fTPCDigits);
433  fDetTree->Branch("CaloDigits.", "std::vector<gar::raw::CaloDigit>", &fCaloDigits);
434  if(fGeo->HasMuonDetector()){
435  fDetTree->Branch("MuDigits.", "std::vector<gar::raw::CaloDigit>", &fMuDigits);
436  }
437 
438  return; //probably don't want reco info for readout simulation analysis unless doing hit reco ana
439  }
440 
441  //recoTree
442  fRecoTree = tfs->make<TTree>("recoTree", "reconstruction level info");
443  fRecoTree->Branch("Event", &fEvent, "Event/I");
444  fRecoTree->Branch("Tracks", "std::vector<garana::Track>", &fTracks);
445  fRecoTree->Branch("Vees", "std::vector<garana::Vee>", &fVees);
446  fRecoTree->Branch("Vertices", "std::vector<garana::Vertex>", &fVertices);
447  fRecoTree->Branch("CalClusters", "std::vector<garana::CaloCluster>", &fCalClusters);
448  fRecoTree->Branch("TrackG4Indices", "std::vector<std::vector<UInt_t>>", &fTrackG4PIndices);
449  fRecoTree->Branch("VertTrackIndices", "std::vector<std::vector<UInt_t>>", &fVertTrackIndices);
450  fRecoTree->Branch("VertTrackEnds", "std::vector<std::vector<Int_t>>", &fVertTrackEnds);
451  fRecoTree->Branch("VeeTrackIndices", "std::vector<std::vector<UInt_t>>", &fVeeTrackIndices);
452  fRecoTree->Branch("VeeTrackEnds", "std::vector<std::vector<Int_t>>", &fVeeTrackEnds);
453  fRecoTree->Branch("CalTrackIndices", "std::vector<std::vector<UInt_t>>", &fCalTrackIndices);
454  //fRecoTree->Branch("CalTrackEnds", "std::vector<std::vector<Int_t>>", &fCalTrackEnds);
455  fRecoTree->Branch("CalG4Indices", "std::vector<std::vector<UInt_t>>", &fCalG4PIndices);
456  if(fGeo->HasMuonDetector()){
457  fRecoTree->Branch("MuIDClusters", "std::vector<garana::CaloCluster>", &fMuClusters);
458  }
459 
460  //TODO: add Assns for reco r&d products
461  if(fAnaMode == "reco"){
462  fRecoTree->Branch("TPCHits", "std::vector<gar::rec::Hit>", &fTPCHits);
463  fRecoTree->Branch("TPCClusters", "std::vector<gar::rec::TPCCluster>", &fTPCClusters);
464  fRecoTree->Branch("CalHits", "std::vector<gar::rec::CaloHit>", &fCalHits);
465  if(fGeo->HasMuonDetector()){
466  fRecoTree->Branch("MuIDHits", "std::vector<gar::rec::CaloHit>", &fMuHits);
467  }
468  }
469 
470 
471  //auxilliary info for PID calculation (not yet in reco)
472  string filename = "${DUNE_PARDATA_DIR}/MPD/dedxPID/dedxpidmatrices8kevcm.root";
473  TFile infile(filename.c_str(), "READ");
474 
475  m_pidinterp.clear();
476  char str[11];
477  for (int q = 0; q < 501; ++q)
478  {
479  sprintf(str, "%d", q);
480  std::string s = "pidmatrix";
481  s.append(str);
482  // read the 500 histograms one by one; each histogram is a
483  // 6 by 6 matrix of probabilities for a given momentum value
484  m_pidinterp.insert( std::make_pair(q, (TH2F*) infile.Get(s.c_str())->Clone("pidinterp")) );
485  }
486 
487  //map region names to id code for easy access from the trees
488  // TODO this is for the current (as of 3/25/2021) default geometry
489  // -> add handling for arbitrary geometry
490  fRegionNameToID = {
491  {"Unknown", -1 },
492  {"TPC1", 0 },
493  {"TPC2", 1 },
494  {"GArInactive", 2 },
495  {"BarrelECal", 3 },
496  {"EndcapECal", 4 },
497  {"Cryostat", 5 },
498  {"CryostatEndcap", 6 },
499  {"YokeBarrel", 7 },
500  {"YokeEndcap", 8 },
501  {"MPD", 9 }
502  };
503 
504  return;
505 
506 } // End of StructuredTree::beginJob
507 
508 ////==============================================================================
509 ////==============================================================================
510 ////==============================================================================
512 
513  auto const& ID = run.id();
514 
515  auto summaryHandle = run.getHandle<sumdata::POTSummary>(fPOTtag);
516  if (!summaryHandle) {
517  MF_LOG_DEBUG("anatree") << " No sumdata::POTSummary branch for run " << ID
518  <<" Line " << __LINE__ << " in file " << __FILE__ << std::endl;
519  return;
520  }
521 
522  sumdata::POTSummary const& RunPOT = *summaryHandle;
523  fPOT = RunPOT.TotalPOT();
524  fNSpills = RunPOT.TotalSpills();
525 
526  MF_LOG_INFO("anatree") << "POT for this file is " << fPOT
527  << " The number of spills is " << fNSpills;
528 
529 }
530 
532 
533  fHeaderTree->Fill();
534 }
535 
536 //==============================================================================
537 //==============================================================================
538 //==============================================================================
540 
541  // Is the backtracker good to go? Need to fill fBack on per-event basis
542  // not in beginJob()
543  cheat::BackTrackerCore const* const_bt = providerFrom<cheat::BackTracker>();
544  fBt = const_cast<cheat::BackTrackerCore*>(const_bt);
545  /*if ( !fBt->HasTracks() || !fBack->HasClusters() ) {
546  throw cet::exception("MatchingPerformance") << " Not enough backtracker info"
547  << " Line " << __LINE__ << " in file " << __FILE__ << std::endl;
548  }*/
549 
550  ClearVectors();
551 
552  fRun = e.run();
553  fSubRun = e.subRun();
554  fEvent = e.id().event();
555 
556  //Fill generator and MC Information
557  mf::LogDebug("StructuredTree") << "fill truth level info";
558  FillGenTree(e);
559  FillG4Tree(e);
560  fGenTree->Fill();
561  fG4Tree->Fill();
562 
563  if(fWriteDisplay){
564  mf::LogDebug("StructuredTree") << "fill display tree";
565  fDisplayTree->Fill();
566  }
567 
568  //Fill Readout Information
569  if(fAnaMode=="readout") {
570  mf::LogDebug("StructuredTree") << "fill det info";
571  FillDetTree(e);
572  fDetTree->Fill();
573  mf::LogDebug("StructuredTree") << "done.";
574  return; //no need for reco info (possible exception could be hit reco ana)
575  }
576 
577  //Fill Reco Information
578  if(fAnaMode=="reco"){
579  mf::LogDebug("StructuredTree") << "fill base level reco info";
580  FillRecoInfo(e);
581  }
582 
583  //Fill HL Reco Information
584  mf::LogDebug("StructuredTree") << "fill high level reco info";
586  fRecoTree->Fill();
587 
588  mf::LogDebug("StructuredTree") << "done.";
589 
590  return;
591 }
592 
593 //==============================================================================
594 //==============================================================================
595 //==============================================================================
597 
598  //Assns bookkeeing
599  fMCTruths.clear();
600  fMCParticles.clear();
601 
602  // genTree
603  fGIndex.clear();
604  fGTruth.clear();
605  fFSParticles.clear();
606 
607  // g4Tree
608  fG4TruthIndex.clear();
609  fG4FSIndex.clear();
610  fG4Particles.clear();
611 
612  // displayTree
613  if (fWriteDisplay) {
614  //fMCDisplay.clear();
615  fRecoDisplay.clear();
616  }
617 
618  // detTree
619  if(fAnaMode == "readout") {
620  fTPCDigits.clear();
621  fCaloDigits.clear();
622  fMuDigits.clear();
623  }
624 
625  // recoTree
626  if(fAnaMode == "reco") {
627 
628  //g4 tree
629  fSimTPCHits.clear();
630  fSimCalHits.clear();
631  //fSimTPCHitsG4P.clear(); //may not be needed. use vector of
632  //fSimCalHitsG4P.clear(); //hits for each G4Particle (assuming each G4Part has one...)
633 
634  // Hit data
635  fTPCHits.clear();
636  fCalHits.clear();
637  if(fGeo->HasMuonDetector()){
638  fSimMuHits.clear(); //g4
639  //fSimMuHitsG4P.clear();
640  fMuHits.clear(); //reco
641  }
642 
643  // TPC Cluster data
644  fTPCClusters.clear();
645  }
646 
647  // Track data
648  fTracks.clear();
649  fTrackG4PIndices.clear();
650  //TODO: for reco R&D, add Assns to TPC clusters
651 
652  // Vertex data
653  fVertices.clear();
654  fVertTrackIndices.clear();
655  fVertTrackEnds.clear();
656 
657  // Vee data
658  fVees.clear();
659  fVeeTrackIndices.clear();
660  fVeeTrackEnds.clear();
661 
662  //ECal/MuID clusters
663  fCalClusters.clear();
664  if(fGeo->HasMuonDetector()){
665  fMuClusters.clear();
666  }
667 
668  // ECAL cluster to track association info
669  fCalTrackIndices.clear(); // index of fTracks associated with fCalClusters
670  fCalTrackEnds.clear(); // Track end associated with the cluster
671  fCalG4PIndices.clear();
672 
673  return;
674 
675 } // end :StructuredTree::ClearVectors
676 
677 //==============================================================================
679 
680  //Need to keep enough info for GENIE reweighting: GTruth + MCTruth
681 
682  // ============= Get art handles ==========================================
683  // Get handles for MCinfo, also good for MCPTrajectory
684 
685  auto mcthandlelist = e.getMany<vector<simb::MCTruth> >();
686  auto gthandlelist = e.getMany<vector<simb::GTruth> >();
687 
688  vector<string> genInstances; //instances for different generator products
689 
690  //all generators produce MCTruths, some produce associated GTruth
691  for (size_t imcthl = 0; imcthl < mcthandlelist.size(); ++imcthl) {
692 
693  auto mcthandle = mcthandlelist.at(imcthl);
694  string instance = mcthandle.provenance()->productInstanceName();
695  if( std::find(genInstances.begin(),genInstances.end(),instance) == genInstances.end()) {
696  mf::LogDebug("StructuredTree::FillGenTree")
697  << "found new generator instance, '" << instance << "'";
698  genInstances.push_back(instance);
699  }
700  else
701  mf::LogWarning("StructuredTree::FillGenTree")
702  << "found repeated generator instance, '" << instance << "'";
703 
704  mf::LogDebug("StructuredTree::FillGenTree")
705  << "processing " << mcthandle->size() << " MCTruths";
706 
707  //loop over MCTruths
708  for (size_t imct = 0; imct < mcthandle->size(); imct++) {
709 
710  auto const& mct = mcthandle->at(imct); //MCTruth
711  fMCTruths.push_back(&mct);
712  //if(fEvent==994)
713  //std::cout << "neutrino in event 994 has CCNC = " << mct.GetNeutrino().CCNC() << std::endl;
714 
715  //check if MCTruth produced by GENIE
716  //TO DO: we might not want to make all nu samples reweightable
717  // TPC - yes of course;
718  // ECal - probably
719  // Dirt - probably not
720  if(mct.GeneratorInfo().generator == simb::_ev_generator::kGENIE) {
721  // for GTruth handles...
722  //for (size_t igthl = 0; igthl < gthandlelist.size(); ++igthl) {
723  for (auto const& gth : gthandlelist) {
724 
725  auto const& gt = (*gth).at(0);
726 
727  // only expect one GTruth per MCTruth
728  //if((*gthandlelist.at(igthl)).size()!=1)
729  if((*gth).size()!=1)
730  throw cet::exception("StructuredTree")
731  << "more than 1 GTruth in MCTruth! ("
732  //<< (*gthandlelist.at(igthl)).size() << ")";
733  << (*gth).size() << ")";
734 
735  //adp::GarGTruth gt((*gthandlelist.at(igthl)).at(0));
736  // need to convert vertex units from meters to cm for GENIE data
737  garana::GTruth gtout = MakeAnaGTruth( gt, fRegionNameToID.at( PointToRegion(100*gt.fVertex.Vect()) ) );
738  gtout.fVertex -= fTpcCenter;
739  fGTruth.push_back(gtout); //MakeAnaGTruth( gt, fRegionNameToID.at( PointToRegion(100*gt.fVertex.Vect()) ) ) );
740  fGIndex.push_back(fGIndex.size());
741  }
742  mf::LogDebug("StructuredTree::FillGenTree")
743  << "filled vector with " << fGTruth.size() << " GTruths";
744 
745  }//if MCTruth from GENIE
746  else{
747  fGIndex.push_back(-1); //non-GENIE gen flag
748  }
749 
750  fFSParticles.push_back({});//only one GTruth per MCTruth
751 
752  //loop over gen-level MCParticles, select FS particles only
753  for(int imcp = 0; imcp<mct.NParticles(); imcp++) {
754 
755  auto const& mcp = mct.GetParticle(imcp);
756  if(mcp.StatusCode() == 1){ //GENIE specific???
757 
758  mf::LogDebug("StructuredTree::FillGenTree")
759  << "FS particle with trackID " << (int)mcp.TrackId() << ", PDG "
760  << mcp.PdgCode() << ", " << "4-position (" << mcp.Position(0).X() << ", "
761  << mcp.Position(0).Y() << ", " << mcp.Position(0).Z() << ", "
762  << mcp.Position(0).T() << "), and "
763  << (int)mcp.NumberTrajectoryPoints() << " trajectory points";
764 
765  fFSParticles.back().push_back(MakeFSParticle(mcp));
766 
767  }//if FS particle
768  }//for MCParticles
769 
770  mf::LogDebug("StructuredTree::FillGenTree")
771  << "Processed MCTruth with " << mct.NParticles() << " particles of which "
772  << fFSParticles.back().size() << " are in the final state";
773 
774  }//for MCTruths
775  }//for MCTruth handles
776 
777 }//end FillGenTree()
778 
779 //===============================================================================
781 
782  // handle to MCParticles produced in G4 stage
783  InputTag mcptag(fGeantLabel);
784  auto MCPHandle = e.getValidHandle<vector<MCParticle>>(mcptag);
785 
786  //loop over MCParticles
787  for ( auto mcp : *MCPHandle ) {
788 
789  //if(abs(mcp.PdgCode())==12 || abs(mcp.PdgCode())==14)
790  // std::cout << "neutrino MCParticle??? (PDG = " << mcp.PdgCode()
791  // << " | trackID = " << mcp.TrackId() << ")" << std::endl;
792 
793  fMCParticles.push_back(&mcp);
794  //std::cout << "MCParticle created in " << fGeo->VolumeName(mcp.Position(0).Vect()) << std::endl;
795 
796  int parentPdg = INT_MAX;
797  int progenitorId = INT_MAX;
798  int progenitorPdg = INT_MAX;
799  vector<pair<TLorentzVector,TLorentzVector>> positions;
800  vector<pair<TLorentzVector,TLorentzVector>> momenta;
801  vector<int> regions;
802  vector<size_t> npointsPerRegion;
803 
804  if(mcp.Mother()>0) {
805  parentPdg = (fBt->FindMother(&mcp))->PdgCode();
806  auto const& progenitor = fBt->FindEve(&mcp);
807  progenitorId = progenitor->TrackId();
808  progenitorPdg = progenitor->PdgCode();
809  }
810  else {
811  //std::cout
812  mf::LogDebug("StructuredTree") << "G4 primary with trackID " << mcp.TrackId() << ", PDG " << mcp.PdgCode()
813  << ", initial 4-position (" << mcp.Position(0).X()
814  << "," << mcp.Position(0).Y() << ","
815  << mcp.Position(0).Z() << ", " << mcp.Position(0).T() << ")" ;
816  //<< std::endl;
817  }
818 
819 
820  // find regions of interest and get the entry and exit 4-vectors
821  //std::cout << "looking for regions..." << std::endl;
822  bool enter = false;
823  size_t nptsreg=0;
824  TLorentzVector *pEnter=0, *pExit=0, *xEnter=0, *xExit=0;
825  for(size_t ipt = 0; ipt < mcp.NumberTrajectoryPoints(); ipt++){
826 
827  //if particle is not in a region of interest, skip to next traj point
828  std::string regionName = PointToRegion(mcp.Position(ipt).Vect()); //fGeo->VolumeName(mcp.Position(ipt).Vect());
829  if(fRegionNameToID.at(regionName)==-1)//==fRegionNameToID.end())
830  continue;
831 
832  //std::cout << "trajectory point in " << regionName << " (" <<
833  // fRegionNameToID.at(regionName) << ")" << std::endl;;
834  //is this the last trajectory point?
835  bool last = (ipt==mcp.NumberTrajectoryPoints()-1);
836  std::string nextName;
837  if(!last) nextName = PointToRegion(mcp.Position(ipt+1).Vect());
838  //if(nextName!=regionName) std::cout << " next region is " << nextName << std::endl;
839 
840  // if the particle is entering into a region of interest
841  if(!enter) {
842  enter = true;
843  nptsreg=0;
844  nptsreg++;
845  pEnter = new TLorentzVector(mcp.Momentum(ipt));
846  xEnter = new TLorentzVector(mcp.Position(ipt));
847  regions.push_back(fRegionNameToID.at(regionName));
848 
849  // is this the only point in this region?
850  if(regionName != nextName) {
851 
852  enter = false;
853  pExit = pEnter;
854  xExit = xEnter;
855  momenta.push_back({*pEnter,*pExit});
856  positions.push_back({*xEnter,*xExit});
857  npointsPerRegion.push_back(nptsreg);
858 
859  /*if(momenta.size()==0 && !last)//first region and not last traj point
860  std::cout << "found MCParticle with single point in " << regionName << std::endl;
861  else if(momenta.size()==0 && last) //first region and not last traj point
862  std::cout << "found MCParticle with single and only point in " << regionName << std::endl;
863  else if(last) //not first region and last traj point
864  std::cout << " last point in " << regionName << " with a single point" << std::endl;
865  else //not first region and not last traj point
866  std::cout << " now it's in " << regionName << " with a single point" << std::endl; */
867  }
868  }//if now entering ROI
869 
870  if(enter)
871  nptsreg++;
872 
873  //if last point or next region is not this one (this is the exit point)
874  if(enter && //if it entered, it can exit and ...
875  (last || ( !last && //it's the last point or if not...
876  regionName != nextName ) ) ) { //the next region isn't this one
877 
878  /*if(momenta.size()==0 && !last) //first region but not last traj point
879  std::cout << "found MCParticle in " << regionName << std::endl;
880  else if(momenta.size()==0 && last) //first region and last traj point
881  std::cout << "found MCParticle with first and last point in " << regionName << std::endl;
882  else if(last)//not first region but last traj point
883  std::cout << " last point in " << regionName << std::endl;
884  else //not first region and not last traj point
885  std::cout << " now it's in " << regionName << std::endl;
886 
887  std::cout << "number of traj. points in this region = " << nptsreg << std::endl;*/
888 
889  enter = false;
890  pExit = new TLorentzVector(mcp.Momentum(ipt));
891  xExit = new TLorentzVector(mcp.Position(ipt));
892 
893  momenta.push_back({*pEnter,*pExit});
894  positions.push_back({*xEnter,*xExit});
895  npointsPerRegion.push_back(nptsreg);
896 
897  }//if now exiting ROI
898 
899  }//for trajectory points
900  //std::cout << "done." << std::endl;
901  //if(momenta.size()!=0)
902  // std::cout << " filled momenta/positions with " << momenta.size() << " pairs" << std::endl;
903 
904  // sanity check
905  if(momenta.size()!=positions.size()) std::cout << "G4Particle: positions-momenta size mismatch" << std::endl;
906  if(momenta.size()!=regions.size()) std::cout << "G4Particle: positions/momenta - regions size mismatch" << std::endl;
907 
908  // make a G4Particle
909  fG4Particles.push_back(MakeG4Particle(mcp,parentPdg,progenitorPdg,progenitorId,positions,momenta,regions,npointsPerRegion));
910 
911  /*bool foundfs = false;
912  for(UInt_t index=0; index<fFSParticles.size(); index++) {
913  if(fFSParticles[index].TrackId() == progenitorId) {
914  fG4FSIndex.push_back(index);
915  foundfs = true;
916  break;
917  }
918  }
919  if(!foundfs) {
920  std::cout <<
921  "WARNING in StructuredTree_module::FillG4Tree: FSParticle association not found!"
922  << std::endl;
923  fG4FSIndex.push_back(UINT_MAX); //need to push back something or association ordering is broken
924  }*/
925 
926  //find associated MCTruth
927  auto mcmatch = fBt->ParticleToMCTruth(&mcp);
928  bool found = false;
929  for(size_t i=0; i<fMCTruths.size(); i++){
930  if(fMCTruths[i]==mcmatch.get()) { //compare pointers to check MCTruth equality
931  found = true;
932  fG4TruthIndex.push_back(i);
933 
934  bool foundfs = false;
935  for(UInt_t index=0; index<fFSParticles.size(); index++) {
936  if(fFSParticles[i][index].TrackId() == progenitorId) {
937  fG4FSIndex.push_back(index);
938  foundfs = true;
939  break;
940  }
941  }
942  if(!foundfs) {
943  //std::cout <<
944  //"WARNING in StructuredTree_module::FillG4Tree: FSParticle association not found!"
945  //<< std::endl;
946  fG4FSIndex.push_back(UINT_MAX); //need to push back something or association ordering is broken
947  }
948 
949  break;
950  }
951  }
952  if(!found){
953  mf::LogWarning("StructuredTree::FillG4Tree")
954  << "no MCTruth found for MCParticle";
955  fG4TruthIndex.push_back(UINT32_MAX);
956  }
957 
958  if(fWriteDisplay){
959  //const TDatabasePDG* databasePDG = TDatabasePDG::Instance();
960  //const TParticlePDG* definition = databasePDG->GetParticle( mcp.PdgCode() );
961  //No charge don't store the trajectory
962  //if (definition==nullptr || definition->Charge() == 0) continue;
963 
964  //adp::MCDisplayTrack mcdis(mcp);
965  //fMCDisplay.push_back(mcdis);
966  }
967 
968  }//for MCParticles
969 
970  // Get handles for SimHits used for reco R&D
971  if(fAnaMode == "reco") {
972 
973  InputTag geanttag(fGeantLabel); //TPC
974  InputTag calgeanttag(fGeantLabel, fGeantInstanceCalo); //ECal
975  auto TPCSimHitHandle = e.getValidHandle< vector<sdp::EnergyDeposit> >(geanttag); //TPC
976  auto CalSimHitHandle = e.getValidHandle< vector<sdp::CaloDeposit> >(calgeanttag); //ECal
977  // Note: no backtracker for sim hit(s) <-> MCParticle so we do it the hard way...
978  //
979 
980  fSimTPCHits.resize(fG4Particles.size()); //want MCParticle to have same index as its hits
981  fSimCalHits.resize(fG4Particles.size());
982  if(fGeo->HasMuonDetector())
983  fSimMuHits.resize(fG4Particles.size());
984 
985  //try to find SimHits with matching MCParticle
986  // there can (and usually will) be multiple hits/particle
987  size_t nnomatch = 0;
988  for(size_t ig4p=0; ig4p<fG4Particles.size(); ig4p++){
989 
990  bool hasmatched = false;
991  fSimTPCHits.push_back({});
992  fSimCalHits.push_back({});
993 
994  // TPC
995  for( auto const& hit : *TPCSimHitHandle ){
996  if(hit.TrackID() == fG4Particles[ig4p].TrackID()){
997  fSimTPCHits[ig4p].push_back(hit);
998  hasmatched = true;
999  }
1000  }//for TPC hits
1001 
1002  // Save simulation ecal hit info
1003  for ( auto const& hit : *CalSimHitHandle ) {
1004  if(hit.TrackID() == fG4Particles[ig4p].TrackID()){
1005  fSimCalHits[ig4p].push_back(hit);
1006  hasmatched = true;
1007  }
1008  }//for ECal hits
1009 
1010  // Save simulation muon system hit info
1011  if(fGeo->HasMuonDetector()) {
1012 
1013  InputTag mugeanttag(fGeantLabel, fGeantInstanceMuID); //MuID
1014  auto MuSimHitHandle = e.getValidHandle< vector<sdp::CaloDeposit> >(mugeanttag); //MuID
1015  fSimMuHits.push_back({});
1016 
1017  for ( auto const& hit : *MuSimHitHandle ) {
1018  if(hit.TrackID() == fG4Particles[ig4p].TrackID()) {
1019  fSimMuHits[ig4p].push_back(hit);
1020  hasmatched = true;
1021  }
1022  }//for MuID hits
1023 
1024  }//if MuID
1025  if(!hasmatched)
1026  nnomatch++;
1027 
1028  }//for G4Particles
1029 
1030 
1031  if(nnomatch>0){
1032  mf::LogWarning("StructuredTree::FillG4Tree")
1033  << " found " << nnomatch << " G4Particle(s) with no matching SimHit."
1034  << " SimHit -> G4Particle associations corrupted!";
1035  }
1036 
1037  }//if mode reco
1038 
1039 }//FillG4Tree
1040 
1041 //==============================================================================
1042 
1044 
1045  // Get handles for RawDigits
1046  InputTag tpcdigittag(fTPCDigitLabel);
1048 
1049  // request valid handle -> throws exception if product not found
1050  auto TPCDigitHandle = e.getValidHandle< vector<raw::RawDigit> >(tpcdigittag);
1051  auto CalDigitHandle = e.getValidHandle< vector<raw::CaloRawDigit> >(caldigittag);
1052 
1053  //TPC digits
1054  for( auto const& digit : *TPCDigitHandle)
1055  fTPCDigits.push_back(digit);
1056 
1057  // save ecal raw digits info
1058  for ( auto const& digit : *CalDigitHandle ) {
1059  fCaloDigits.push_back(digit);
1060  }
1061 
1062  // save muon system raw digits info if MuID present
1063  if(fGeo->HasMuonDetector()) {
1064 
1066  auto MuDigitHandle = e.getValidHandle< vector<raw::CaloRawDigit> >(mudigittag);
1067 
1068  for ( auto const& digit : *MuDigitHandle ) {
1069  fMuDigits.push_back(digit);
1070  }
1071  }
1072 }//FillDetTree
1073 
1074 //==============================================================================
1075 // base level reconstruction products (used for reco R&D mode)
1077 
1078 
1079  // reco hits
1080  // Get handles
1081  InputTag tpchittag(fHitLabel);
1083  auto TPCHitHandle = e.getValidHandle< vector<rec::Hit> >(tpchittag);
1084  auto CalHitHandle = e.getValidHandle< vector<rec::CaloHit> >(calhittag);
1085 
1086  // save reco hits from the TPC
1087  for ( auto const& hit : *TPCHitHandle ) {
1088  fTPCHits.push_back(hit);
1089  }
1090 
1091 
1092  // save reco hits from the ECal
1093  for ( auto const& hit : *CalHitHandle ) {
1094  fCalHits.push_back(hit);
1095  }
1096 
1097  // save reco hits from the MuID (if present)
1098  if(fGeo->HasMuonDetector()) {
1099 
1101  auto MuHitHandle = e.getValidHandle< vector<rec::CaloHit> >(muhittag);
1102 
1103  for ( auto const& hit : *MuHitHandle ) {
1104  fMuHits.push_back(hit);
1105  }
1106  }
1107 
1108  // reco clusters
1109  // Get handles
1110  InputTag tpcclustertag(fTPCClusterLabel);
1111  InputTag tracktag(fTrackLabel);
1112  auto TPCClusterHandle = e.getValidHandle< vector<rec::TPCCluster> >(tpcclustertag);
1113  //auto TrackHandle = e.getValidHandle< vector<rec::Track> >(tracktag);
1114  //art::FindManyP<rec::TPCCluster>* findManyTPCClusters = NULL;
1115  //findManyTPCClusters = new art::FindManyP<rec::TPCCluster>(TrackHandle,e,fTrackLabel);
1116 
1117  //FIX ME: ASSOCIATIONS
1118  // save clusters in the TPC. For some reason, can't get FindOneP<rec::Track> or
1119  // FindManyP<rec::Track> to work; seems the underlying Assn isn't found. Have
1120  // to FindManyP<TPCCluster> instead and iterate if (fWriteTracks). :(
1121  for ( auto const& TPCCluster : (*TPCClusterHandle) ) {
1122 
1123  fTPCClusters.push_back(TPCCluster);
1124  //TODO: fix assns
1125  /*Int_t trackForThisTPCluster = -1;
1126  size_t iTrack = 0;
1127  for ( auto const& track : (*TrackHandle) ) {
1128  for (size_t iCluster=0; iCluster<track.NHits(); iCluster++) {
1129  auto const& trackedCluster =
1130  *(findManyTPCClusters->at(iTrack).at(iCluster));
1131  if (TPCCluster==trackedCluster) {
1132  trackForThisTPCluster = track.getIDNumber();
1133  // No cluster is in 2 tracks (don't mess up dE/dx!)
1134  goto pushit; // break 2 loops
1135  }
1136  }
1137  iTrack++;
1138  }
1139  pushit:
1140  fTPCClusterTrkIDNumber.push_back(trackForThisTPCluster);*/
1141  }//for TPCClusters
1142 
1143 }//FillReco
1144 
1145 //==============================================================================
1146 
1148 
1149 
1150  // Get handles for Track, TrackIoniz, Vertex, Vee and also Assn's
1151  InputTag tracktag(fTrackLabel);
1152  InputTag iontag(fTrackLabel);
1153  InputTag verttag(fVertexLabel);
1154  InputTag veetag(fVeeLabel);
1155  InputTag calclustertag(fClusterLabel); //instance too?
1156  auto TrackHandle = e.getValidHandle< vector<rec::Track> >(tracktag);
1157  //auto TrackIonHandle = e.getValidHandle< vector<rec::TrackIoniz> >(iontag);
1158  auto VertexHandle = e.getValidHandle< vector<rec::Vertex> >(verttag);
1159  auto VeeHandle = e.getValidHandle< vector<rec::Vee> >(veetag);
1160  auto CalClusterHandle = e.getValidHandle< vector<rec::Cluster> >(calclustertag);
1161 
1162  //associations (FIX ME)
1163  art::FindOneP<rec::TrackIoniz>* findIonization = NULL;
1164  findIonization = new art::FindOneP<rec::TrackIoniz>(TrackHandle,e,fTrackLabel);
1165 
1166  // Vertices Assn's to Tracks
1167  art::FindManyP<rec::Track, rec::TrackEnd>* findManyTrackEnd = NULL;
1168  findManyTrackEnd = new art::FindManyP<rec::Track, rec::TrackEnd>(VertexHandle,e,fVertexLabel);
1169 
1170  // Vees Assn's to Tracks
1171  art::FindManyP<rec::Track, rec::TrackEnd>* findManyVeeTrackEnd = NULL;
1172  findManyVeeTrackEnd = new art::FindManyP<rec::Track, rec::TrackEnd>(VeeHandle,e,fVeeLabel);
1173 
1174  // ECal cluster Assn's to Tracks
1175  // TODO: add track end assns when available (add on to BackTrackerCore)
1176  art::FindManyP<rec::Track/*, rec::TrackEnd*/>* findManyCalTrackEnd = NULL;
1177  findManyCalTrackEnd = new art::FindManyP<rec::Track/*, rec::TrackEnd*/>(CalClusterHandle,e,fECALAssnLabel);
1178  //art::FindManyP<MCParticle>* findManyCalMCP = NULL;
1179  //findManyCalMCP = new art::FindManyP<MCParticle>(CalClusterHandle,e,fECALAssnLabel);
1180 
1181  // save per-track info
1182  size_t iTrack = 0;
1183  vector<size_t> trackIDs;
1184  for ( auto /*const&*/ track : *TrackHandle ) { //backtracker takes ptr to non-const obj
1185 
1186  //get track -> G4Particle Assns
1187  vector<pair<MCParticle*,float>> trackmcps = fBt->TrackToMCParticles(&track); //MCParticle w/fraction energy contributed to track
1188  //std::cout << "size of track <-> G4p vec from BT: " << trackmcps.size() << std::endl;
1189  vector<UInt_t> indices;
1190  for(auto const& mcpe : trackmcps){
1191  //std::cout << "looking for G4P match to associated match MCP with track ID, " << mcpe.first->TrackId() << std::endl;
1192  for(size_t i=0; i< fG4Particles.size(); i++) {
1193  //std::cout << " check G4Particle " << i << " with track ID, " << fG4Particles[i].TrackID() << std::endl;
1194  if( mcpe.first->TrackId() == fG4Particles[i].TrackID()) //fMCParticles and fG4Particles have same mapping
1195  indices.push_back(i);
1196  }
1197  }
1198 
1199  // std::cout << "found " << indices.size() << " track <-> G4P matches" << std::endl;
1200  fTrackG4PIndices.push_back(indices);
1201 
1202  //Reconstructed momentum forward and backward
1203  vector< pair<int, float> > pidF = processPIDInfo( track.Momentum_beg() );
1204  vector< pair<int, float> > pidB = processPIDInfo( track.Momentum_end() );
1205 
1206  //average ionization
1207  float avgIonF = 0., avgIonB=0.;
1208  if (findIonization->isValid()) {
1209  // No calibration for now. Someday this should all be in reco
1210  rec::TrackIoniz ionization = *(findIonization->at(iTrack));
1211  processIonizationInfo(ionization, fIonizTruncate, avgIonF, avgIonB);
1212  }
1213 
1214  // track truth-matching info
1215  TVector3 trkVtx(track.Vertex()[0],track.Vertex()[1],track.Vertex()[2]);
1216  vector<art::Ptr<rec::Hit>> hits = fBt->TrackToHits(&track); // not time ordered
1217  std::sort(hits.begin(),hits.end(),
1218  [trkVtx] ( const art::Ptr<rec::Hit>& hl, const art::Ptr<rec::Hit>& hr ) -> bool {
1219  TVector3 rhitl(hl->Position()[0],hl->Position()[1],hl->Position()[2]);
1220  TVector3 rhitr(hr->Position()[0],hr->Position()[1],hr->Position()[2]);
1221  return (trkVtx-rhitl).Mag() < (trkVtx-rhitr).Mag();
1222  });
1223 
1224  // first and last rec::Hit
1225  auto hitIdesBeg = fBt->HitToHitIDEs(*(hits.begin()));
1226  auto hitIdesEnd = fBt->HitToHitIDEs(*(hits.end()-1));
1227  vector<pair<UInt_t,TLorentzVector>> truePosBeg, trueMomBeg, truePosEnd, trueMomEnd;
1228  vector<std::pair<int,float>> trueEnergy;
1229 
1230  for(auto const& ide : hitIdesBeg) {
1231  truePosBeg.push_back(std::make_pair(ide.trackID , ide.position));
1232  trueMomBeg.push_back(std::make_pair(ide.trackID , ide.momentum));
1233  }
1234 
1235 
1236  for(auto const& ide : hitIdesEnd) {
1237  truePosEnd.push_back(std::make_pair(ide.trackID , ide.position));
1238  trueMomEnd.push_back(std::make_pair(ide.trackID , ide.momentum));
1239  }
1240 
1241  std::vector<std::pair<simb::MCParticle*,float>> trkmcps = fBt->TrackToMCParticles(&track);
1242  double etot = fBt->TrackToTotalEnergy(&track);
1243  for(auto const& mcpfrac : trkmcps) {
1244  trueEnergy.push_back(std::make_pair(mcpfrac.first->TrackId(),etot*mcpfrac.second));
1245  }
1246 
1247  // make a garana::Track
1248  trackIDs.push_back(track.getIDNumber());
1249  fTracks.push_back(MakeAnaTrack(track, pidF, pidB, avgIonF, avgIonB,truePosBeg,truePosEnd,trueMomBeg,
1250  trueMomEnd, trueEnergy) );
1251 
1252 
1253  iTrack++;
1254  } //for tracks
1255 
1256  // save Vertex and Track-Vertex association info
1257  size_t iVertex = 0;
1258  for ( auto const& vertex : *VertexHandle ) {
1259 
1260  fVertices.push_back(MakeAnaVtx(vertex));
1261  fVertTrackIndices.push_back({});
1262  fVertTrackEnds.push_back({});
1263 
1264 
1265  int nVertexedTracks = 0;
1266  if ( findManyTrackEnd->isValid() ) {
1267  nVertexedTracks = findManyTrackEnd->at(iVertex).size();
1268  }
1269  //fVertexN.push_back(nVertexedTracks); //number of tracks assced with this vertex
1270 
1271  //int vertexCharge = 0;
1272  for (int iVertexedTrack=0; iVertexedTrack<nVertexedTracks; ++iVertexedTrack) {
1273 
1274  // Get this vertexed track.
1275  rec::Track track = *(findManyTrackEnd->at(iVertex).at(iVertexedTrack));
1276  rec::TrackEnd fee = *(findManyTrackEnd->data(iVertex).at(iVertexedTrack));
1277 
1278  // find its index in the track list
1279  for(size_t itrk=0; itrk<fTracks.size(); itrk++){
1280  if(trackIDs[itrk] == track.getIDNumber()){
1281  fVertTrackEnds.back().push_back(fee);
1282  fVertTrackIndices.back().push_back(itrk);
1283  break;
1284  }
1285  }
1286 
1287  // add Vertex charge?
1288  /*if (fee==rec::TrackEndBeg) {
1289  vertexCharge += track.ChargeBeg();
1290  } else {
1291  vertexCharge += track.ChargeEnd();
1292  }*/
1293  }
1294 
1295  //fVertexQ.push_back(vertexCharge);
1296  ++iVertex;
1297  } // end loop over VertexHandle
1298 
1299  // save Vee and Track-Vee association info
1300  size_t iVee = 0;
1301  for ( auto const& vee : *VeeHandle ) {
1302 
1303  fVees.push_back(MakeAnaVee(vee));
1304  fVeeTrackIndices.push_back({});
1305  fVeeTrackEnds.push_back({});
1306 
1307  int nVeeTracks = 0;
1308  if ( findManyVeeTrackEnd->isValid() ) {
1309  nVeeTracks = findManyVeeTrackEnd->at(iVee).size();
1310  }
1311 
1312  for (int iVeeTrack=0; iVeeTrack<nVeeTracks; ++iVeeTrack) {
1313 
1314  // Get this vertexed track.
1315  rec::Track track = *(findManyVeeTrackEnd->at(iVee).at(iVeeTrack));
1316  rec::TrackEnd fee = *(findManyVeeTrackEnd->data(iVee).at(iVeeTrack));
1317 
1318  // find its index in the track list
1319  for(size_t itrk=0; itrk<fTracks.size(); itrk++){
1320  if(trackIDs[itrk] == track.getIDNumber()){
1321  fVeeTrackIndices.back().push_back(itrk);
1322  fVeeTrackEnds.back().push_back(fee);
1323  break;
1324  }
1325  }
1326  }
1327 
1328  ++iVee;
1329  } // for Vees
1330 
1331  // Get info for ECal clusters and for ECAL-matched tracks
1332  size_t iCluster = 0;
1333  size_t n0edep = 0; // number of clusters with no associated true energy deposits
1334  for ( auto cluster : *CalClusterHandle ) {
1335 
1336  size_t n0ide=0; // number of hits with no associated CalIDEs
1337  vector<std::pair<int,float>> edeps; // trackID , true deposited energy [GeV]
1338  std::string regionName = PointToRegion(TVector3(cluster.Position())); //fGeo->VolumeName(mcp.Position(ipt).Vect());
1339  int clustreg = fRegionNameToID.at(regionName);
1340  const vector<art::Ptr<rec::CaloHit>> hits = fBt->ClusterToCaloHits(&cluster);
1341  //if(hits.size()==0) std::cout << "cluster " << iCluster << ": hits is empty!" << std::endl;
1342  //else std::cout << "cluster " << iCluster << " with " << hits.size() << " hits" << std::endl;
1343  for(auto const& hit : hits) {
1344 
1345  auto const& ides = fBt->CaloHitToCalIDEs(hit);
1346  if(ides.size()==0) n0ide++; //std::cout << "have a hit, but ides is empty!" << std::endl;
1347  for(auto const& ide : ides) {
1348 
1349  std::pair<int,float> trkdep = std::make_pair(ide.trackID,ide.energyTot);
1350  if(std::find(edeps.begin(),edeps.end(),trkdep) == edeps.end()) {
1351  edeps.push_back(trkdep);
1352  }
1353  else {
1354  (*(std::find(edeps.begin(),edeps.end(),trkdep))).second+=trkdep.second;
1355  }
1356 
1357  }// for calo IDEs
1358 
1359  }// for calo hits
1360 
1361  if(hits.size()!=0 && n0ide>0) mf::LogDebug("FillHighLevelReco")
1362  << " hits with no IDEs: " << n0ide << " of " << hits.size()
1363  << " hits affected (" << 100.0*(hits.size()-n0ide)/hits.size()
1364  << " %)"; // << std::endl;
1365 
1366  if(edeps.size()==0) {
1367  mf::LogDebug("FillHighLevelReco") << "have a cluster, but edeps is empty!";
1368  edeps.push_back({-1,-1});
1369  n0edep++;
1370  }
1371  //else std::cout << " found " << edeps.size() << " truth edeps" << std::endl;
1372 
1373  fCalClusters.push_back(MakeAnaCalCluster(cluster,clustreg,edeps));
1374  fCalTrackIndices.push_back({});
1375  fCalTrackEnds.push_back({});
1376  fCalG4PIndices.push_back({});
1377 
1378  size_t nMatch = 0;
1379  if ( findManyCalTrackEnd->isValid() ) {
1380  nMatch = findManyCalTrackEnd->at(iCluster).size();
1381  }
1382  for (size_t itrk=0; itrk<nMatch; itrk++) {
1383  rec::Track track = *(findManyCalTrackEnd->at(iCluster).at(itrk));
1384  //TODO: add track ends when they become available
1385  //rec::TrackEnd fee = *(findManyCalTrackEnd->data(iCluster).at(itrk));
1386 
1387  for(size_t imatch=0; imatch<fTracks.size(); imatch++){
1388  if(trackIDs[imatch] == track.getIDNumber()){
1389  fCalTrackIndices.back().push_back(imatch);
1390  //fCalTrackEnds.back().push_back(fee);
1391  break;
1392  }
1393  }
1394 
1395  }//for matched tracks
1396  //std::cout << "filled ECal cluster -> track associations. on to MCParticles..." << std::endl;
1397 
1398  // list of MCParticles associated with this cluster and the fraction of the total energy contributed
1399  vector<std::pair<MCParticle*,float>> clustToMCPs = fBt->ClusterToMCParticles(&cluster);
1400 
1401  //need to find MCParticle index
1402  for(size_t imcp=0; imcp<clustToMCPs.size(); imcp++) {
1403 
1404  vector<int> pdgs;
1405  for(size_t index=0; index<fG4Particles.size(); index++){
1406 
1407  if(fG4Particles.at(index).TrackID() == clustToMCPs.at(imcp).first->TrackId()){
1408  pdgs.push_back(fG4Particles.at(index).PDG());
1409  fCalG4PIndices.back().push_back(index);
1410  break;
1411  }// if cluster and MCParticle track IDs match
1412  }// for G4Particles
1413  }// for cluster-MCParticle matches
1414  //std::cout << "filled ECal cluster -> MCParticle associations" << std::endl;
1415 
1416  /*const vector<art::Ptr<rec::CaloHit>> hits = fBt->ClusterToCaloHits(&cluster);
1417  for(auto const& hit : hits) {
1418 
1419  const vector<sdp::CalIDE> ides = CaloHitToCalIDEs(hit);
1420  for(auto const& ide : ides) {
1421 
1422 
1423 
1424  }
1425 
1426  }// for calo hits*/
1427 
1428 
1429  iCluster++;
1430  }// for ECal clusters
1431  //std::cout << "number ECal clusters: " << iCluster << std::endl;
1432  //std::cout << "cluster truth matching 'efficiency': " << 1.0*(iCluster-n0edep)/iCluster << std::endl;
1433 
1434 
1435  return;
1436 
1437 } // end FillHighLevelReco()
1438 
1439 
1440 
1441 //==============================================================================
1442 //==============================================================================
1443 // Helper Functions
1444 //==============================================================================
1445 
1446 // determine if point could be in a ROI
1448 
1449  std::string region = "Unknown";
1450  std::string volName = fGeo->VolumeName(point);
1451 
1452  //only care about volumes in MPD
1453  if( fGeo->PointInMPD(point) ) {
1454 
1455  region = "MPD";
1456 
1457  //GArTPC->TPCChamber->TPCGas->TPCDrift
1458  if( fGeo->PointInGArTPC(point) ) {
1459  region = "TPC";
1460  if(volName.find("1")!=std::string::npos)
1461  region += "1";
1462  else if(volName.find("2")!=std::string::npos)
1463  region += "2";
1464  else
1465  region = "GArInactive";
1466  }
1467  else if ( fGeo->PointInECALBarrel(point) ) region = "BarrelECal";
1468  else if ( fGeo->PointInECALEndcap(point) ) region = "EndcapECal";
1469 
1470  //FIXME: probably missing the daughter volumes below
1471  else if ( volName == "volCryostat" )
1472  region = "Cryostat";
1473 
1474  else if ( volName == "volEndcapCryostat" )
1475  region = "EndcapCryostat";
1476 
1477  else if ( volName == "volYokeBarrel" )
1478  region = "YokeBarrel";
1479 
1480  else if ( volName == "volYokeEndcap" )
1481  region = "YokeEndcap";
1482  }
1483 
1484  return region;
1485 }
1486 
1487 // Process ionization. Eventually this moves into the reco code.
1489  float& forwardIonVal, float& backwardIonVal) {
1490 
1491  // NO CALIBRATION SERVICE FOR NOW
1492 
1493  std::vector<std::pair<float,float>> SigData = ion.getFWD_dSigdXs();
1494  forwardIonVal = processOneDirection(SigData, ionizeTruncate);
1495 
1496  SigData = ion.getBAK_dSigdXs();
1497  backwardIonVal = processOneDirection(SigData, ionizeTruncate);
1498 
1499  return;
1500 }
1501 
1502 
1503 
1504 float gar::StructuredTree::processOneDirection(std::vector<std::pair<float,float>> SigData,
1505  float ionizeTruncate) {
1506 
1507  std::vector<std::pair<float,float>> dEvsX; // Ionization vs distance along track
1508 
1509  // The first hit on the track never had its ionization info stored. Not a problem
1510  // really. Each pair is a hit and the step along the track that ends at the hit
1511  // For the last hit, just take the step from the n-1 hit; don't guess some distance
1512  // to (nonexistant!) n+1 hit. Using pointer arithmetic because you are a real K&R
1513  // C nerd! Except that C++ doesn't know you are such a nerd and if
1514  // SigData.size()==0, then SigData.end()-1 is 0xFFFFFFFFFFFFFFF8.
1515  if (SigData.size()==0) return 0.0;
1516  float distAlongTrack = 0;
1517  std::vector<std::pair<float,float>>::iterator littlebit = SigData.begin();
1518  for (; littlebit<(SigData.end()-1); ++littlebit) {
1519  float dE = std::get<0>(*littlebit);
1520  // tpctrackfit2_module.cc fills the TrackIoniz data product so that
1521  // this quantity is really dL > 0 not dX, a coordinate on the drift axis
1522  float dX = std::get<1>(*littlebit);
1523  distAlongTrack += dX; // But count full step to get hit position on track
1524  // Take dX to be 1/2 the previous + last segment
1525  dX += std::get<1>(*(littlebit+1));
1526  float dEdX = dE/(0.5*dX);
1527 
1528  std::pair pushme = std::make_pair(dEdX,distAlongTrack);
1529  dEvsX.push_back( pushme );
1530  }
1531 
1532  // Get the truncated mean; first sort then take mean
1533  std::sort(dEvsX.begin(),dEvsX.end(), lessThan_byE);
1534 
1535  // Get the dEdX vs length data, truncated.
1536  int goUpTo = ionizeTruncate * dEvsX.size() +0.5;
1537  if (goUpTo > (int)dEvsX.size()) goUpTo = dEvsX.size();
1538  int i = 1; float returnvalue = 0;
1539  littlebit = dEvsX.begin();
1540  for (; littlebit<dEvsX.end(); ++littlebit) {
1541  returnvalue += std::get<0>(*littlebit);
1542  ++i;
1543  if (i>goUpTo) break;
1544  }
1545  returnvalue /= goUpTo;
1546  return returnvalue;
1547 }
1548 
1549 //==============================================================================
1550 //==============================================================================
1551 //==============================================================================
1552 vector< pair<int, float> > gar::StructuredTree::processPIDInfo( float p )
1553 {
1554  vector<string> recopnamelist = {"#pi", "#mu", "p", "K", "d", "e"};
1555  vector<int> pdg_charged = {211, 13, 2212, 321, 1000010020, 11};
1556  vector< pair<int, float> > pid;
1557  pid.resize(6);
1558 
1559  int qclosest = 0;
1560  float dist = 100000000.;
1561  CLHEP::RandFlat FlatRand(fEngine);
1562 
1563  for (int q = 0; q < 501; ++q)
1564  {
1565  //Check the title and the reco momentum take only the one that fits
1566  string fulltitle = m_pidinterp[q]->GetTitle();
1567  unsigned first = fulltitle.find("=");
1568  unsigned last = fulltitle.find("GeV");
1569  string substr = fulltitle.substr(first+1, last - first-1);
1570  float pidinterp_mom = std::atof(substr.c_str());
1571  //calculate the distance between the bin and mom, store the q the closest
1572  float disttemp = std::abs(pidinterp_mom - p);
1573 
1574  if( disttemp < dist ){
1575  dist = disttemp;
1576  qclosest = q;
1577  }
1578  } // closes the "pidmatrix" loop
1579 
1580  //Compute all the probabities for each type of true to reco
1581  //loop over the columns (true pid)
1582  for (int pidm = 0; pidm < 6; ++pidm)
1583  {
1584  //loop over the columns (true pid)
1585  vector< pair<float, string> > v_prob;
1586 
1587  //loop over the rows (reco pid)
1588  for (int pidr = 0; pidr < 6; ++pidr)
1589  {
1590  string recoparticlename = m_pidinterp[qclosest]->GetYaxis()->GetBinLabel(pidr+1);
1591  float prob = m_pidinterp[qclosest]->GetBinContent(pidm+1, pidr+1);
1592  //Need to check random number value and prob value then associate the recopdg to the reco prob
1593  v_prob.push_back( std::make_pair(prob, recoparticlename) );
1594  }
1595 
1596  //Compute the pid from it
1597  if(v_prob.size() > 1)
1598  {
1599  //Order the vector of prob
1600  std::sort(v_prob.begin(), v_prob.end());
1601  //Throw a random number between 0 and 1
1602  float random_number = FlatRand.fire();
1603  //Make cumulative sum to get the range
1604  std::partial_sum(v_prob.begin(), v_prob.end(), v_prob.begin(), [](const P& _x, const P& _y){return P(_x.first + _y.first, _y.second);});
1605 
1606  for(size_t ivec = 0; ivec < v_prob.size()-1; ivec++)
1607  {
1608  if( random_number < v_prob.at(ivec+1).first && random_number >= v_prob.at(ivec).first )
1609  {
1610  pid.push_back( std::make_pair(pdg_charged.at( std::distance( recopnamelist.begin(), std::find(recopnamelist.begin(), recopnamelist.end(), v_prob.at(ivec+1).second) ) ), v_prob.at(ivec+1).first) );
1611  }
1612  }//for probs
1613  }//if found
1614  else
1615  {
1616  pid.push_back( std::make_pair(pdg_charged.at( std::distance( recopnamelist.begin(), std::find(recopnamelist.begin(), recopnamelist.end(), v_prob.at(0).second) ) ), v_prob.at(0).first) );
1617  }
1618  }//compute probabilities
1619 
1620  //return a vector of pid and prob
1621  return pid;
1622 
1623 }//processPIDInfo()
1624 
1625 /*string gar::StructuredTree::GetGenCodeString(const simb::MCTruth& mct){
1626 
1627  string gen = "";
1628  auto code = mct.GeneratorInfo().generator;
1629 
1630  if (code == simb::_ev_generator::kGENIE) gen = "genie";
1631  else if (code == simb::_ev_generator::kCRY) gen = "cry";
1632  else if (code == simb::_ev_generator::kCRY) gen = "single";
1633  else {
1634  gen = "other";
1635  std::cout << "Warning: unrecognized generator code encountered!" << std::endl;
1636  }
1637 
1638  return gen;
1639  }*/
1640 
vector< vector< sdp::CaloDeposit > > fSimCalHits
base_engine_t & createEngine(seed_t seed)
std::vector< CalIDE > CaloHitToCalIDEs(art::Ptr< rec::CaloHit > const &hit) const
string fVeeLabel
module label for conversion/decay vertexes rec:Vee
StructuredTree & operator=(StructuredTree const &)=delete
int TrackEnd
Definition: Track.h:32
vector< vector< UInt_t > > fVeeTrackIndices
index of fTracks associated with fVees
void FillDetTree(Event const &e)
extracts readout sim products
string fCaloHitLabel
module label for reco calo hits rec::CaloHit
std::vector< art::Ptr< rec::Hit > > const TrackToHits(rec::Track *const t)
RunID id() const
Definition: Run.cc:17
art::Ptr< simb::MCTruth > const ParticleToMCTruth(simb::MCParticle *const p) const
string fECALAssnLabel
module label for track-clusters associations
string fGeantLabel
module label for geant4 simulated hits
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
unsigned int ID
bool PointInECALEndcap(TVector3 const &point) const
vector< const simb::MCTruth * > fMCTruths
virtual void beginJob() override
bool PointInGArTPC(TVector3 const &point) const
garana::FSParticle MakeFSParticle(const simb::MCParticle &mcp)
Definition: AnaUtils.cxx:29
struct vector vector
bool PointInMPD(TVector3 const &point) const
std::unordered_map< int, TH2F * > m_pidinterp
virtual void endRun(art::Run const &run) override
void ClearVectors()
clear all vectors and reset counters
void FillRecoInfo(Event const &e)
extracts base level reco products
const std::string instance
float TPCXCent() const
Returns the X location of the center of the TPC in cm.
Definition: GeometryCore.h:778
std::pair< float, std::string > P
string fMuDigitInstance
Instance name MuID for raw::CaloRawDigit.
Description of geometry of one entire detector.
Definition: GeometryCore.h:436
vector< vector< UInt_t > > fVertTrackIndices
index of fTracks associated with fVertices
string fClusterLabel
module label for calo clusters rec::Cluster
Int_t fRun
number of the run being processed
string fGeantInstanceMuID
Instance name MuID for sdp::CaloDeposit.
vector< vector< Int_t > > fVertTrackEnds
which fTrack end belongs to this vertex
Cluster finding and building.
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:25
vector< vector< sdp::CaloDeposit > > fSimMuHits
Particle class.
string filename
Definition: train.py:213
string fCalDigitInstance
Instance name ECAL for raw::CaloRawDigit.
vector< rec::CaloHit > fMuHits
vector< vector< Int_t > > fVeeTrackEnds
track end associated with fVees
vector< vector< sdp::EnergyDeposit > > fSimTPCHits
several "hits" per MCParticle
garana::Vee MakeAnaVee(const rec::Vee &vee)
Definition: AnaUtils.cxx:67
#define UINT32_MAX
Definition: code.cpp:104
vector< raw::CaloRawDigit > fCaloDigits
double dEdX(double KE, const simb::MCParticle *part)
Definition: Run.h:17
int TrackId() const
Definition: MCParticle.h:210
double const & TotalPOT() const
Definition: POTSummary.h:45
garana::CaloCluster MakeAnaCalCluster(const rec::Cluster &clust, const int &region, const std::vector< std::pair< int, float >> &edeps)
Definition: AnaUtils.cxx:48
TLorentzVector fVertex
Definition: GTruth.h:31
vector< rec::CaloHit > fCalHits
string fVertexLabel
module label for vertexes rec:Vertex
T abs(T value)
std::vector< std::pair< simb::MCParticle *, float > > ClusterToMCParticles(rec::Cluster *const c)
string fTPCClusterLabel
module label for TPC Clusters rec::TPCCluster
vector< vector< garana::FSParticle > > fFSParticles
FS particles/4-vecs.
CLHEP::HepRandomEngine & fEngine
random engine
const double e
int PdgCode(Resonance_t res, int Q)
(resonance id, charge) -> PDG code
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
string infile
Int_t fEvent
number of the event being processed
float TPCRadius() const
Returns the radius of the TPC (y or z direction)
Definition: GeometryCore.h:755
vector< raw::CaloRawDigit > fMuDigits
vector< garana::Vertex > fVertices
reco TPC vertices
garana::Vertex MakeAnaVtx(const rec::Vertex &vtx)
Definition: AnaUtils.cxx:80
Int_t fSubRun
number of the sub-run being processed
std::string GDMLFile() const
Returns the full directory path to the GDML file source.
Definition: GeometryCore.h:486
vector< vector< UInt_t > > fCalG4PIndices
index of fG4Particles associated with fCalClusters
const double a
garana::G4Particle MakeG4Particle(const simb::MCParticle &mcp, int parentPdg, int progenitorPdg, int progenitorTrackId, const vector< pair< TLorentzVector, TLorentzVector >> &positions, const vector< pair< TLorentzVector, TLorentzVector >> &momenta, const vector< int > &regions, const vector< size_t > &nptsPerRegion)
Definition: AnaUtils.cxx:33
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
Definition: DataViewImpl.h:479
T get(std::string const &key) const
Definition: ParameterSet.h:271
simb::MCParticle * FindMother(simb::MCParticle *const p) const
vector< garana::CaloCluster > fCalClusters
reco ECal clusters
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
void FillG4Tree(Event const &e)
extracts G4(truth) level sim products
size_t size
Definition: lodepng.cpp:55
void processIonizationInfo(rec::TrackIoniz &ion, float ionizeTruncate, float &forwardIonVal, float &backwardIonVal)
vector< const simb::MCParticle * > fMCParticles
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
string fTPCDigitLabel
module label for digitized TPC hits raw::RawDigit
p
Definition: test.py:223
bool fWriteDisplay
include sim/reco traj points for event display, default=false
float TPCZCent() const
Returns the Z location of the center of the TPC in cm.
Definition: GeometryCore.h:792
SubRunNumber_t subRun() const
Definition: DataViewImpl.cc:78
vector< rec::Hit > fTPCHits
bool PointInECALBarrel(TVector3 const &point) const
std::vector< HitIDE > HitToHitIDEs(art::Ptr< rec::Hit > const &hit) const
Definition of basic calo raw digits.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
RunNumber_t run() const
Definition: DataViewImpl.cc:71
#define MF_LOG_INFO(category)
vector< vector< UInt_t > > fCalTrackIndices
index of fTracks associated with fCalClusters
vector< garana::CaloCluster > fMuClusters
reco MuID clusters
simb::MCParticle * FindEve(simb::MCParticle *const p) const
vector< raw::RawDigit > fTPCDigits
vector< garana::Vee > fVees
reco Vees (reco 4-mom, 4-pos from decay vertex)
Detector simulation of raw signals on wires.
const geo::GeometryCore * fGeo
pointer to the geometry service
vector< Int_t > fGIndex
index of GTruth object associated with MCTruth in this row (-1 if not associated, e...
double TrackToTotalEnergy(rec::Track *const t)
vector< garana::G4Particle > fG4Particles
&#39;condensed&#39; MCParticles from G4
General GArSoft Utilities.
vector< UInt_t > fG4TruthIndex
index of GTruth objects matched to this particle
vector< garana::Track > fTracks
reco TPC tracks
string fCaloHitInstanceMuID
Instance name MuID for rec::CaloHit.
garana::GTruth MakeAnaGTruth(const simb::GTruth &gt, const int &vtxregion)
Definition: AnaUtils.cxx:17
void analyze(Event const &e) override
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
vector< garana::GTruth > fGTruth
GENIE interction-level info.
vector< UInt_t > fG4FSIndex
index of FSParticle objects matched to this particle
float TPCYCent() const
Returns the Y location of the center of the TPC in cm.
Definition: GeometryCore.h:785
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
float fIonizTruncate
Default=1.00;.
std::vector< std::pair< simb::MCParticle *, float > > TrackToMCParticles(rec::Track *const t)
bool HasMuonDetector() const
Definition: GeometryCore.h:999
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
#define MF_LOG_DEBUG(id)
vector< rec::TPCCluster > fTPCClusters
reco TPC clusters
std::map< std::string, int > fRegionNameToID
string fHitLabel
module label for reco TPC hits rec::Hit
static bool * b
Definition: config.cpp:1043
EventNumber_t event() const
Definition: EventID.h:116
void FillGenTree(Event const &e)
extracts generator(truth) level sim products
float TPCLength() const
Returns the length of the TPC (x direction)
Definition: GeometryCore.h:763
cheat::BackTrackerCore * fBt
const std::string VolumeName(TVector3 const &point) const
Returns the name of the deepest volume containing specified point.
gar::rec::IDNumber getIDNumber() const
Definition: Track.cxx:42
string fAnaMode
analysis configs: (gen)eral, (reco) R&D or (readout) sim R&D, default="gen"
vector< vector< Int_t > > fCalTrackEnds
Track end associated with the cluster.
const std::vector< std::pair< float, float > > getBAK_dSigdXs() const
Definition: TrackIoniz.h:23
std::string PointToRegion(const TVector3 &point)
string fTrackLabel
module label for TPC Tracks rec:Track
std::vector< art::Ptr< rec::CaloHit > > const ClusterToCaloHits(rec::Cluster *const c)
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:85
const std::vector< std::pair< float, float > > getFWD_dSigdXs() const
Definition: TrackIoniz.h:22
art framework interface to geometry description
unsigned int const & TotalSpills() const
Definition: POTSummary.h:46
vector< vector< UInt_t > > fTrackG4PIndices
index of fG4Particles associated with fTracks
static bool lessThan_byE(std::pair< float, float > a, std::pair< float, float > b)
string fCaloHitInstanceCalo
Instance name ECAL for rec::CaloHit.
static QCString * s
Definition: config.cpp:1042
virtual void endJob() override
EventID id() const
Definition: Event.cc:34
const garana::Track MakeAnaTrack(const rec::Track &trk, const vector< pair< int, float >> &pidf, const vector< pair< int, float >> &pidb, float ionf, float ionb, const vector< pair< UInt_t, TLorentzVector >> &posBeg, const vector< pair< UInt_t, TLorentzVector >> &posEnd, const vector< pair< UInt_t, TLorentzVector >> &momBeg, const vector< pair< UInt_t, TLorentzVector >> &momEnd, const vector< pair< int, float >> &edeps)
Definition: AnaUtils.cxx:202
static QCString str
string fCalDigitLabel
module label for digitized calo/muID hits raw::CaloRawDigit
string fTreeType
"structured" (in our case yes) or "flat" (no)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
QCString & append(const char *s)
Definition: qcstring.cpp:383
string fGeantInstanceCalo
Instance name ECAL for sdp::CaloDeposit.
string fPFLabel
module label for reco particles rec::PFParticle
void FillHighLevelRecoInfo(Event const &e)
extracts high level reco products
float processOneDirection(vector< pair< float, float >> SigData, float ionizeTruncate)
vector< rec::TrackTrajectory > fRecoDisplay
reconstructed track trajectory points
StructuredTree(fhicl::ParameterSet const &p)
vector< pair< int, float > > processPIDInfo(float p)
vertex reconstruction