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