LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
NuShowerEff_module.cc
Go to the documentation of this file.
1 // Class: NuShowerEff
3 // Plugin Type: analyzer (art v2_11_03)
4 // File: NuShowerEff_module.cc
5 //
6 // Generated at Tue Sep 18 14:20:57 2018 by Wanwei Wu using cetskelgen
7 // from cetlib version v3_03_01.
9 
10 // Framework includes
18 #include "fhiclcpp/ParameterSet.h"
20 
25 
26 // LArsoft includes
40 
43 //#include "larsim/MCCheater/BackTrackerService.h" // for uboone, Backtracker is empty (not saved)
48 
49 // ROOT includes
50 #include "TFile.h"
51 #include "TTree.h"
52 #include "TDirectory.h"
53 #include "TH1.h"
54 #include "TEfficiency.h"
55 #include "TGraphAsymmErrors.h"
56 
57 // user's defined constant
58 #define MAX_SHOWERS 1000
59 
60 using namespace std;
61 
62 class NuShowerEff;
63 
64 
65 class NuShowerEff : public art::EDAnalyzer {
66 public:
67  explicit NuShowerEff(fhicl::ParameterSet const & p);
68  // The compiler-generated destructor is fine for non-base
69  // classes without bare pointers or other resource use.
70 
71  // Plugins should not be copied or assigned.
72  NuShowerEff(NuShowerEff const &) = delete;
73  NuShowerEff(NuShowerEff &&) = delete;
74  NuShowerEff & operator = (NuShowerEff const &) = delete;
75  NuShowerEff & operator = (NuShowerEff &&) = delete;
76 
77  // Required functions.
78  void analyze(art::Event const & e) override;
79 
80  // user's defined functions
81  void beginJob() override;
82  void endJob() override;
83  void beginRun(art::Run const& run) override;
84  void doEfficiencies();
85  bool insideFV(double vertex[4]);
86  void reset();
87 
88 private:
89 
90  // Declare member data here.
91 
92  // read from fchicl: Input Tag
93  std::string fMCTruthModuleLabel;
94  std::string fHitModuleLabel;
95  std::string fShowerModuleLabel;
97 
98  // read from fchicl: user's defined parameters
102  bool fHitShowerThroughPFParticle; // an option for getting hits associated with shower
103  double fMinPurity; // for reference
104  double fMinCompleteness; // for reference
105  float fFidVolCutX;// Fiducail Volume cut [cm]
106  float fFidVolCutY;
107  float fFidVolCutZ;
108 
109  // Fiducial Volume parameters
110  float fFidVolXmin;
111  float fFidVolXmax;
112  float fFidVolYmin;
113  float fFidVolYmax;
114  float fFidVolZmin;
115  float fFidVolZmax;
116 
117  // Event
118  int Event;
119  int Run;
120  int SubRun;
121 
122  // MC Truth: Generator
125  int MC_isCC;
128  double MC_Q2;
129  double MC_W;
130  double MC_vertex[4];
131  double MC_incoming_P[4];
132  double MC_lepton_startMomentum[4];
133  double MC_lepton_endMomentum[40];
134  double MC_lepton_startXYZT[4];
135  double MC_lepton_endXYZT[4];
139 
140  double MC_incoming_E; // incoming neutrino energy
142 
143  // recob::Shower
145  double sh_direction_X[MAX_SHOWERS];
146  double sh_direction_Y[MAX_SHOWERS];
147  double sh_direction_Z[MAX_SHOWERS];
148  double sh_start_X[MAX_SHOWERS];
149  double sh_start_Y[MAX_SHOWERS];
150  double sh_start_Z[MAX_SHOWERS];
151  double sh_length[MAX_SHOWERS];
152  double sh_ehit_Q[MAX_SHOWERS];
153  int sh_TrackId[MAX_SHOWERS];
154  int sh_hasPrimary_e[MAX_SHOWERS];
155  double sh_allhit_Q[MAX_SHOWERS];
156  double sh_purity[MAX_SHOWERS];
157  double sh_completeness[MAX_SHOWERS];
158  double esh_1_purity; // largest shower in a CC event that contains electron contributions
160  double esh_each_purity[MAX_SHOWERS]; // each shower in a CC event that contains electron contributions
161  double esh_each_completeness[MAX_SHOWERS];
162  double esh_purity; // average over all electron showers in a CC event
164  int count_primary_e_in_Event;// number of showers containing electron contribution in a CC event
165 
166  // TTree
167  TTree *fEventTree;
168 
169  TH1D *h_Ev_den; // incoming neutrino energy from MC. den: denominator
170  TH1D *h_Ev_num; // recon. num: numerator
171 
172  TH1D *h_Ee_den; // primary electron energy from MC
173  TH1D *h_Ee_num;
174 
175  TEfficiency* h_Eff_Ev = 0;
176  TEfficiency* h_Eff_Ee = 0;
177 
178 
179 };
180 
181 // =====================================================================================
183  :
184  EDAnalyzer(p), // ,
185  // More initializers here.
186  //fMCTruthModuleLabel (p.get< std::string >("MCTruthModuleLabel", "generator")),
187  fMCTruthModuleLabel (p.get< std::string >("MCTruthModuleLabel")),// get parameter from fcl file
188  fHitModuleLabel (p.get< std::string >("HitModuleLabel")),
189  fShowerModuleLabel (p.get< std::string >("ShowerModuleLabel")),
190  fTruthMatchDataModuleLabel (p.get< std::string >("TruthMatchDataModuleLabel")),
191  fNeutrinoPDGcode (p.get<int>("NeutrinoPDGcode")),
192  fLeptonPDGcode (p.get<int>("LeptonPDGcode")),
193  fSaveMCTree (p.get<bool>("SaveMCTree")),
194  fHitShowerThroughPFParticle (p.get<bool>("HitShowerThroughPFParticle")),
195  fMinPurity (p.get<double>("MinPurity")),
196  fMinCompleteness (p.get<double>("MinCompleteness")),
197  fFidVolCutX (p.get<float>("FidVolCutX")),
198  fFidVolCutY (p.get<float>("FidVolCutY")),
199  fFidVolCutZ (p.get<float>("FidVolCutZ"))
200 {
201  //cout << "\n===== Please refer the fchicl for the values of preset parameters ====\n" << endl;
202 }
203 
204 //============================================================================
206  //cout << "\n===== function: beginJob() ====\n" << endl;
207 
208  // Get geometry: Fiducial Volume
209  auto const* geo = lar::providerFrom<geo::Geometry>();
210  double minx = 1e9; // [cm]
211  double maxx = -1e9;
212  double miny = 1e9;
213  double maxy = -1e9;
214  double minz = 1e9;
215  double maxz = -1e9;
216  //cout << "\nGeometry:\n\tgeo->NTPC(): " << geo->NTPC() << endl;
217  for (size_t i = 0; i<geo->NTPC(); ++i){
218  double local[3] = {0.,0.,0.};
219  double world[3] = {0.,0.,0.};
220  const geo::TPCGeo &tpc = geo->TPC(i);
221  tpc.LocalToWorld(local,world);
222  //cout << "\tlocal: " << local[0] << " ; " << local[1] << " ; " << local[2] << endl;
223  //cout << "\tworld: " << world[0] << " ; " << world[1] << " ; " << world[2] << endl;
224  //cout << "\tgeo->DetHalfWidth(" << i << "): " << geo->DetHalfWidth(i) << endl;
225  //cout << "\tgeo->DetHalfHeight(" << i << "): " << geo->DetHalfHeight(i) << endl;
226  //cout << "\tgeo->DetLength(" << i << "): " << geo->DetLength(i) << endl;
227 
228  if (minx > world[0] - geo->DetHalfWidth(i)) minx = world[0]-geo->DetHalfWidth(i);
229  if (maxx < world[0] + geo->DetHalfWidth(i)) maxx = world[0]+geo->DetHalfWidth(i);
230  if (miny > world[1] - geo->DetHalfHeight(i)) miny = world[1]-geo->DetHalfHeight(i);
231  if (maxy < world[1] + geo->DetHalfHeight(i)) maxy = world[1]+geo->DetHalfHeight(i);
232  if (minz > world[2] - geo->DetLength(i)/2.) minz = world[2]-geo->DetLength(i)/2.;
233  if (maxz < world[2] + geo->DetLength(i)/2.) maxz = world[2]+geo->DetLength(i)/2.;
234  }
235 
236  fFidVolXmin = minx + fFidVolCutX;
237  fFidVolXmax = maxx - fFidVolCutX;
238  fFidVolYmin = miny + fFidVolCutY;
239  fFidVolYmax = maxy - fFidVolCutY;
240  fFidVolZmin = minz + fFidVolCutZ;
241  fFidVolZmax = maxz - fFidVolCutZ;
242 
243  //cout << "\nFiducial Volume (length unit: cm):\n"
244  //<< "\t" << fFidVolXmin<<"\t< x <\t"<<fFidVolXmax<<"\n"
245  //<< "\t" << fFidVolYmin<<"\t< y <\t"<<fFidVolYmax<<"\n"
246  //<< "\t" << fFidVolZmin<<"\t< z <\t"<<fFidVolZmax<<"\n";
247 
249 
250  double E_bins[21] = {0,0.5,1.0,1.5,2.0,2.5,3.0,3.5,4,4.5,5.0,5.5,6.0,7.0,8.0,10.0,12.0,14.0,17.0,20.0,25.0};
251 // double theta_bins[44]= { 0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,16.,17.,18.,19.,20.,22.,24.,26.,28.,30.,32.,34.,36.,38.,40.,42.,44.,46.,48.,50.,55.,60.,65.,70.,75.,80.,85.,90.};
252  // double Pbins[18] ={0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.2,1.4,1.6,1.8,2.0,2.5,3.0};
253 
254  h_Ev_den = tfs->make<TH1D>("h_Ev_den", "Neutrino Energy; Neutrino Energy (GeV); Shower Reconstruction Efficiency", 20, E_bins);
255  h_Ev_den->Sumw2();
256  h_Ev_num = tfs->make<TH1D>("h_Ev_num","Neutrino Energy; Neutrino Energy (GeV); Shower Reconstruction Efficiency",20,E_bins);
257  h_Ev_num->Sumw2();
258 
259  h_Ee_den = tfs->make<TH1D>("h_Ee_den","Electron Energy; Electron Energy (GeV); Shower Reconstruction Efficiency",20,E_bins);
260  h_Ee_den->Sumw2();
261  h_Ee_num = tfs->make<TH1D>("h_Ee_num","Electron Energy; Electron Energy (GeV); Shower Reconstruction Efficiency",20,E_bins);
262  h_Ee_num->Sumw2();
263 
264  if (fSaveMCTree) {
265  fEventTree = new TTree("Event", "Event Tree from Sim & Reco");
266  fEventTree->Branch("eventNo", &Event); // only select event in FV
267  fEventTree->Branch("runNo", &Run);
268  fEventTree->Branch("subRunNo", &SubRun);
269 
270  fEventTree->Branch("MC_incoming_E", &MC_incoming_E);
271  fEventTree->Branch("MC_lepton_startEnergy", &MC_lepton_startEnergy);
272 
273  fEventTree->Branch("n_showers", &n_recoShowers);
274  fEventTree->Branch("sh_hasPrimary_e", &sh_hasPrimary_e, "sh_hasPrimary_e[n_showers]/I");
275  //fEventTree->Branch("sh_purity", &sh_purity, "sh_purity[n_showers]/D");
276  //fEventTree->Branch("sh_completeness", &sh_completeness, "sh_completeness[n_showers]/D");
277  fEventTree->Branch("count_primary_e_in_Event", &count_primary_e_in_Event);
278  fEventTree->Branch("esh_1_purity", &esh_1_purity);
279  fEventTree->Branch("esh_1_completeness", &esh_1_completeness);
280  fEventTree->Branch("esh_each_purity", &esh_each_purity, "esh_each_purity[count_primary_e_in_Event]/D");
281  fEventTree->Branch("esh_each_completeness", &esh_each_completeness, "esh_each_completeness[count_primary_e_in_Event]/D");
282  fEventTree->Branch("esh_purity", &esh_purity);
283  fEventTree->Branch("esh_completeness", &esh_completeness);
284  }
285 
286 }
287 
288 //============================================================================
290  //cout << "\n===== function: endJob() =====\n" << endl;
291  doEfficiencies();
292 }
293 
294 //============================================================================
295 void NuShowerEff::beginRun(art::Run const & run){
296  //cout << "\n===== function: beginRun() =====\n" << endl;
297  mf::LogInfo("ShowerEff") << "==== begin run ... ====" << endl;
298 }
299 
300 //============================================================================
302 {
303  // Implementation of required member function here.
304  //cout << "\n===== function: analyze() =====\n" << endl;
305 
306  reset(); // for some variables
307 
308  Event = e.id().event();
309  Run = e.run();
310  SubRun = e.subRun();
311  //cout << "Event information:" << endl;
312  //cout << "\tEvent: " << Event << endl;
313  //cout << "\tRun: " << Run << endl;
314  //cout << "\tSubRun: " << SubRun << endl;
315 
316 
317  // -------- find Geant4 TrackId that corresponds to e+/e- from neutrino interaction ----------
318  // MCTruth: Generator
320  e.getByLabel(fMCTruthModuleLabel, MCtruthHandle);
321  std::vector<art::Ptr<simb::MCTruth>> MCtruthlist;
322  art::fill_ptr_vector(MCtruthlist, MCtruthHandle);
323  art::Ptr<simb::MCTruth> MCtruth;
324  // MC (neutrino) interaction
325  int MCinteractions = MCtruthlist.size();
326  //cout << "\nMCinteractions: " << MCinteractions << endl;
327  for (int i=0; i<MCinteractions; i++){
328  MCtruth = MCtruthlist[i];
329  if ( MCtruth->NeutrinoSet() ) { // NeutrinoSet(): whether the neutrino information has been set
330  simb::MCNeutrino nu = MCtruth->GetNeutrino();// GetNeutrino(): reference to neutrino info
331  if( nu.CCNC()==0 ) MC_isCC = 1;
332  else if (nu.CCNC()==1) MC_isCC = 0;
333  simb::MCParticle neutrino = nu.Nu(); // Nu(): the incoming neutrino
334  MC_target = nu.Target(); // Target(): nuclear target, as PDG code
335  MC_incoming_PDG = std::abs(nu.Nu().PdgCode());// here not use std::abs()
336  MC_Q2 = nu.QSqr();// QSqr(): momentum transfer Q^2, in GeV^2
337  MC_channel = nu.InteractionType();// 1001: CCQE
338  MC_W = nu.W(); // W(): hadronic invariant mass
339  const TLorentzVector& nu_momentum = nu.Nu().Momentum(0);
340  nu_momentum.GetXYZT(MC_incoming_P);
341  const TLorentzVector& vertex =neutrino.Position(0);
342  vertex.GetXYZT(MC_vertex);
343  simb::MCParticle lepton = nu.Lepton();// Lepton(): the outgoing lepton
344  MC_lepton_PDG = lepton.PdgCode();
345 
347 
348  //cout << "\tMCinteraction: " << i << "\n\t"
349  // << "neutrino PDG: " << MC_incoming_PDG << "\n\t"
350  // << "MC_lepton_PDG: " << MC_lepton_PDG << "\n\t"
351  // << "MC_channel: " << MC_channel << "\n\t"
352  // << "incoming E: " << MC_incoming_P[3] << "\n\t"
353  // << "MC_vertex: " << MC_vertex[0] << " , " << MC_vertex[1] << " , " <<MC_vertex[2] << " , " <<MC_vertex[3] << endl;
354  }
355  // MCTruth Generator Particles
356  int nParticles = MCtruthlist[0]->NParticles();
357  //cout << "\n\tNparticles: " << MCtruth->NParticles() <<endl;
358  for (int i=0; i<nParticles; i++){
359  simb::MCParticle pi = MCtruthlist[0]->GetParticle(i);
360  //cout << "\tparticle: " << i << "\n\t\t"
361  //<< "Pdgcode: " << pi.PdgCode() << "; Mother: " << pi.Mother() << "; TrackId: " << pi.TrackId() << endl;
362  // Mother(): mother = -1 means that this particle has no mother
363  // TrackId(): same as the index in the MCParticleList
364  }
365  }
366 
367  // Geant4: MCParticle -> lepton (e)
368  // Note: generator level MCPartilceList is different from Geant4 level MCParticleList. MCParticleList(Geant4) contains all particles in MCParticleList(generator) but their the indexes (TrackIds) are different.
369  simb::MCParticle *MClepton = NULL; //Geant4 level
371  const sim::ParticleList& plist = pi_serv->ParticleList();
372  simb::MCParticle *particle=0;
373 
374  for (sim::ParticleList::const_iterator ipar = plist.begin(); ipar!=plist.end();++ipar){
375  particle = ipar->second; // first is index(TrackId), second is value (point address)
376 
377  auto & truth = pi_serv->ParticleToMCTruth_P(particle);// beam neutrino only
378  if ( truth->Origin()==simb::kBeamNeutrino && std::abs(particle->PdgCode()) == fLeptonPDGcode && particle->Mother()==0){ // primary lepton; Mother() = 0 means e^{-} for v+n=e^{-}+p
379  const TLorentzVector& lepton_momentum =particle->Momentum(0);
380  const TLorentzVector& lepton_position =particle->Position(0);
381  const TLorentzVector& lepton_positionEnd = particle->EndPosition();
382  const TLorentzVector& lepton_momentumEnd = particle->EndMomentum();
383  lepton_momentum.GetXYZT(MC_lepton_startMomentum);
384  lepton_position.GetXYZT(MC_lepton_startXYZT);
385  lepton_positionEnd.GetXYZT(MC_lepton_endXYZT);
386  lepton_momentumEnd.GetXYZT(MC_lepton_endMomentum);
387  MC_leptonID = particle->TrackId();
388 
390  //cout << "\nGeant Track ID for electron/positron: " << endl;
391  //cout << "\tMClepton PDG: " << particle->PdgCode() << " ; MC_leptonID: " << MC_leptonID << endl;
392  MClepton = particle;
393  //cout << "\tMClepton PDG:" << MClepton->PdgCode() <<endl;
394  //cout << "\tipar->first (TrackId): " << ipar->first << endl;
395  }
396  }
397 
398  // check if the interaction is inside the Fiducial Volume
399  bool isFiducial = false;
400  isFiducial = insideFV( MC_vertex);
401  if (isFiducial) {
402  //cout <<"\nInfo: Interaction is inside the Fiducial Volume.\n" << endl;
403  }
404  else {
405  //cout << "\n********Interaction is NOT inside the Fiducial Volume. RETURN**********" << endl;
406  return;
407  }
408 
409  if (MC_isCC && (fNeutrinoPDGcode == std::abs(MC_incoming_PDG))) {
410  if (MClepton){
411  h_Ev_den->Fill(MC_incoming_P[3]);
413  }
414  }
415 
416  //if (MC_isCC && (fNeutrinoPDGcode == std::abs(MC_incoming_PDG)) && MC_incoming_E < 0.5) {
417  // cout << "\n------output CC event info for neutrino energy less than 0.5 GeV ------\n" << endl;
418  // cout << "\tEvent : " << Event << "\n"
419  // << "\tRun : " << Run << "\n"
420  // << "\tSubRun : " << SubRun << "\n"
421  // << "\tMC_incoming_E: " << MC_incoming_E << endl;
422  // }
423 
424  // recob::Hit
425  // ---- build a map for total hit charges corresponding to MC_leptonID (Geant4) ----
426 
428  std::vector<art::Ptr<recob::Hit>> all_hits;
429  if(e.getByLabel(fHitModuleLabel,hitHandle)){
430  art::fill_ptr_vector(all_hits, hitHandle);
431  }
432  //cout << "\nTotal hits:" << endl;
433  //cout << "\tall_hits.size(): " << all_hits.size() << endl;
434 
435  double ehit_total =0.0;
436 
437  art::FindManyP<simb::MCParticle,anab::BackTrackerHitMatchingData> fmhitmc(hitHandle, e, fTruthMatchDataModuleLabel);// need #include "lardataobj/AnalysisBase/BackTrackerMatchingData.h"
438 
439  std::map<int,double> all_hits_trk_Q;//Q for charge: Integral()
440  for (size_t i=0; i < all_hits.size(); ++i) {
441  art::Ptr<recob::Hit> hit = all_hits[i];
442  auto particles = fmhitmc.at(hit.key());// particles here is a pointer. A hit may come from multiple particles.
443  auto hitmatch = fmhitmc.data(hit.key());// metadata
444  double maxenergy = -1e9;
445  int hit_TrackId = 0;
446  for (size_t j = 0; j < particles.size(); ++j){
447  if (!particles[j]) continue;
448  if (!pi_serv->TrackIdToMotherParticle_P(particles[j]->TrackId())) continue;
449  size_t trkid = (pi_serv->TrackIdToMotherParticle_P(particles[j]->TrackId()))->TrackId();
450 
451  if ( (hitmatch[j]->energy) > maxenergy ){
452  maxenergy = hitmatch[j]->energy;
453  hit_TrackId = trkid;
454  }
455  }
456  if (hit_TrackId == MC_leptonID) ehit_total += hit->Integral();
457  all_hits_trk_Q[hit_TrackId] += hit->Integral(); // Integral(): the integral under the calibrated signal waveform of the hit, in tick x ADC units
458  }
459  //cout << "....ehit_total: " << ehit_total << endl;
460  //cout << "\tall_hits_trk_Q.size(): " << all_hits_trk_Q.size() << endl;
461 
462 
463  //--------- Loop over all showers: find the associated hits for each shower ------------
464  const simb::MCParticle *MClepton_reco = NULL;
465 
466  double temp_sh_ehit_Q = 0.0;
467  double temp_sh_allHit_Q = 0.0;
468  int temp_sh_TrackId = -999;
470 
472  std::vector<art::Ptr<recob::Shower>> showerlist;
473  if(e.getByLabel(fShowerModuleLabel,showerHandle)){
474  art::fill_ptr_vector(showerlist, showerHandle);
475  }
476  n_recoShowers= showerlist.size();
477  //cout << "\nRecon Showers: " << endl;
478  //cout << "\tn_recoShowers: " << n_recoShowers << endl;
479  art::FindManyP<recob::Hit> sh_hitsAll(showerHandle, e, fShowerModuleLabel);
480 
481  //std::vector<std::map<int,double>> showers_hits_trk_Q;
482  std::map<int,double> showers_trk_Q;
483  for (int i=0; i<n_recoShowers;i++){ // loop over showers
484  //const simb::MCParticle *particle;
485  sh_hasPrimary_e[i] = 0;
486 
487  std::map<int,double> sh_hits_trk_Q;//Q for charge: Integral()
488  sh_hits_trk_Q.clear();
489 
490  art::Ptr<recob::Shower> shower = showerlist[i];
491  sh_direction_X[i] = shower->Direction().X(); // Direction(): direction cosines at start of the shower
492  sh_direction_Y[i] = shower->Direction().Y();
493  sh_direction_Z[i] = shower->Direction().Z();
494  sh_start_X[i] = shower->ShowerStart().X();
495  sh_start_Y[i] = shower->ShowerStart().Y();
496  sh_start_Z[i] = shower->ShowerStart().Z();
497  sh_length[i] = shower->Length(); // shower length in [cm]
498  //cout << "\tInfo of shower " << i << "\n\t\t"
499  //<< "direction (cosines): " << sh_direction_X[i] << ", " << sh_direction_Y[i] << ", " << sh_start_Z[i] << "\n\t\t"
500  //<< "start position: " << sh_start_X[i] << ", " << sh_start_Y[i] << ", " << sh_start_Z[i] << "\n\t\t"
501  //<< "shower length: " << sh_length[i] << endl;
502 
503 
504  std::vector<art::Ptr<recob::Hit>> sh_hits;// associated hits for ith shower
505  //In mcc8, if we get hits associated with the shower through shower->hits association directly for pandora, the hit list is incomplete. The recommended way of getting hits is through association with pfparticle:
506  //shower->pfparticle->clusters->hits
507  //----------getting hits through PFParticle (an option here)-------------------
509  //cout << "\n==== Getting Hits associated with shower THROUGH PFParticle ====\n" << endl;
510  //cout << "\nHits in a shower through PFParticle:\n" << endl;
511 
512  // PFParticle
514  std::vector<art::Ptr<recob::PFParticle> > pfps;
515  if (e.getByLabel(fShowerModuleLabel, pfpHandle)) art::fill_ptr_vector(pfps, pfpHandle);
516  // Clusters
518  std::vector<art::Ptr<recob::Cluster> > clusters;
519  if (e.getByLabel(fShowerModuleLabel, clusterHandle)) art::fill_ptr_vector(clusters, clusterHandle);
520  art::FindManyP<recob::PFParticle> fmps(showerHandle, e, fShowerModuleLabel);// PFParticle in Shower
521  art::FindManyP<recob::Cluster> fmcp(pfpHandle, e, fShowerModuleLabel); // Cluster vs. PFParticle
522  art::FindManyP<recob::Hit> fmhc(clusterHandle, e, fShowerModuleLabel); // Hit in Shower
523  if (fmps.isValid()){
524  std::vector<art::Ptr<recob::PFParticle>> pfs = fmps.at(i);
525  for (size_t ipf = 0; ipf<pfs.size(); ++ipf){
526  if (fmcp.isValid()){
527  std::vector<art::Ptr<recob::Cluster>> clus = fmcp.at(pfs[ipf].key());
528  for (size_t iclu = 0; iclu<clus.size(); ++iclu){
529  if (fmhc.isValid()){
530  std::vector<art::Ptr<recob::Hit>> hits = fmhc.at(clus[iclu].key());
531  for (size_t ihit = 0; ihit<hits.size(); ++ihit){
532  sh_hits.push_back(hits[ihit]);
533  }
534  }
535  }
536  }
537  }
538  }
539 
540  // cout << "\tsh_hits.size(): " << sh_hits.size() << endl;
541 
542  // for (size_t k=0;k<sh_hits.size();k++){
543  // art::Ptr<recob::Hit> hit = sh_hits[k];
544  // cout << k << "\thit.key(): " << hit.key() << endl;
545  // cout << k << "\thit->Integral(): " << hit->Integral() << endl;
546  // }
547  } else {
548 
549  // ----- using shower->hit association for getting hits associated with shower-----
550  sh_hits = sh_hitsAll.at(i);// associated hits for ith shower (using association of hits and shower)
551  //cout << "\t\tsh_hits.size(): " << sh_hits.size() << endl;
552  } // we only choose one method for hits associated with shower here.
553 
554 
555  for (size_t k=0; k < sh_hits.size(); ++k) {
556  art::Ptr<recob::Hit> hit = sh_hits[k];
557  auto particles = fmhitmc.at(hit.key());
558  auto hitmatch = fmhitmc.data(hit.key());
559  double maxenergy = -1e9;
560  int hit_TrackId = 0;
561  for (size_t j = 0; j < particles.size(); ++j){
562  if (!particles[j]) continue;
563  if (!pi_serv->TrackIdToMotherParticle_P(particles[j]->TrackId())) continue;
564  size_t trkid = (pi_serv->TrackIdToMotherParticle_P(particles[j]->TrackId()))->TrackId();
565 
566  if ( (hitmatch[j]->energy) > maxenergy ){
567  maxenergy = hitmatch[j]->energy;
568  hit_TrackId = trkid;
569  }
570  }
571  if (hit_TrackId == MC_leptonID) {
572  sh_ehit_Q[i] += hit->Integral();
573  }
574  sh_allhit_Q[i] += hit->Integral();
575  sh_hits_trk_Q[hit_TrackId] += hit->Integral();// Q from the same hit_TrackId
576  }
577  //cout << "\tsh_hits_trk_Q.size(): " << sh_hits_trk_Q.size() << endl;
578  //showers_hits_trk_Q.push_back(sh_hits_trk_Q);
579 
580  // get TrackId for a shower
581  double maxshowerQ = -1.0e9;
582  //sh_TrackId[i] = 0;
583  for(std::map<int,double>::iterator k = sh_hits_trk_Q.begin(); k != sh_hits_trk_Q.end(); k++) {
584  //cout << k->first << "\t;\t" << k->second << endl;
585  if (k->second > maxshowerQ) {
586  maxshowerQ = k->second;
587  sh_TrackId[i] = k->first;//assign a sh_TrackId with TrackId from hit(particle) that contributing largest to the shower.
588  }
589  }
590 
591  //---------------------------------------------------------------------------------
592  //cout << "\nRecon Shower: " << i << endl;
593  //cout << "\t*****shower primary TrackId: " << sh_TrackId[i] << endl;
594 
595  if (sh_TrackId[i] == MC_leptonID && sh_ehit_Q[i] >0) {
596  temp_sh_TrackId = sh_TrackId[i];
597  sh_hasPrimary_e[i] = 1;
599  MClepton_reco = pi_serv->TrackIdToParticle_P(sh_TrackId[i]);
600 
601  if (sh_allhit_Q[i] >0 && sh_ehit_Q[i] <= sh_allhit_Q[i]){
602  sh_purity[i] = sh_ehit_Q[i]/sh_allhit_Q[i];
603  //cout << "\t*****shower purity: " << sh_purity[i] << endl;
604  } else {
605  sh_purity[i] = 0;
606  }
607  if(ehit_total >0 && sh_ehit_Q[i] <= sh_allhit_Q[i]){
608  sh_completeness[i] = sh_ehit_Q[i] / ehit_total;
609  //cout << "\t*****shower completeness: " << sh_completeness[i] << endl;
610  } else {
611  sh_completeness[i] = 0;
612  }
613  temp_sh_ehit_Q += sh_ehit_Q[i];
614  temp_sh_allHit_Q += sh_allhit_Q[i];
615  }
616 
617  showers_trk_Q[sh_TrackId[i]] += maxshowerQ;
618  //cout << "\tsh_TrackId: " << sh_TrackId[i] <<" ; maxshowerQ: " << maxshowerQ << endl;
619 
620  } // end: for loop over showers
621 
622  // ---------------------------------------------------------------
623  if (MClepton_reco && MClepton) {
624  if ((temp_sh_TrackId == MC_leptonID) && MC_isCC && (fNeutrinoPDGcode == std::abs(MC_incoming_PDG))) {
625  if ((temp_sh_allHit_Q >= temp_sh_ehit_Q) && (temp_sh_ehit_Q > 0.0)) {
626  esh_purity = temp_sh_ehit_Q/temp_sh_allHit_Q;
627  esh_completeness = temp_sh_ehit_Q/ehit_total;
628 
629  if (esh_purity > fMinPurity &&
631  //cout << "\nInfo: fill h_Ev_num ........\n" << endl;
632  h_Ev_num->Fill(MC_incoming_P[3]);
634  }
635  }
636  }
637  }
638  // --------------------------------------------------------------
639 
640  if ( (MClepton_reco && MClepton) && MC_isCC && (fNeutrinoPDGcode == std::abs(MC_incoming_PDG))){
641  //cout << "\n count_primary_e_in_Event: " << count_primary_e_in_Event << endl;
642  for (int j=0; j<count_primary_e_in_Event; j++){
643  esh_each_purity[j] = 0.0;
644  }
645 
646  double temp_esh_1_allhit = -1.0e9;
647  int temp_shower_index = -999;
648  int temp_esh_index = 0;
649  for (int i=0; i<n_recoShowers; i++) {
650  if (sh_TrackId[i] == MC_leptonID) {
651 
652  // for each electron shower
653  if (sh_ehit_Q[i] >0){
654  esh_each_purity[temp_esh_index] = sh_purity[i];
655  esh_each_completeness[temp_esh_index] = sh_completeness[i];
656  temp_esh_index += 1;
657  }
658 
659  // find largest shower
660  if ((sh_allhit_Q[i] > temp_esh_1_allhit) && (sh_ehit_Q[i] > 0.0) ) {
661  temp_esh_1_allhit = sh_allhit_Q[i];
662  temp_shower_index = i;
663  }
664  }
665  }
666  //if (temp_esh_index != count_primary_e_in_Event){
667  // cout << "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww" << endl;
668  //}
669  // largest shower with electron contribution
670  esh_1_purity = sh_purity[temp_shower_index];
671  esh_1_completeness = sh_completeness[temp_shower_index];
672  }
673 
674  if (count_primary_e_in_Event>0 && MC_isCC && fSaveMCTree) { fEventTree->Fill();}// so far, only save CC event
675 }
676 
677 // ====================================================================================
679  //cout << "\n==== function: doEfficiencies() ====" << endl;
680 
682 
683  if(TEfficiency::CheckConsistency(*h_Ev_num,*h_Ev_den)){
684  h_Eff_Ev = tfs->make<TEfficiency>(*h_Ev_num,*h_Ev_den);
685  TGraphAsymmErrors *grEff_Ev = h_Eff_Ev->CreateGraph();
686  grEff_Ev->Write("grEff_Ev");
687  h_Eff_Ev->Write("h_Eff_Ev");
688  }
689 
690  if(TEfficiency::CheckConsistency(*h_Ee_num,*h_Ee_den)){
691  h_Eff_Ee = tfs->make<TEfficiency>(*h_Ee_num,*h_Ee_den);
692  TGraphAsymmErrors *grEff_Ee = h_Eff_Ee->CreateGraph();
693  grEff_Ee->Write("grEff_Ee");
694  h_Eff_Ee->Write("h_Eff_Ee");
695  }
696 
697 }
698 
699 // ====================================================================================
700 bool NuShowerEff::insideFV( double vertex[4] ){
701  //cout << "\n==== function: insideFV() ====" << endl;
702  double x = vertex[0];
703  double y = vertex[1];
704  double z = vertex[2];
705 
706  if (x>fFidVolXmin && x<fFidVolXmax&&
707  y>fFidVolYmin && y<fFidVolYmax&&
708  z>fFidVolZmin && z<fFidVolZmax)
709  {return true;}
710  else
711  {return false;}
712 }
713 
714 // ====================================================================================
716  //cout << "\n===== function: reset() =====\n" << endl;
717 
718  MC_incoming_PDG = -999;
719  MC_lepton_PDG =-999;
720  MC_isCC =-999;
721  MC_channel =-999;
722  MC_target =-999;
723  MC_Q2 =-999.0;
724  MC_W =-999.0;
725  MC_lepton_theta = -999.0;
726  MC_leptonID = -999;
727  MC_LeptonTrack = -999;
728 
729  for(int i=0; i<MAX_SHOWERS; i++){
730  sh_direction_X[i] = -999.0;
731  sh_direction_Y[i] = -999.0;
732  sh_direction_Z[i] = -999.0;
733  sh_start_X[i] = -999.0;
734  sh_start_Y[i] = -999.0;
735  sh_start_Z[i] = -999.0;
736  sh_length[i] = -999.0;
737  sh_hasPrimary_e[i] = -999;
738  sh_ehit_Q[i] = 0.0;
739  sh_allhit_Q[i] = 0.0;
740  sh_purity[i] = 0.0;
741  sh_completeness[i] = 0.0;
742  }
743 
744 }
Float_t x
Definition: compare.C:6
key_type key() const
Definition: Ptr.h:356
double esh_each_purity[MAX_SHOWERS]
double sh_direction_X[MAX_SHOWERS]
const simb::MCParticle * TrackIdToParticle_P(int const &id)
SubRunNumber_t subRun() const
Definition: Event.h:72
const TVector3 & ShowerStart() const
Definition: Shower.h:192
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:223
int PdgCode() const
Definition: MCParticle.h:216
int CCNC() const
Definition: MCNeutrino.h:152
double QSqr() const
Definition: MCNeutrino.h:161
const simb::MCNeutrino & GetNeutrino() const
Definition: MCTruth.h:74
double MC_lepton_startEnergy
TEfficiency * h_Eff_Ee
const TLorentzVector & EndPosition() const
Definition: MCParticle.h:229
double Length() const
Definition: Shower.h:201
intermediate_table::iterator iterator
NuShowerEff(fhicl::ParameterSet const &p)
double sh_start_Y[MAX_SHOWERS]
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
void endJob() override
int Mother() const
Definition: MCParticle.h:217
Declaration of signal hit object.
Float_t y
Definition: compare.C:6
const simb::MCParticle & Nu() const
Definition: MCNeutrino.h:150
list_type::const_iterator const_iterator
Definition: ParticleList.h:132
Double_t z
Definition: plot.C:279
Geometry information for a single TPC.
Definition: TPCGeo.h:37
double sh_direction_Y[MAX_SHOWERS]
const art::Ptr< simb::MCTruth > & ParticleToMCTruth_P(const simb::MCParticle *p)
Class to keep data related to recob::Hit associated with recob::Track.
std::string fMCTruthModuleLabel
STL namespace.
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
Definition: Hit.h:225
#define MAX_SHOWERS
data_const_reference data(size_type i) const
Definition: FindManyP.h:458
double MC_lepton_startMomentum[4]
Particle class.
Class def header for mcstep data container.
Definition: Run.h:30
int TrackId() const
Definition: MCParticle.h:214
bool fHitShowerThroughPFParticle
int sh_TrackId[MAX_SHOWERS]
std::string fShowerModuleLabel
int InteractionType() const
Definition: MCNeutrino.h:154
void hits()
Definition: readHits.C:15
const simb::MCParticle & Lepton() const
Definition: MCNeutrino.h:151
double W() const
Definition: MCNeutrino.h:158
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
Provides recob::Track data product.
void beginJob()
Definition: Breakpoints.cc:14
std::string fHitModuleLabel
double esh_each_completeness[MAX_SHOWERS]
TEfficiency * h_Eff_Ev
int sh_hasPrimary_e[MAX_SHOWERS]
void analyze(art::Event const &e) override
bool insideFV(double vertex[4])
double energy
Definition: plottest35.C:25
iterator begin()
Definition: ParticleList.h:305
const TVector3 & Direction() const
Definition: Shower.h:189
double sh_start_Z[MAX_SHOWERS]
Declaration of cluster object.
Class def header for mctrack data container.
double sh_purity[MAX_SHOWERS]
constexpr std::tuple_element_t< I, art::AssnsNode< L, R, D > > & get(art::AssnsNode< L, R, D > &t) noexcept
Detector simulation of raw signals on wires.
double sh_ehit_Q[MAX_SHOWERS]
double MC_lepton_startXYZT[4]
double MC_lepton_endXYZT[4]
double sh_direction_Z[MAX_SHOWERS]
T * make(ARGS...args) const
int Target() const
Definition: MCNeutrino.h:155
Utility object to perform functions of association.
double sh_completeness[MAX_SHOWERS]
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
double MC_lepton_endMomentum[40]
double sh_allhit_Q[MAX_SHOWERS]
const TLorentzVector & Momentum(const int i=0) const
Definition: MCParticle.h:224
void beginJob() override
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
Class def header for MCShower data container.
EventNumber_t event() const
Definition: EventID.h:117
void beginRun(art::Run const &run) override
std::string fTruthMatchDataModuleLabel
bool NeutrinoSet() const
Definition: MCTruth.h:75
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:464
const simb::MCParticle * TrackIdToMotherParticle_P(int const &id)
Float_t e
Definition: plot.C:34
RunNumber_t run() const
Definition: Event.h:77
Event generator information.
Definition: MCNeutrino.h:18
Namespace collecting geometry-related classes utilities.
double sh_start_X[MAX_SHOWERS]
const TLorentzVector & EndMomentum() const
Definition: MCParticle.h:244
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Definition: TPCGeo.h:490
EventID id() const
Definition: Event.h:56
art framework interface to geometry description
double MC_incoming_P[4]
double sh_length[MAX_SHOWERS]
Beam neutrinos.
Definition: MCTruth.h:21
vertex reconstruction