All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FillTrue.cxx
Go to the documentation of this file.
1 #include "FillTrue.h"
2 
4 #include "RecoUtils/RecoUtils.h"
5 
6 #include <functional>
7 #include <algorithm>
8 
9 // helper function declarations
10 
11 caf::SRTrackTruth MatchTrack2Truth(const detinfo::DetectorClocksData &clockData, const std::vector<caf::SRTrueParticle> &particles, const std::vector<art::Ptr<recob::Hit>> &hits,
12  const std::map<int, caf::HitsEnergy> &all_hits_map);
13 
14 caf::SRTruthMatch MatchSlice2Truth(const std::vector<art::Ptr<recob::Hit>> &hits,
15  const std::vector<art::Ptr<simb::MCTruth>> &neutrinos,
16  const caf::SRTruthBranch &srtruth,
17  const cheat::ParticleInventoryService &inventory_service,
18  const detinfo::DetectorClocksData &clockData);
19 
20 float ContainedLength(const TVector3 &v0, const TVector3 &v1,
21  const std::vector<geoalgo::AABox> &boxes);
22 
23 bool FRFillNumuCC(const simb::MCTruth &mctruth,
24  const std::vector<art::Ptr<sim::MCTrack>> &mctracks,
25  const std::vector<geo::BoxBoundedGeo> &volumes,
26  TRandom &rand,
27  caf::SRFakeReco &fakereco);
28 bool FRFillNueCC(const simb::MCTruth &mctruth,
29  const std::vector<caf::SRTrueParticle> &srparticle,
30  const std::vector<geo::BoxBoundedGeo> &volumes,
31  TRandom &rand,
32  caf::SRFakeReco &fakereco);
33 
34 // helper function definitions
35 
36 bool isFromNuVertex(const simb::MCTruth& mc, const sim::MCTrack& track,
37  float distance=5.0) {
38  TVector3 nuVtx = mc.GetNeutrino().Nu().Trajectory().Position(0).Vect();
39  TVector3 trkStart = track.Start().Position().Vect();
40  return (trkStart - nuVtx).Mag() < distance;
41 }
42 
43 // returns particle mass in MeV
44 double PDGMass(int pdg) {
45  const TDatabasePDG *PDGTable = TDatabasePDG::Instance();
46  // regular particle
47  if (pdg < 1000000000) {
48  TParticlePDG* ple = PDGTable->GetParticle(pdg);
49  if (ple == NULL) return -1;
50  return ple->Mass() * 1000.0;
51  }
52  // ion
53  else {
54  int p = (pdg % 10000000) / 10000;
55  int n = (pdg % 10000) / 10 - p;
56  return (PDGTable->GetParticle(2212)->Mass() * p +
57  PDGTable->GetParticle(2112)->Mass() * n) * 1000.0;
58  }
59 }
60 
61 double SmearLepton(const caf::SRTrueParticle &lepton, TRandom& rand) {
62  const double smearing = 0.15;
63  // Oscillation tech note says smear ionization deposition, but
64  // code in old samples seems to use true energy.
65  const double true_E = lepton.plane[0][2].visE + lepton.plane[1][2].visE;
66  const double smeared_E = rand.Gaus(true_E, smearing * true_E / std::sqrt(true_E));
67  return std::max(smeared_E, 0.0);
68 }
69 
70 double SmearHadron(const caf::SRTrueParticle &hadron, TRandom& rand) {
71  const double smearing = 0.05;
72  const double true_E = hadron.startE - PDGMass(hadron.pdg) / 1000;
73  const double smeared_E = rand.Gaus(true_E, smearing * true_E);
74  return std::max(smeared_E, 0.0);
75 }
76 
77 
78 //......................................................................
79 void CopyTMatrixDToVector(const TMatrixD& m, std::vector<float>& v)
80 {
81  const double& start = m(0, 0);
82  v.insert(v.end(), &start, &start + m.GetNoElements());
83 }
84 
85 namespace caf {
86 
87  //------------------------------------------------
88 
90  caf::SRGlobal& srglobal,
91  std::map<std::string, unsigned int>& weightPSetIndex)
92  {
93  SRWeightPSet& cafpset = srglobal.wgts.emplace_back();
94 
95  cafpset.name = pset.fName;
96  cafpset.type = caf::ReweightType_t(pset.fRWType);
97  cafpset.nuniv = pset.fNuniverses;
99 
100  weightPSetIndex[cafpset.name] = srglobal.wgts.size()-1;
101 
102  for(const auto& it: pset.fParameterMap){
103  const sbn::evwgh::EventWeightParameter& param = it.first;
104  const std::vector<float>& vals = it.second;
105 
106  SRWeightParam cafparam;
107  cafparam.name = param.fName;
108  cafparam.mean = param.fMean;
109  cafparam.width = param.fWidth;
110  cafparam.covidx = param.fCovIndex;
111 
112  cafpset.map.emplace_back(cafparam, vals);
113  } // end for it
114  }
115 
116  //------------------------------------------------
117 
118  void FillTrackTruth(const std::vector<art::Ptr<recob::Hit>> &hits,
119  const std::map<int, caf::HitsEnergy> &id_hits_map,
120  const std::vector<caf::SRTrueParticle> &particles,
121  const detinfo::DetectorClocksData &clockData,
122  caf::SRTrack& srtrack,
123  bool allowEmpty)
124  {
125  // Truth matching
126  srtrack.truth = MatchTrack2Truth(clockData, particles, hits, id_hits_map);
127 
128  }//FillTrackTruth
129 
130  //------------------------------------------------
131 
132  // TODO: write trith matching for shower. Currently uses track truth matching
133  // N.B. this will only work if showers are rolled up
134  void FillShowerTruth(const std::vector<art::Ptr<recob::Hit>> &hits,
135  const std::map<int, caf::HitsEnergy> &id_hits_map,
136  const std::vector<caf::SRTrueParticle> &particles,
137  const detinfo::DetectorClocksData &clockData,
138  caf::SRShower& srshower,
139  bool allowEmpty)
140  {
141  // Truth matching
142  srshower.truth = MatchTrack2Truth(clockData, particles, hits, id_hits_map);
143 
144  }//FillShowerTruth
145 
146 
147  void FillStubTruth(const std::vector<art::Ptr<recob::Hit>> &hits,
148  const std::map<int, caf::HitsEnergy> &id_hits_map,
149  const std::vector<caf::SRTrueParticle> &particles,
150  const detinfo::DetectorClocksData &clockData,
151  caf::SRStub& srstub,
152  bool allowEmpty)
153  {
154  srstub.truth = MatchTrack2Truth(clockData, particles, hits, id_hits_map);
155  }
156 
157 
158  //------------------------------------------------
159 
160  void FillSliceTruth(const std::vector<art::Ptr<recob::Hit>> &hits,
161  const std::vector<art::Ptr<simb::MCTruth>> &neutrinos,
162  const caf::SRTruthBranch &srmc,
163  const cheat::ParticleInventoryService &inventory_service,
164  const detinfo::DetectorClocksData &clockData,
165  caf::SRSlice &srslice,
166  bool allowEmpty)
167  {
168 
169  caf::SRTruthMatch tmatch = MatchSlice2Truth(hits, neutrinos, srmc, inventory_service, clockData);
170 
171  if (tmatch.index >= 0) {
172  srslice.truth = srmc.nu[tmatch.index];
173  srslice.tmatch = tmatch;
174  }
175 
176  std::cout << "Slice matched to index: " << tmatch.index
177  << " with match frac: " << tmatch.pur << std::endl;
178 
179  }//FillSliceTruth
180 
181 
183  const std::vector<geo::BoxBoundedGeo> &active_volumes,
184  caf::SRMeVPrtl &srtruth) {
185  // Fill stuff!!
186  srtruth.position.x = truth.decay_pos.X();
187  srtruth.position.y = truth.decay_pos.Y();
188  srtruth.position.z = truth.decay_pos.Z();
189  srtruth.time = truth.decay_pos.T();
190 
191  srtruth.momentum.x = truth.mevprtl_mom.X();
192  srtruth.momentum.y = truth.mevprtl_mom.Y();
193  srtruth.momentum.z = truth.mevprtl_mom.Z();
194  srtruth.E = truth.mevprtl_mom.E();
195 
196  // Set the cryostat of the position
197  for (int icryo = 0; icryo < (int)active_volumes.size(); icryo++) {
198  if (active_volumes[icryo].ContainsPosition(truth.decay_pos.Vect())) {
199  srtruth.cryostat = icryo;
200  break;
201  }
202  }
203 
204  srtruth.M = truth.mass;
205  srtruth.flux_weight = truth.flux_weight;
206  srtruth.ray_weight = truth.ray_weight;
207  srtruth.decay_weight = truth.decay_weight;
208  srtruth.decay_length = truth.mean_distance;
209 
210  srtruth.enter.x = truth.mevprtl_enter.X();
211  srtruth.enter.y = truth.mevprtl_enter.Y();
212  srtruth.enter.z = truth.mevprtl_enter.Z();
213  srtruth.exit.x = truth.mevprtl_exit.X();
214  srtruth.exit.y = truth.mevprtl_exit.Y();
215  srtruth.exit.z = truth.mevprtl_exit.Z();
216  srtruth.start.x = truth.mevprtl_start.X();
217  srtruth.start.y = truth.mevprtl_start.Y();
218  srtruth.start.z = truth.mevprtl_start.Z();
219 
220  srtruth.C1 = truth.C1;
221  srtruth.C2 = truth.C2;
222  srtruth.C3 = truth.C3;
223  srtruth.C4 = truth.C4;
224  srtruth.C5 = truth.C5;
225 
226  switch(truth.gen) {
228  srtruth.gen = caf::kMeVPrtlHiggs;
229  break;
230  case evgen::ldm::kHNL:
231  srtruth.gen = caf::kMeVPrtlHNL;
232  break;
233  default:
234  break;
235  }
236  }
237 
238  void FillSliceFakeReco(const std::vector<art::Ptr<recob::Hit>> &hits,
239  const std::vector<art::Ptr<simb::MCTruth>> &neutrinos,
240  const caf::SRTruthBranch &srmc,
241  const cheat::ParticleInventoryService &inventory_service,
242  const detinfo::DetectorClocksData &clockData,
243  caf::SRSlice &srslice,
244  const std::vector<caf::SRTrueParticle> &srparticles,
245  const std::vector<art::Ptr<sim::MCTrack>> &mctracks,
246  const std::vector<geo::BoxBoundedGeo> &volumes, TRandom &rand)
247  {
248  caf::SRTruthMatch tmatch = MatchSlice2Truth(hits, neutrinos, srmc, inventory_service, clockData);
249  if(tmatch.index >= 0) {
250  FRFillNumuCC(*neutrinos[tmatch.index], mctracks, volumes, rand, srslice.fake_reco);
251  if(!srslice.fake_reco.filled)
252  FRFillNueCC(*neutrinos[tmatch.index], srparticles, volumes, rand, srslice.fake_reco);
253  }
254  }//FillSliceFakeReco
255 
256 
257  //------------------------------------------------
258  void FillTrueNeutrino(const art::Ptr<simb::MCTruth> mctruth,
259  const simb::MCFlux &mcflux,
260  const simb::GTruth& gtruth,
261  const std::vector<caf::SRTrueParticle> &srparticles,
262  const std::map<int, std::vector<art::Ptr<recob::Hit>>> &id_to_truehit_map,
263  caf::SRTrueInteraction &srneutrino, size_t i,
264  const std::vector<geo::BoxBoundedGeo> &active_volumes) {
265 
266  srneutrino.index = i;
267 
268  for (int c = 0; c < 2; c++) {
270  init.visE = 0.;
271  init.nhit = 0;
272  init.nhitprim = 0;
273 
274  for (int p = 0; p < 3; p++) {
275  srneutrino.plane[c][p] = init;
276  }
277  }
278 
279  for(const caf::SRTrueParticle& part: srparticles){
280  // save the G4 particles that came from this interaction
281  if(part.interaction_id == (int)i) {
282  if(part.start_process == caf::kG4primary) srneutrino.prim.push_back(part);
283 
284  // total up the deposited energy
285  for(int p = 0; p < 3; ++p) {
286  for (int i_cryo = 0; i_cryo < 2; i_cryo++) {
287  srneutrino.plane[i_cryo][p].visE += part.plane[i_cryo][p].visE;
288  }
289  }
290  }
291  }
292  srneutrino.nprim = srneutrino.prim.size();
293 
294  // Set of hits per-plane: primary particles
295  {
296  std::vector<std::array<std::set<unsigned>, 3>> planehitIDs(2);
297  for (unsigned i_part = 0; i_part < srparticles.size(); i_part++) {
298  if (srparticles[i_part].start_process == caf::kG4primary && srparticles[i_part].interaction_id == (int)i) {
299  int track_id = srparticles[i_part].G4ID;
300  // Look for hits
301  if (!id_to_truehit_map.count(track_id)) continue;
302  for (const art::Ptr<recob::Hit> &h: id_to_truehit_map.at(track_id)) {
303  if (!h->WireID()) continue;
304  planehitIDs[h->WireID().Cryostat][h->WireID().Plane].insert(h.key());
305  }
306  }
307  }
308 
309  for(int p = 0; p < 3; ++p) {
310  for (int i_cryo = 0; i_cryo < 2; i_cryo++) {
311  srneutrino.plane[i_cryo][p].nhitprim = planehitIDs[i_cryo][p].size();
312  }
313  }
314  }
315 
316  // Set of hits per-plane: all particles
317  {
318  std::vector<std::array<std::set<unsigned>, 3>> planehitIDs(2);
319  for (unsigned i_part = 0; i_part < srparticles.size(); i_part++) {
320  if (srparticles[i_part].interaction_id == (int)i) {
321  int track_id = srparticles[i_part].G4ID;
322  // Look for hits
323  if (!id_to_truehit_map.count(track_id)) continue;
324  for (const art::Ptr<recob::Hit> &h: id_to_truehit_map.at(track_id)) {
325  if (!h->WireID()) continue;
326  planehitIDs[h->WireID().Cryostat][h->WireID().Plane].insert(h.key());
327  }
328  }
329  }
330 
331  for(int p = 0; p < 3; ++p) {
332  for (int i_cryo = 0; i_cryo < 2; i_cryo++) {
333  srneutrino.plane[i_cryo][p].nhit = planehitIDs[i_cryo][p].size();
334  }
335  }
336  }
337 
338  // Set the GTruth stuff
339  srneutrino.npiplus = gtruth.fNumPiPlus;
340  srneutrino.npiminus = gtruth.fNumPiMinus;
341  srneutrino.npizero = gtruth.fNumPi0;
342  srneutrino.nproton = gtruth.fNumProton;
343  srneutrino.nneutron = gtruth.fNumNeutron;
344  srneutrino.ischarm = gtruth.fIsCharm;
345  srneutrino.isseaquark = gtruth.fIsSeaQuark;
346  srneutrino.resnum = gtruth.fResNum;
347  srneutrino.xsec = gtruth.fXsec;
348 
349  // Set the MCFlux stuff
350  srneutrino.initpdg = mcflux.fntype;
351  srneutrino.baseline = mcflux.fdk2gen + mcflux.fgen2vtx;
352  srneutrino.parent_pdg = mcflux.fptype;
353  srneutrino.parent_dcy_mode = mcflux.fndecay;
354  srneutrino.prod_vtx.x = mcflux.fvx;
355  srneutrino.prod_vtx.y = mcflux.fvy;
356  srneutrino.prod_vtx.z = mcflux.fvz;
357  srneutrino.parent_dcy_mom.x = mcflux.fpdpx;
358  srneutrino.parent_dcy_mom.y = mcflux.fpdpy;
359  srneutrino.parent_dcy_mom.z = mcflux.fpdpz;
360  float Pmass = PDGMass(mcflux.fptype) / 1000.; // MeV -> GeV
361  srneutrino.parent_dcy_E = sqrt(mcflux.fpdpx*mcflux.fpdpx + mcflux.fpdpy*mcflux.fpdpy + mcflux.fpdpz*mcflux.fpdpz + Pmass*Pmass);
362  srneutrino.imp_weight = mcflux.fnimpwt;
363 
364  if (mctruth->NeutrinoSet()) {
365  // Neutrino
366  const simb::MCNeutrino& nu = mctruth->GetNeutrino();
367  srneutrino.isnc = nu.CCNC() && (nu.Mode() != simb::kWeakMix);
368  srneutrino.iscc = (!nu.CCNC()) && (nu.Mode() != simb::kWeakMix);
369  srneutrino.pdg = nu.Nu().PdgCode();
370  srneutrino.targetPDG = nu.Target();
371  srneutrino.hitnuc = nu.HitNuc();
372  srneutrino.genie_mode = (caf::genie_interaction_mode_)nu.Mode();
373  srneutrino.genie_inttype = (caf::genie_interaction_type_)nu.InteractionType();
374  srneutrino.bjorkenX = nu.X();
375  srneutrino.inelasticityY = nu.Y();
376  srneutrino.Q2 = nu.QSqr();
377  srneutrino.w = nu.W();
378  srneutrino.E = nu.Nu().EndMomentum().Energy();
379  srneutrino.momentum = nu.Nu().EndMomentum().Vect();
380  srneutrino.position = nu.Nu().Position().Vect();
381  srneutrino.time = nu.Nu().Position().T() / 1000. /* ns -> us */;
382  srneutrino.genweight = nu.Nu().Weight();
383 
384  const simb::MCParticle& lepton = nu.Lepton();
385  TLorentzVector q_labframe;
386  q_labframe = nu.Nu().EndMomentum() - lepton.Momentum(0);
387  srneutrino.q0_lab = q_labframe.E();
388  srneutrino.modq_lab = q_labframe.P();
389 
390  // make sure the lepton comes first in the list of prim
391  for (unsigned i_part = 0; i_part < srneutrino.prim.size(); i_part++) {
392  if (srneutrino.prim[i_part].pdg == lepton.PdgCode()) {
393  // swap them
394  caf::SRTrueParticle temp = srneutrino.prim[0];
395  srneutrino.prim[0] = srneutrino.prim[i_part];
396  srneutrino.prim[i_part] = temp;
397  break;
398  }
399  }
400 
401  // Set the cryostat of the position
402  for (int icryo = 0; icryo < 2; icryo++) {
403  if (active_volumes[icryo].ContainsPosition(nu.Nu().Position().Vect())) {
404  srneutrino.cryostat = icryo;
405  break;
406  }
407  }
408  }
409 
410  }
411 
412  //------------------------------------------------
413 
415  caf::SRTrueInteraction& srint,
416  const std::map<std::string, unsigned int>& weightPSetIndex)
417  {
418  for(auto& it: wgtmap){
419  if(weightPSetIndex.count(it.first) == 0){
420  std::cout << "CAFMaker: Unknown EventWeightMap name '" << it.first << "'" << std::endl;
421  std::cout << "Known names from EventWeightParameterSet:" << std::endl;
422  for(auto k: weightPSetIndex) std::cout << " " << k.first << std::endl;
423  abort();
424  }
425 
426  const unsigned int idx = weightPSetIndex.at(it.first);
427  if(idx >= srint.wgt.size()) srint.wgt.resize(idx+1);
428  srint.wgt[idx].univ = it.second;
429  }
430  }
431 
432  //------------------------------------------------
433 
434  void FillTrueG4Particle(const simb::MCParticle &particle,
435  const std::vector<geo::BoxBoundedGeo> &active_volumes,
436  const std::vector<std::vector<geo::BoxBoundedGeo>> &tpc_volumes,
437  const std::map<int, std::vector<std::pair<geo::WireID, const sim::IDE *>>> &id_to_ide_map,
438  const std::map<int, std::vector<art::Ptr<recob::Hit>>> &id_to_truehit_map,
439  const cheat::BackTrackerService &backtracker,
440  const cheat::ParticleInventoryService &inventory_service,
441  const std::vector<art::Ptr<simb::MCTruth>> &neutrinos,
442  caf::SRTrueParticle &srparticle) {
443 
444  std::vector<std::pair<geo::WireID, const sim::IDE *>> empty;
445  const std::vector<std::pair<geo::WireID, const sim::IDE *>> &particle_ides = id_to_ide_map.count(particle.TrackId()) ? id_to_ide_map.at(particle.TrackId()) : empty;
446 
447  std::vector<art::Ptr<recob::Hit>> emptyHits;
448  const std::vector<art::Ptr<recob::Hit>> &particle_hits = id_to_truehit_map.count(particle.TrackId()) ? id_to_truehit_map.at(particle.TrackId()) : emptyHits;
449 
450  srparticle.length = 0.;
451  srparticle.crosses_tpc = false;
452  srparticle.wallin = caf::kWallNone;
453  srparticle.wallout = caf::kWallNone;
454 
455  for (unsigned c = 0; c < 2; c++) {
457  init.visE = 0.;
458  init.nhit = 0;
459 
460  for (int p = 0; p < 3; p++) {
461  srparticle.plane[c][p] = init;
462  }
463  }
464 
465  for (auto const &ide_pair: particle_ides) {
466  const geo::WireID &w = ide_pair.first;
467  const sim::IDE *ide = ide_pair.second;
468 
469  if(w.Plane >= 0 && w.Plane < 3 && w.Cryostat < 2){
470  srparticle.plane[w.Cryostat][w.Plane].visE += ide->energy / 1000. /* MeV -> GeV*/;
471  }
472  }
473 
474  for (const art::Ptr<recob::Hit> h: particle_hits) {
475  const geo::WireID &w = h->WireID();
476 
477  if(w.Plane >= 0 && w.Plane < 3 && w.Cryostat < 2) {
478  srparticle.plane[w.Cryostat][w.Plane].nhit ++;
479  }
480  }
481 
482  // if no trajectory points, then assume outside AV
483  srparticle.cont_tpc = particle.NumberTrajectoryPoints() > 0;
484  srparticle.contained = particle.NumberTrajectoryPoints() > 0;
485 
486  // Get the entry and exit points
487  int entry_point = -1;
488 
489  int cryostat_index = -1;
490  int tpc_index = -1;
491 
492  for (unsigned j = 0; j < particle.NumberTrajectoryPoints(); j++) {
493  for (unsigned i = 0; i < active_volumes.size(); i++) {
494  if (active_volumes.at(i).ContainsPosition(particle.Position(j).Vect())) {
495  entry_point = j;
496  cryostat_index = i;
497  break;
498  }
499  }
500  if (entry_point != -1) break;
501  }
502  // get the wall
503  if (entry_point > 0) {
504  srparticle.wallin = GetWallCross(active_volumes.at(cryostat_index), particle.Position(entry_point).Vect(), particle.Position(entry_point-1).Vect());
505  }
506 
507  int exit_point = -1;
508 
509  // now setup the cryostat the particle is in
510  std::vector<geo::BoxBoundedGeo> volumes;
511  if (entry_point >= 0) {
512  volumes = tpc_volumes.at(cryostat_index);
513  for (unsigned i = 0; i < volumes.size(); i++) {
514  if (volumes[i].ContainsPosition(particle.Position(entry_point).Vect())) {
515  tpc_index = i;
516  srparticle.cont_tpc = entry_point == 0;
517  break;
518  }
519  }
520  srparticle.contained = entry_point == 0;
521  }
522  // if we couldn't find the initial point, set not contained
523  else {
524  srparticle.contained = false;
525  }
526  if (tpc_index < 0) {
527  srparticle.cont_tpc = false;
528  }
529 
530  // setup aa volumes too for length calc
531  // Define the volume used for length calculation to be the cryostat volume in question
532  std::vector<geoalgo::AABox> aa_volumes;
533  if (entry_point >= 0) {
534  const geo::BoxBoundedGeo &v = active_volumes.at(cryostat_index);
535  aa_volumes.emplace_back(v.MinX(), v.MinY(), v.MinZ(), v.MaxX(), v.MaxY(), v.MaxZ());
536  }
537 
538  // Get the length and determine if any point leaves the active volume
539  //
540  // Use every trajectory point if possible
541  if (entry_point >= 0) {
542  // particle trajectory
543  const simb::MCTrajectory &trajectory = particle.Trajectory();
544  TVector3 pos = trajectory.Position(entry_point).Vect();
545  for (unsigned i = entry_point+1; i < particle.NumberTrajectoryPoints(); i++) {
546  TVector3 this_point = trajectory.Position(i).Vect();
547  // get the exit point
548  // update if particle is contained
549  // check if particle has crossed TPC
550  if (!srparticle.crosses_tpc) {
551  for (unsigned j = 0; j < volumes.size(); j++) {
552  if (volumes[j].ContainsPosition(this_point) && tpc_index >= 0 && j != ((unsigned)tpc_index)) {
553  srparticle.crosses_tpc = true;
554  break;
555  }
556  }
557  }
558  // check if particle has left tpc
559  if (srparticle.cont_tpc) {
560  srparticle.cont_tpc = volumes[tpc_index].ContainsPosition(this_point);
561  }
562 
563  if (srparticle.contained) {
564  srparticle.contained = active_volumes.at(cryostat_index).ContainsPosition(this_point);
565  }
566 
567  // update length
568  srparticle.length += ContainedLength(this_point, pos, aa_volumes);
569 
570  if (!active_volumes.at(cryostat_index).ContainsPosition(this_point) && active_volumes.at(cryostat_index).ContainsPosition(pos)) {
571  exit_point = i-1;
572  }
573 
574  pos = trajectory.Position(i).Vect();
575  }
576  }
577  if (exit_point < 0 && entry_point >= 0) {
578  exit_point = particle.NumberTrajectoryPoints() - 1;
579  }
580  if (exit_point >= 0 && ((unsigned)exit_point) < particle.NumberTrajectoryPoints() - 1) {
581  srparticle.wallout = GetWallCross(active_volumes.at(cryostat_index), particle.Position(exit_point).Vect(), particle.Position(exit_point+1).Vect());
582  }
583 
584  // other truth information
585  srparticle.pdg = particle.PdgCode();
586 
587  srparticle.gen = particle.NumberTrajectoryPoints() ? particle.Position().Vect() : TVector3(-9999, -9999, -9999);
588  srparticle.genT = particle.NumberTrajectoryPoints() ? particle.Position().T() / 1000. /* ns -> us*/: -9999;
589  srparticle.genp = particle.NumberTrajectoryPoints() ? particle.Momentum().Vect(): TVector3(-9999, -9999, -9999);
590  srparticle.genE = particle.NumberTrajectoryPoints() ? particle.Momentum().E(): -9999;
591 
592  srparticle.start = (entry_point >= 0) ? particle.Position(entry_point).Vect(): TVector3(-9999, -9999, -9999);
593  srparticle.startT = (entry_point >= 0) ? particle.Position(entry_point).T() / 1000. /* ns-> us*/: -9999;
594  srparticle.end = (exit_point >= 0) ? particle.Position(exit_point).Vect(): TVector3(-9999, -9999, -9999);
595  srparticle.endT = (exit_point >= 0) ? particle.Position(exit_point).T() / 1000. /* ns -> us */ : -9999;
596 
597  srparticle.startp = (entry_point >= 0) ? particle.Momentum(entry_point).Vect() : TVector3(-9999, -9999, -9999);
598  srparticle.startE = (entry_point >= 0) ? particle.Momentum(entry_point).E() : -9999.;
599  srparticle.endp = (exit_point >= 0) ? particle.Momentum(exit_point).Vect() : TVector3(-9999, -9999, -9999);
600  srparticle.endE = (exit_point >= 0) ? particle.Momentum(exit_point).E() : -9999.;
601 
602  srparticle.start_process = GetG4ProcessID(particle.Process());
603  srparticle.end_process = GetG4ProcessID(particle.EndProcess());
604 
605  srparticle.G4ID = particle.TrackId();
606  srparticle.parent = particle.Mother();
607 
608  // Set the initial cryostat
609  srparticle.cryostat = -1;
610  if (entry_point >= 0) {
611  for (unsigned c = 0; c < active_volumes.size(); c++) {
612  if (active_volumes[c].ContainsPosition(particle.Position(entry_point).Vect())) {
613  srparticle.cryostat = c;
614  break;
615  }
616  }
617  }
618 
619  // Save the daughter particles
620  for (int i_d = 0; i_d < particle.NumberDaughters(); i_d++) {
621  srparticle.daughters.push_back(particle.Daughter(i_d));
622  }
623 
624  // See if this MCParticle matches a genie truth
625  srparticle.interaction_id = -1;
626 
627  art::Ptr<simb::MCTruth> truth = inventory_service.TrackIdToMCTruth_P(particle.TrackId());
628  for (unsigned i = 0; i < neutrinos.size(); i++) {
629  if (truth.get() == neutrinos[i].get()) {
630  srparticle.interaction_id = i;
631  break;
632  }
633  }
634  } //FillTrueG4Particle
635 
636  void FillFakeReco(const std::vector<art::Ptr<simb::MCTruth>> &mctruths,
637  const std::vector<caf::SRTrueParticle> &srparticles,
638  const std::vector<art::Ptr<sim::MCTrack>> &mctracks,
639  const std::vector<geo::BoxBoundedGeo> &volumes,
640  TRandom &rand,
641  std::vector<caf::SRFakeReco> &srfakereco) {
642  // iterate and fill
643  for (const art::Ptr<simb::MCTruth> mctruth: mctruths) {
644  bool do_fill = false;
645  caf::SRFakeReco this_fakereco;
646  do_fill = FRFillNumuCC(*mctruth, mctracks, volumes, rand, this_fakereco);
647  if(!do_fill) do_fill = FRFillNueCC(*mctruth, srparticles, volumes, rand, this_fakereco);
648 
649  // TODO: others?
650  // if (!do_fill) ...
651 
652  if (do_fill) srfakereco.push_back(this_fakereco);
653 
654  }
655  }
656 
657  std::map<int, caf::HitsEnergy> SetupIDHitEnergyMap(const std::vector<art::Ptr<recob::Hit>> &allHits,
658  const detinfo::DetectorClocksData &clockData,
659  const cheat::BackTrackerService &backtracker) {
660  std::map<int, caf::HitsEnergy> ret;
661 
662  for (const art::Ptr<recob::Hit> h : allHits) {
663  const int hit_trackID = CAFRecoUtils::GetShowerPrimary(TruthMatchUtils::TrueParticleID(clockData, h, true));
664  ++ret[hit_trackID].nHits;
665 
666  for (const sim::TrackIDE ide : backtracker.HitToTrackIDEs(clockData, h)) {
667  const int ide_trackID = CAFRecoUtils::GetShowerPrimary(ide.trackID);
668  ret[ide_trackID].totE += ide.energy;
669  }
670  }
671  return ret;
672  }
673 
674  std::map<int, std::vector<art::Ptr<recob::Hit>>> PrepTrueHits(const std::vector<art::Ptr<recob::Hit>> &allHits,
675  const detinfo::DetectorClocksData &clockData, const cheat::BackTrackerService &backtracker) {
676  std::map<int, std::vector<art::Ptr<recob::Hit>>> ret;
677  for (const art::Ptr<recob::Hit> h: allHits) {
678  for (int ID: backtracker.HitToTrackIds(clockData, *h)) {
679  ret[abs(ID)].push_back(h);
680  }
681  }
682  return ret;
683  }
684 
685  std::map<int, std::vector<std::pair<geo::WireID, const sim::IDE*>>> PrepSimChannels(const std::vector<art::Ptr<sim::SimChannel>> &simchannels, const geo::GeometryCore &geo) {
686  std::map<int, std::vector<std::pair<geo::WireID, const sim::IDE*>>> ret;
687 
688  for (const art::Ptr<sim::SimChannel> sc : simchannels) {
689  // Lookup the wire of this channel
690  raw::ChannelID_t channel = sc->Channel();
691  std::vector<geo::WireID> maybewire = geo.ChannelToWire(channel);
692  geo::WireID thisWire; // Default constructor makes invalid wire
693  if (maybewire.size()) thisWire = maybewire[0];
694 
695  for (const auto &item : sc->TDCIDEMap()) {
696  for (const sim::IDE &ide: item.second) {
697  // indexing initializes empty vector
698  ret[abs(ide.trackID)].push_back({thisWire, &ide});
699  }
700  }
701  }
702  return ret;
703  }
704 
705 } // end namespace
706 
707 
708 //--------------------------------------------
709 
710 bool FRFillNumuCC(const simb::MCTruth &mctruth,
711  const std::vector<art::Ptr<sim::MCTrack>> &mctracks,
712  const std::vector<geo::BoxBoundedGeo> &volumes,
713  TRandom &rand,
714  caf::SRFakeReco &fakereco) {
715  // Configuration -- TODO: make configurable?
716 
717  // Fiducial Volume
718  float xmin = 10.;
719  float xmax = 10.;
720  float ymin = 10.;
721  float ymax = 10.;
722  float zmin = 10.;
723  float zmax = 100.;
724 
725  // energy smearing
726  float hadron_smearing = 0.05;
727  float lepton_contained_smearing = 0.02;
728  std::function<float (float)> lepton_exiting_smearing = [](float length) {
729  float A = 0.102;
730  float B = 0.000612;
731  return -A * TMath::Log(B * length);
732  };
733 
734  // visible energy threshold
735  float hadronic_energy_threshold = 0.021; // GeV
736 
737  // length cut
738  float contained_length_cut = 50.; // cm
739  float exiting_length_cut = 100.; // cm
740 
741  fakereco.filled = false;
742 
743  // first check if neutrino exists
744  if (!mctruth.NeutrinoSet()) return false;
745 
746  // then check if fiducial
747  int cryo_index = -1;
748  for (unsigned i = 0; i < volumes.size(); i++) {
749  const geo::BoxBoundedGeo &vol = volumes[i];
750  geo::BoxBoundedGeo FV(vol.MinX() + xmin, vol.MaxX() - xmax, vol.MinY() + ymin, vol.MaxY() - ymax, vol.MinZ() + zmin, vol.MaxZ() - zmax);
751  if (FV.ContainsPosition(mctruth.GetNeutrino().Nu().Position().Vect())) {
752  cryo_index = i;
753  break;
754  }
755  }
756 
757  if (cryo_index == -1) return false;
758 
759  std::vector<geoalgo::AABox> aa_volumes;
760  const geo::BoxBoundedGeo &v = volumes.at(cryo_index);
761  aa_volumes.emplace_back(v.MinX(), v.MinY(), v.MinZ(), v.MaxX(), v.MaxY(), v.MaxZ());
762 
763  // look for CC lepton or a \pi^+/- which can "fake" a numu CC interaction
764 
765  int lepton_ind = -1;
766  // CC lepton
767  if (abs(mctruth.GetNeutrino().Nu().PdgCode()) == 14 && mctruth.GetNeutrino().CCNC() == 0) {
768  for (int i = 0; i < (int)mctracks.size(); i++) {
769  if (isFromNuVertex(mctruth, *mctracks[i]) && abs(mctracks[i]->PdgCode()) == 13 && mctracks[i]->Process() == "primary") {
770  if (lepton_ind == -1 || mctracks[lepton_ind]->Start().E() < mctracks[i]->Start().E()) {
771  lepton_ind = i;
772  }
773  }
774  }
775  }
776  // NC pion
777  else if (mctruth.GetNeutrino().CCNC() == 1) {
778  for (int i = 0; i < (int)mctracks.size(); i++) {
779  if (isFromNuVertex(mctruth, *mctracks[i]) && abs(mctracks[i]->PdgCode()) == 211 && mctracks[i]->Process() == "primary") {
780  if (lepton_ind == -1 || mctracks[lepton_ind]->Start().E() < mctracks[i]->Start().E()) {
781  lepton_ind = i;
782  }
783  }
784  }
785  }
786 
787  // no matching track -- no fake reco
788  if (lepton_ind == -1) return false;
789 
790  // Now set the "lepton"
791  caf::SRFakeRecoParticle fake_lepton;
792 
793  fake_lepton.pid = 13;
794  fake_lepton.contained = false;
795  for (const geo::BoxBoundedGeo &vol: volumes) {
796  if (vol.ContainsPosition(mctracks[lepton_ind]->Start().Position().Vect()) && vol.ContainsPosition(mctracks[lepton_ind]->Start().Position().Vect())) {
797  fake_lepton.contained = true;
798  }
799  }
800  fake_lepton.len = ContainedLength(mctracks[lepton_ind]->Start().Position().Vect(), mctracks[lepton_ind]->End().Position().Vect(), aa_volumes);
801  fake_lepton.costh = mctracks[lepton_ind]->Start().Position().Vect().CosTheta();
802 
803  // apply length cut
804  if (fake_lepton.contained && fake_lepton.len < contained_length_cut) return false;
805  if (!fake_lepton.contained && fake_lepton.len < exiting_length_cut) return false;
806 
807 
808  // smear the lepton energy
809  float smearing = fake_lepton.contained ? lepton_contained_smearing : lepton_exiting_smearing(fake_lepton.len);
810  float ke = (mctracks[lepton_ind]->Start().E() - PDGMass(mctracks[lepton_ind]->PdgCode())) / 1000. /* MeV -> GeV*/;
811  fake_lepton.ke = rand.Gaus(ke, smearing * ke);
812  fake_lepton.ke = std::max(fake_lepton.ke, 0.f);
813 
814  // get the hadronic state
815  std::vector<caf::SRFakeRecoParticle> hadrons;
816 
817  for (int i = 0; i < (int)mctracks.size(); i++) {
818  if (isFromNuVertex(mctruth, *mctracks[i]) // from this interaction
819  && (abs(mctracks[i]->PdgCode()) == 211 || abs(mctracks[i]->PdgCode()) == 321 || abs(mctracks[i]->PdgCode()) == 2212) // hadronic
820  && mctracks[i]->Process() == "primary" // primary
821  && i != lepton_ind // not the fake lepton
822  ) {
824  hadron.pid = abs(mctracks[i]->PdgCode());
825  hadron.contained = false;
826  for (const geo::BoxBoundedGeo &vol: volumes) {
827  if (vol.ContainsPosition(mctracks[i]->Start().Position().Vect()) && vol.ContainsPosition(mctracks[i]->Start().Position().Vect())) {
828  hadron.contained = true;
829  }
830  }
831  hadron.len = ContainedLength(mctracks[i]->Start().Position().Vect(), mctracks[i]->Start().Position().Vect(), aa_volumes);
832  hadron.costh = mctracks[i]->Start().Position().Vect().CosTheta();
833 
834  float ke = (mctracks[i]->Start().E() - PDGMass(mctracks[i]->PdgCode())) / 1000. /* MeV -> GeV*/;
835  if (ke < hadronic_energy_threshold) continue;
836 
837  hadron.ke = rand.Gaus(ke, hadron_smearing * ke);
838  hadron.ke = std::max(hadron.ke, 0.f);
839 
840  hadrons.push_back(hadron);
841  }
842  }
843 
844  // total up the energy to get the reco neutrino energy
845  fakereco.nuE = fake_lepton.ke;
846  for (const caf::SRFakeRecoParticle &had: hadrons) fakereco.nuE += had.ke;
847  fakereco.nuE += PDGMass(13) / 1000.; // MeV -.> GeV
848 
849  // save the particles
850  fakereco.lepton = fake_lepton;
851  fakereco.hadrons = hadrons;
852 
853  // other info
854  TVector3 vertex = mctruth.GetNeutrino().Nu().Position().Vect();
855  fakereco.vtx.x = vertex.X();
856  fakereco.vtx.y = vertex.Y();
857  fakereco.vtx.z = vertex.Z();
858 
859  // signal
860  if (abs(mctruth.GetNeutrino().Nu().PdgCode()) == 14 && mctruth.GetNeutrino().CCNC() == 0) {
861  fakereco.wgt = 0.8;
862  }
863  // bkg
864  else {
865  fakereco.wgt = 1.;
866  }
867  fakereco.nhad = fakereco.hadrons.size();
868  fakereco.filled = true;
869 
870  return true;
871 }
872 
873 bool FRFillNueCC(const simb::MCTruth &mctruth,
874  const std::vector<caf::SRTrueParticle> &srparticles,
875  const std::vector<geo::BoxBoundedGeo> &volumes,
876  TRandom &rand,
877  caf::SRFakeReco &fakereco) {
878  // Configuration -- TODO: make configurable?
879 
880  // Fiducial Volume
881  float xmin = 10.;
882  float xmax = 10.;
883  float ymin = 10.;
884  float ymax = 10.;
885  float zmin = 10.;
886  float zmax = 100.;
887 
888  // energy smearing
889 /* auto smear_lepton = [&rand](const caf::SRTrueParticle &lepton) -> float {
890  const double smearing = 0.15;
891  // Oscillation tech note says smear ionization deposition, but
892  // code in old samples seems to use true energy.
893  const double true_E = lepton.plane[0][2].visE + lepton.plane[1][2].visE;
894  const double smeared_E = rand.Gaus(true_E, smearing * true_E / std::sqrt(true_E));
895  return std::max(smeared_E, 0.0);
896  };
897  auto smear_hadron = [&rand](const caf::SRTrueParticle &hadron) -> float {
898  const double smearing = 0.05;
899  const double true_E = hadron.startE - PDGMass(hadron.pdg) / 1000;
900  const double smeared_E = rand.Gaus(true_E, smearing * true_E);
901  return std::max(smeared_E, 0.0);
902  };
903 */
904  // visible energy threshold
905  const float hadronic_energy_threshold = 0.021; // GeV
906 
907  fakereco.filled = false;
908 
909  // first check if neutrino exists
910  if (!mctruth.NeutrinoSet()) return false;
911 
912  TVector3 nuVtx = mctruth.GetNeutrino().Nu().Position().Vect();
913 
914  // then check if fiducial
915  int cryo_index = -1;
916  for (unsigned i = 0; i < volumes.size(); i++) {
917  const geo::BoxBoundedGeo &vol = volumes[i];
918  geo::BoxBoundedGeo FV(vol.MinX() + xmin, vol.MaxX() - xmax, vol.MinY() + ymin, vol.MaxY() - ymax, vol.MinZ() + zmin, vol.MaxZ() - zmax);
919  if (FV.ContainsPosition(nuVtx)) {
920  cryo_index = i;
921  break;
922  }
923  }
924 
925  if (cryo_index == -1) return false;
926 
927  std::vector<geoalgo::AABox> aa_volumes;
928  const geo::BoxBoundedGeo &v = volumes.at(cryo_index);
929  aa_volumes.emplace_back(v.MinX(), v.MinY(), v.MinZ(), v.MaxX(), v.MaxY(), v.MaxZ());
930 
931  //Showers arising from the vertex are identified and the reconstructed energy is found
932  //from smearing the ionisation deposition. If more than one shower with energy above
933  //100 MeV exists, the event is removed. This removes neutral pion events where the
934  //pion decays into two photon showers.
935 
936  std::vector<const caf::SRTrueParticle*> lepton_candidates;
937  for(const auto& particle: srparticles) {
938  const int pdg = std::abs(particle.pdg);
939  const float distance_from_vertex = std::hypot(nuVtx.X() - particle.start.x,
940  nuVtx.Y() - particle.start.y,
941  nuVtx.Z() - particle.start.z);
942  if((pdg == 11 || pdg == 22) && distance_from_vertex < 5) {
943  const auto parent = std::find_if(srparticles.begin(), srparticles.end(),
944  [&particle](const caf::SRTrueParticle& parent_candidate) -> bool {
945  return particle.parent == std::abs(parent_candidate.G4ID);
946  });
947  if((parent == srparticles.end()
948  || !(std::abs((*parent).pdg) == 11 || std::abs((*parent).pdg) == 22))
949  && SmearLepton(particle, rand) > 0.1) {
950  lepton_candidates.push_back(&particle);
951  }
952  }
953  }
954  if(lepton_candidates.size() != 1) return false;
955 
956  const caf::SRTrueParticle* lepton = lepton_candidates[0];
957  caf::SRFakeRecoParticle fake_lepton;
958  fake_lepton.pid = 11;
959  fake_lepton.ke = SmearLepton(*lepton, rand) - PDGMass(11) / 1000;
960  // Should these be set for a shower?
961  // fake_lepton.len = ???;
962  // fake_lepton.costh = ???;
963  // fake_lepton.contained = false;
964 
965  // Get hadrons
966 
967  std::vector<caf::SRFakeRecoParticle> fake_hadrons;
968  float hadronic_E = 0.0;
969  for(const auto& particle: srparticles) {
970  const int pdg = std::abs(particle.pdg);
971  const float ke = SmearHadron(particle, rand);
972  const float distance_from_vertex = std::hypot(nuVtx.X() - particle.start.x,
973  nuVtx.Y() - particle.start.y,
974  nuVtx.Z() - particle.start.z);
975 
976  if((pdg == 2212 || pdg == 211 || pdg == 321) && distance_from_vertex < 5
977  && particle.start_process == caf::kG4primary && ke > hadronic_energy_threshold) {
978  caf::SRFakeRecoParticle fake_hadron;
979  fake_hadron.pid = pdg;
980  fake_hadron.len = ContainedLength(TVector3(particle.start), TVector3(particle.end), aa_volumes);
981  fake_hadron.contained = false;
982  for(const geo::BoxBoundedGeo &vol: volumes) {
983  if(vol.ContainsPosition(TVector3(particle.start))
984  && vol.ContainsPosition(TVector3(particle.end))) {
985  fake_hadron.contained = true;
986  }
987  }
988  fake_hadron.costh = TVector3(particle.start).CosTheta();
989  fake_hadron.ke = ke;
990  hadronic_E += ke;
991  fake_hadrons.push_back(fake_hadron);
992  }
993  }
994 
995  // If there is only one photon candidate in the event, a conversion gap cut is applied.
996  // If the vertex is deemed visible, due to the presence of at least 50 MeV of hadronic
997  // kinetic energy, and the photon starts to shower further than 3 cm from the vertex the
998  // event is removed.
999 
1000  if(lepton->pdg == 22 && hadronic_E > 0.05 && (TVector3(lepton->end) - nuVtx).Mag() > 3)
1001  return false;
1002 
1003  // Remaining photons undergo a dE/dx cut resulting in a 94% background rejection.
1004 
1005  double weight = 1.0;
1006  if(lepton->pdg == 22) weight *= 0.06;
1007 
1008  // If a misidentified photon originates from a resonant numuCC interaction, the muon
1009  // lepton is identified. Events where a muon travels greater than 1 m are assumed to be
1010  // from numuCC interactions and the event is removed.
1011 
1012  if(std::abs(mctruth.GetNeutrino().Nu().PdgCode()) == 14 && mctruth.GetNeutrino().CCNC() == 0) {
1013  const caf::SRTrueParticle* muon = NULL;
1014  for(const auto& particle: srparticles) {
1015  const int pdg = std::abs(particle.pdg);
1016  const float distance_from_vertex = std::hypot(nuVtx.X() - particle.start.x,
1017  nuVtx.Y() - particle.start.y,
1018  nuVtx.Z() - particle.start.z);
1019  if(pdg == 13 && distance_from_vertex < 5 && particle.start_process == caf::kG4primary
1020  && (muon == NULL || muon->startE < particle.startE))
1021  muon = &particle;
1022  }
1023  if(muon != NULL && ContainedLength(TVector3(muon->start), TVector3(muon->end), aa_volumes) > 100)
1024  return false;
1025  }
1026 
1027  // Events where the shower has an energy less than 200 MeV are removed
1028 
1029  if((lepton->plane[0][2].visE + lepton->plane[1][2].visE) < 0.2) return false;
1030 
1031  // total up the energy to get the reco neutrino energy
1032  fakereco.nuE = fake_lepton.ke + PDGMass(11) / 1000 + hadronic_E;
1033 
1034  // save the particles
1035  fakereco.lepton = fake_lepton;
1036  fakereco.hadrons = fake_hadrons;
1037 
1038  // other info
1039  fakereco.vtx.x = nuVtx.X();
1040  fakereco.vtx.y = nuVtx.Y();
1041  fakereco.vtx.z = nuVtx.Z();
1042 
1043  fakereco.wgt = 0.8;
1044  fakereco.wgt *= weight;
1045 
1046  fakereco.nhad = fakereco.hadrons.size();
1047  fakereco.filled = true;
1048 
1049  return true;
1050 }
1051 
1052 caf::Wall_t caf::GetWallCross(const geo::BoxBoundedGeo &volume, const TVector3 p0, const TVector3 p1) {
1053  TVector3 direction = (p1 - p0) * ( 1. / (p1 - p0).Mag());
1054  std::vector<TVector3> intersections = volume.GetIntersections(p0, direction);
1055 
1056  assert(intersections.size() == 2);
1057 
1058  // get the intersection point closer to p0
1059  int intersection_i = ((intersections[0] - p0).Mag() < (intersections[1] - p0).Mag()) ? 0 : 1;
1060 
1061  double eps = 1e-3;
1062  if (abs(intersections[intersection_i].X() - volume.MinX()) < eps) {
1063  //std::cout << "Left\n";
1064  return caf::kWallLeft;
1065  }
1066  else if (abs(intersections[intersection_i].X() - volume.MaxX()) < eps) {
1067  //std::cout << "Right\n";
1068  return caf::kWallRight;
1069  }
1070  else if (abs(intersections[intersection_i].Y() - volume.MinY()) < eps) {
1071  //std::cout << "Bottom\n";
1072  return caf::kWallBottom;
1073  }
1074  else if (abs(intersections[intersection_i].Y() - volume.MaxY()) < eps) {
1075  //std::cout << "Top\n";
1076  return caf::kWallTop;
1077  }
1078  else if (abs(intersections[intersection_i].Z() - volume.MinZ()) < eps) {
1079  //std::cout << "Front\n";
1080  return caf::kWallFront;
1081  }
1082  else if (abs(intersections[intersection_i].Z() - volume.MaxZ()) < eps) {
1083  //std::cout << "Back\n";
1084  return caf::kWallBack;
1085  }
1086  else assert(false);
1087  //std::cout << "None\n";
1088 
1089  return caf::kWallNone;
1090 }//GetWallCross
1091 
1092 //------------------------------------------
1093 
1095 #define MATCH_PROCESS(name) if (process_name == #name) {return caf::kG4 ## name;}
1096 #define MATCH_PROCESS_NAMED(strname, id) if (process_name == #strname) {return caf::kG4 ## id;}
1097  MATCH_PROCESS(primary)
1098  MATCH_PROCESS(CoupledTransportation)
1099  MATCH_PROCESS(FastScintillation)
1101  MATCH_PROCESS(anti_neutronInelastic)
1102  MATCH_PROCESS(neutronInelastic)
1103  MATCH_PROCESS(anti_protonInelastic)
1104  MATCH_PROCESS(protonInelastic)
1105  MATCH_PROCESS(hadInelastic)
1106  MATCH_PROCESS_NAMED(kaon+Inelastic, kaonpInelastic)
1107  MATCH_PROCESS_NAMED(kaon-Inelastic, kaonmInelastic)
1108  MATCH_PROCESS_NAMED(kaon+Inelastic, kaonpInelastic)
1109  MATCH_PROCESS_NAMED(kaon-Inelastic, kaonmInelastic)
1110  MATCH_PROCESS_NAMED(sigma+Inelastic, sigmapInelastic)
1111  MATCH_PROCESS_NAMED(sigma-Inelastic, sigmamInelastic)
1112  MATCH_PROCESS_NAMED(pi+Inelastic, pipInelastic)
1113  MATCH_PROCESS_NAMED(pi-Inelastic, pimInelastic)
1114  MATCH_PROCESS_NAMED(xi+Inelastic, xipInelastic)
1115  MATCH_PROCESS_NAMED(xi-Inelastic, ximInelastic)
1116  MATCH_PROCESS(kaon0LInelastic)
1117  MATCH_PROCESS(kaon0SInelastic)
1118  MATCH_PROCESS(lambdaInelastic)
1119  MATCH_PROCESS_NAMED(anti-lambdaInelastic, anti_lambdaInelastic)
1120  MATCH_PROCESS(He3Inelastic)
1121  MATCH_PROCESS(ionInelastic)
1122  MATCH_PROCESS(xi0Inelastic)
1123  MATCH_PROCESS(alphaInelastic)
1124  MATCH_PROCESS(tInelastic)
1125  MATCH_PROCESS(dInelastic)
1126  MATCH_PROCESS(anti_neutronElastic)
1127  MATCH_PROCESS(neutronElastic)
1128  MATCH_PROCESS(anti_protonElastic)
1129  MATCH_PROCESS(protonElastic)
1130  MATCH_PROCESS(hadElastic)
1131  MATCH_PROCESS_NAMED(kaon+Elastic, kaonpElastic)
1132  MATCH_PROCESS_NAMED(kaon-Elastic, kaonmElastic)
1133  MATCH_PROCESS_NAMED(pi+Elastic, pipElastic)
1134  MATCH_PROCESS_NAMED(pi-Elastic, pimElastic)
1135  MATCH_PROCESS(conv)
1136  MATCH_PROCESS(phot)
1137  MATCH_PROCESS(annihil)
1138  MATCH_PROCESS(nCapture)
1139  MATCH_PROCESS(nKiller)
1140  MATCH_PROCESS(muMinusCaptureAtRest)
1141  MATCH_PROCESS(muIoni)
1142  MATCH_PROCESS(eBrem)
1143  MATCH_PROCESS(CoulombScat)
1144  MATCH_PROCESS(hBertiniCaptureAtRest)
1145  MATCH_PROCESS(hFritiofCaptureAtRest)
1146  MATCH_PROCESS(photonNuclear)
1147  MATCH_PROCESS(muonNuclear)
1148  MATCH_PROCESS(electronNuclear)
1149  MATCH_PROCESS(positronNuclear)
1150  MATCH_PROCESS(compt)
1151  MATCH_PROCESS(eIoni)
1152  MATCH_PROCESS(muBrems)
1153  MATCH_PROCESS(hIoni)
1154  MATCH_PROCESS(ionIoni)
1155  MATCH_PROCESS(hBrems)
1156  MATCH_PROCESS(muPairProd)
1157  MATCH_PROCESS(hPairProd)
1158  MATCH_PROCESS(LArVoxelReadoutScoringProcess)
1159  MATCH_PROCESS(Transportation)
1160  MATCH_PROCESS(msc)
1161  MATCH_PROCESS(StepLimiter)
1162  std::cerr << "Error: Process name with no match (" << process_name << ")\n";
1163  assert(false);
1164  return caf::kG4UNKNOWN; // unreachable in debug mode
1165 #undef MATCH_PROCESS
1166 #undef MATCH_PROCESS_NAMED
1167 
1168 }//GetG4ProcessID
1169 //-------------------------------------------
1170 
1171 float ContainedLength(const TVector3 &v0, const TVector3 &v1,
1172  const std::vector<geoalgo::AABox> &boxes) {
1173  static const geoalgo::GeoAlgo algo;
1174 
1175  // if points are the same, return 0
1176  if ((v0 - v1).Mag() < 1e-6) return 0;
1177 
1178  // construct individual points
1179  geoalgo::Point_t p0(v0);
1180  geoalgo::Point_t p1(v1);
1181 
1182  // construct line segment
1183  geoalgo::LineSegment line(p0, p1);
1184 
1185  double length = 0;
1186 
1187  // total contained length is sum of lengths in all boxes
1188  // assuming they are non-overlapping
1189  for (auto const &box: boxes) {
1190  int n_contained = box.Contain(p0) + box.Contain(p1);
1191  // both points contained -- length is total length (also can break out of loop)
1192  if (n_contained == 2) {
1193  length = (v1 - v0).Mag();
1194  break;
1195  }
1196  // one contained -- have to find intersection point (which must exist)
1197  if (n_contained == 1) {
1198  auto intersections = algo.Intersection(line, box);
1199  // Because of floating point errors, it can sometimes happen
1200  // that there is 1 contained point but no "Intersections"
1201  // if one of the points is right on the edge
1202  if (intersections.size() == 0) {
1203  // determine which point is on the edge
1204  double tol = 1e-5;
1205  bool p0_edge = algo.SqDist(p0, box) < tol;
1206  bool p1_edge = algo.SqDist(p1, box) < tol;
1207  assert(p0_edge || p1_edge);
1208  // contained one is on edge -- can treat both as not contained
1209  //
1210  // In this case, no length
1211  if ((p0_edge && box.Contain(p0)) || (box.Contain(p1) && p1_edge))
1212  continue;
1213  // un-contaned one is on edge -- treat both as contained
1214  else if ((p0_edge && box.Contain(p1)) || (box.Contain(p0) && p1_edge)) {
1215  length = (v1 - v0).Mag();
1216  break;
1217  }
1218  else {
1219  assert(false); // bad
1220  }
1221  }
1222  // floating point errors can also falsely cause 2 intersection points
1223  //
1224  // in this case, one of the intersections must be very close to the
1225  // "contained" point, so the total contained length will be about
1226  // the same as the distance between the two intersection points
1227  else if (intersections.size() == 2) {
1228  length += (intersections.at(0).ToTLorentzVector().Vect() - intersections.at(1).ToTLorentzVector().Vect()).Mag();
1229  continue;
1230  }
1231  // "Correct"/ideal case -- 1 intersection point
1232  else if (intersections.size() == 1) {
1233  // get TVector at intersection point
1234  TVector3 int_tv(intersections.at(0).ToTLorentzVector().Vect());
1235  length += ( box.Contain(p0) ? (v0 - int_tv).Mag() : (v1 - int_tv).Mag() );
1236  }
1237  else assert(false); // bad
1238  }
1239  // none contained -- either must have zero or two intersections
1240  if (n_contained == 0) {
1241  auto intersections = algo.Intersection(line, box);
1242  if (!(intersections.size() == 0 || intersections.size() == 2)) {
1243  // more floating point error fixes...
1244  //
1245  // figure out which points are near the edge
1246  double tol = 1e-5;
1247  bool p0_edge = algo.SqDist(p0, box) < tol;
1248  bool p1_edge = algo.SqDist(p1, box) < tol;
1249  // and which points are near the intersection
1250  TVector3 vint = intersections.at(0).ToTLorentzVector().Vect();
1251 
1252  bool p0_int = (v0 - vint).Mag() < tol;
1253  bool p1_int = (v1 - vint).Mag() < tol;
1254  // exactly one of them should produce the intersection
1255  assert((p0_int && p0_edge) != (p1_int && p1_edge));
1256  // void variables when assert-ions are turned off
1257  (void) p0_int; (void) p1_int;
1258 
1259  // both close to edge -- full length is contained
1260  if (p0_edge && p1_edge) {
1261  length += (v0 - v1).Mag();
1262  }
1263  // otherwise -- one of them is not on an edge, no length is contained
1264  else {}
1265  }
1266  // assert(intersections.size() == 0 || intersections.size() == 2);
1267  else if (intersections.size() == 2) {
1268  TVector3 start(intersections.at(0).ToTLorentzVector().Vect());
1269  TVector3 end(intersections.at(1).ToTLorentzVector().Vect());
1270  length += (start - end).Mag();
1271  }
1272  }
1273  }
1274 
1275  return length;
1276 }//ContainedLength
1277 
1278 //------------------------------------------------
1279 caf::SRTrackTruth MatchTrack2Truth(const detinfo::DetectorClocksData &clockData, const std::vector<caf::SRTrueParticle> &particles, const std::vector<art::Ptr<recob::Hit>> &hits,
1280  const std::map<int, caf::HitsEnergy> &all_hits_map) {
1281 
1282  art::ServiceHandle<cheat::BackTrackerService> bt_serv;
1283 
1284  // this id is the same as the mcparticle ID as long as we got it from geant4
1285  std::vector<std::pair<int, float>> matches = CAFRecoUtils::AllTrueParticleIDEnergyMatches(clockData, hits, true);
1286  float total_energy = CAFRecoUtils::TotalHitEnergy(clockData, hits);
1287  std::map<int, caf::HitsEnergy> track_hits_map = caf::SetupIDHitEnergyMap(hits, clockData, *bt_serv.get());
1288 
1289  caf::SRTrackTruth ret;
1290 
1291  ret.visEintrk = total_energy / 1000. /* MeV -> GeV */;
1292 
1293  // setup the matches
1294  for (auto const &pair: matches) {
1295  caf::SRParticleMatch match;
1296  match.G4ID = pair.first;
1297  match.energy = pair.second / 1000. /* MeV -> GeV */;
1298 
1299  caf::HitsEnergy track_matched_hits = track_hits_map.find(match.G4ID)->second;
1300  caf::HitsEnergy all_matched_hits = all_hits_map.find(match.G4ID)->second;
1301 
1302  match.hit_purity = (hits.size() != 0) ? track_matched_hits.nHits / (float) hits.size() : 0.;
1303  match.energy_purity = (ret.visEintrk > 0) ? match.energy / ret.visEintrk : 0.;
1304  match.hit_completeness = (all_matched_hits.nHits != 0) ? track_matched_hits.nHits / (float) all_matched_hits.nHits : 0.;
1305  match.energy_completeness = (all_matched_hits.totE > 0) ? pair.second / all_matched_hits.totE : 0.;
1306 
1307  ret.matches.push_back(match);
1308  }
1309 
1310  // sort highest energy match to lowest
1311  std::sort(ret.matches.begin(), ret.matches.end(),
1312  [](const caf::SRParticleMatch &a, const caf::SRParticleMatch &b) {
1313  return a.energy > b.energy;
1314  }
1315  );
1316 
1317  bool found_bestmatch = false;
1318  if (ret.matches.size()) {
1319  ret.bestmatch = ret.matches.at(0);
1320  for (unsigned i_part = 0; i_part < particles.size(); i_part++) {
1321  if (particles[i_part].G4ID == ret.bestmatch.G4ID) {
1322  ret.p = particles[i_part];
1323  found_bestmatch = true;
1324  break;
1325  }
1326  }
1327  }
1328 
1329  // Calculate efficiency / purity
1330  if (found_bestmatch) {
1331  double match_total_energy = 0.;
1332  for (int p = 0; p < 3; p++) {
1333  for (int c = 0; c < 2; c++) {
1334  match_total_energy += ret.p.plane[c][p].visE;
1335  }
1336  }
1337 
1338  ret.eff = ret.matches[0].energy / match_total_energy;
1339  ret.pur = ret.matches[0].energy / ret.visEintrk;
1340 
1341  int icryo = -1;
1342  if (!hits.empty()) {
1343  icryo = hits[0]->WireID().Cryostat;
1344  }
1345 
1346  assert(icryo < 2);
1347  if (icryo >= 0 && icryo < 2) {
1348  float match_cryo_energy = ret.p.plane[icryo][0].visE + ret.p.plane[icryo][1].visE + ret.p.plane[icryo][2].visE;
1349  ret.eff_cryo = ret.matches[0].energy / match_cryo_energy;
1350  }
1351  else {
1352  ret.eff_cryo = -1;
1353  }
1354 
1355  }
1356  else {
1357  ret.eff = -1.;
1358  ret.pur = -1.;
1359  ret.eff_cryo = -1.;
1360  }
1361 
1362  ret.nmatches = ret.matches.size();
1363 
1364  return ret;
1365 }//MatchTrack2Truth
1366 //------------------------------------------------
1367 caf::SRTruthMatch MatchSlice2Truth(const std::vector<art::Ptr<recob::Hit>> &hits,
1368  const std::vector<art::Ptr<simb::MCTruth>> &truths,
1369  const caf::SRTruthBranch &srmc,
1370  const cheat::ParticleInventoryService &inventory_service,
1371  const detinfo::DetectorClocksData &clockData) {
1372  caf::SRTruthMatch ret;
1373  float total_energy = CAFRecoUtils::TotalHitEnergy(clockData, hits);
1374  // speed optimization: if there are no truths, all the matching energy must be cosmic
1375  if (truths.empty()) {
1376  ret.visEinslc = total_energy / 1000. /* MeV -> GeV */;
1377  ret.visEcosmic = total_energy / 1000. /* MeV -> GeV */;
1378  ret.eff_cryo = -1.;
1379  ret.eff = -1;
1380  ret.pur = -1;
1381  ret.index = -1;
1382  return ret;
1383  }
1384  std::vector<std::pair<int, float>> matches = CAFRecoUtils::AllTrueParticleIDEnergyMatches(clockData, hits, true);
1385  std::vector<float> matching_energy(truths.size(), 0.);
1386  for (auto const &pair: matches) {
1387  art::Ptr<simb::MCTruth> truth;
1388  try {
1389  truth = inventory_service.TrackIdToMCTruth_P(pair.first);
1390  }
1391  // Ignore track ID's that cannot be looked up
1392  catch(...) {
1393  continue;
1394  }
1395  for (unsigned ind = 0; ind < truths.size(); ind++) {
1396  if (truth == truths[ind]) {
1397  matching_energy[ind] += pair.second;
1398  break;
1399  }
1400  }
1401  }
1402 
1403  float cosmic_energy = total_energy;
1404  for (float E: matching_energy) cosmic_energy -= E;
1405 
1406  float matching_frac = *std::max_element(matching_energy.begin(), matching_energy.end()) / total_energy;
1407  int index = (matching_frac > 0.5) ? std::distance(matching_energy.begin(), std::max_element(matching_energy.begin(), matching_energy.end())) : -1;
1408 
1409  ret.index = index;
1410  if (index >= 0) {
1411  ret.visEinslc = total_energy / 1000. /* MeV -> GeV */;
1412  ret.visEcosmic = cosmic_energy / 1000. /* MeV -> GeV */;
1413  ret.pur = matching_energy[index] / total_energy;
1414 
1415  double totVisE = 0.;
1416  for (int p = 0; p < 3; p++) {
1417  for (int c = 0; c < 2; c++) {
1418  totVisE += srmc.nu[index].plane[c][p].visE;
1419  }
1420  }
1421 
1422  ret.eff = (matching_energy[index] / 1000.) / totVisE;
1423 
1424  // Lookup the cryostat
1425  int icryo = -1;
1426  if (!hits.empty()) {
1427  icryo = hits[0]->WireID().Cryostat;
1428  }
1429 
1430  if (icryo >= 0) {
1431  ret.eff_cryo = (matching_energy[index] / 1000.) /
1432  (srmc.nu[index].plane[icryo][0].visE + srmc.nu[index].plane[icryo][1].visE + srmc.nu[index].plane[icryo][2].visE);
1433  }
1434  else {
1435  ret.eff_cryo = -1;
1436  }
1437 
1438  }
1439  else {
1440  ret.pur = -1;
1441  ret.eff = -1;
1442  ret.eff_cryo = -1;
1443  }
1444  return ret;
1445 }//Slc2Truth
TrackID_t trackID
Geant4 supplied track ID.
Definition: SimChannel.h:116
float imp_weight
Importance weight from flux file.
double SmearHadron(const caf::SRTrueParticle &hadron, TRandom &rand)
Definition: FillTrue.cxx:70
process_name vertex
Definition: cheaterreco.fcl:51
TLorentzVector decay_pos
Definition: MeVPrtlTruth.h:30
unsigned int npiplus
Number of &#39;s after neutrino reaction, before FSI.
float genweight
Weight, if any, assigned by the generator.
std::map< int, std::vector< std::pair< geo::WireID, const sim::IDE * > > > PrepSimChannels(const std::vector< art::Ptr< sim::SimChannel >> &simchannels, const geo::GeometryCore &geo)
Definition: FillTrue.cxx:685
SRTruthMatch tmatch
Matching information between truth and reco objects.
Definition: SRSlice.h:37
int initpdg
Initial PDG code of probe neutrino.
unsigned int nneutron
Number of neutrons after neutrino reaction, before FSI.
SRTrackTruth truth
truth information
Definition: SRStub.h:52
bool isseaquark
Did neutrino scatter off a sea quark.
double PDGMass(int pdg)
Definition: FillTrue.cxx:44
Algorithm to compute various geometrical relation among geometrical objects. In particular functions ...
std::map< std::string, std::vector< float > > EventWeightMap
Container for event-level weights.
float genE
Energy at generation pt [GeV].
double ContainedLength(const TVector3 &v0, const TVector3 &v1, const std::vector< geo::BoxBoundedGeo > &boxes)
Definition: Interaction.cxx:28
SRVector3D parent_dcy_mom
Neutrino parent momentum at decay [GeV; beam coordinates].
var pdg
Definition: selectors.fcl:14
unsigned parent
ID&#39;s of parent particle from this particle.
double ray_weight
Weight associated with the Portal hitting the detector.
Definition: SRMeVPrtl.h:31
ReweightType_t type
Definition: SRWeightPSet.h:17
float inelasticityY
Inelasticity y.
std::vector< sim::TrackIDE > HitToTrackIDEs(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
BEGIN_PROLOG could also be cerr
SRVector3D start
Start position in the active TPC volume [cm].
void FillTrueNeutrino(const art::Ptr< simb::MCTruth > mctruth, const simb::MCFlux &mcflux, const simb::GTruth &gtruth, const std::vector< caf::SRTrueParticle > &srparticles, const std::map< int, std::vector< art::Ptr< recob::Hit >>> &id_to_truehit_map, caf::SRTrueInteraction &srneutrino, size_t i, const std::vector< geo::BoxBoundedGeo > &active_volumes)
Definition: FillTrue.cxx:258
std::string name
Definition: SRWeightParam.h:11
void FillStubTruth(const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &id_hits_map, const std::vector< caf::SRTrueParticle > &particles, const detinfo::DetectorClocksData &clockData, caf::SRStub &srstub, bool allowEmpty)
Definition: FillTrue.cxx:147
bool contained
Whether contained.
The SRTrueInteraction is a representation of neutrino interaction information.
SRVector3D position
Neutrino interaction position.
float xsec
xsec for thrown interaction, in 1/GeV^2, as stored by the GENIE spline
int resnum
Resonance number, straight from GENIE.
auto const tol
Definition: SurfXYZTest.cc:16
int nprim
Number of primary daughters.
SRVector3D prod_vtx
Neutrino production vertex [cm; beam coordinates].
double SqDist(const Line_t &line, const Point_t &pt) const
float E
True energy [GeV].
process_name Decay
pdgs p
Definition: selectors.fcl:22
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:88
caf::SRTruthMatch MatchSlice2Truth(const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, const caf::SRTruthBranch &srtruth, const cheat::ParticleInventoryService &inventory_service, const detinfo::DetectorClocksData &clockData)
Definition: FillTrue.cxx:1367
Representation of a simple 3D line segment Defines a finite 3D straight line by having the start and ...
Wall_t
Definition: SREnums.h:22
std::string fName
Parameter name.
An SRTruthMatch contains overarching information for a slice.
Definition: SRTruthMatch.h:15
float endT
End time last point in the active [us – t=0 is spill time].
int cryostat
Cryostat that the particle enters first – -1 if it does not enter a Cryostat.
G4ID TrueParticleID(detinfo::DetectorClocksData const &clockData, const art::Ptr< recob::Hit > &pHit, const bool rollupUnsavedIDs)
The G4 ID of the true particle which deposits the most energy in the recob::Hit.
SRVector3D startp
Momentum at first point in the active TPC volume [GeV/c].
float ke
Fake-reco kinetic energy [GeV].
double SmearLepton(const caf::SRTrueParticle &lepton, TRandom &rand)
Definition: FillTrue.cxx:61
float eff
Slice efficiency for this interaction.
Definition: SRTruthMatch.h:22
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
SRTrueInteraction truth
Truth information on the slice.
Definition: SRSlice.h:36
double time
Decay time [us].
Definition: SRMeVPrtl.h:23
genie_interaction_type_ genie_inttype
Following LARSoft MCNeutrino::InteractionType()
float len
Fake-reco particle length [cm].
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:91
unsigned int nproton
Number of protons after neutrino reaction, before FSI.
process_name E
process_name use argoneut_mc_hitfinder track
The SRFakeRecoParticle is a faked reconstruction using estimates from the SBN proposal.
genie_interaction_mode_
Definition: SREnums.h:62
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
double flux_weight
Weight associated with the production of the Portal.
Definition: SRMeVPrtl.h:30
void FillSliceTruth(const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, const caf::SRTruthBranch &srmc, const cheat::ParticleInventoryService &inventory_service, const detinfo::DetectorClocksData &clockData, caf::SRSlice &srslice, bool allowEmpty)
Definition: FillTrue.cxx:160
float visEintrk
True total deposited energy associated with this Track across all 3 planes [GeV]. NOTE: this energy i...
Definition: SRTrackTruth.h:22
caf::SRVector3D momentum
Portal momentum [GeV].
Definition: SRMeVPrtl.h:24
std::vector< SRWeightPSet > wgts
Definition: SRGlobal.h:13
bool isFromNuVertex(const simb::MCTruth &mc, const sim::MCTrack &track, float distance=5.0)
Definition: FillTrue.cxx:36
double decay_length
Mean decay length of particle.
Definition: SRMeVPrtl.h:34
g4_process_
Which G4 process ?
Definition: SREnums.h:155
float visEinslc
True deposited energy in slice [GeV].
Definition: SRTruthMatch.h:25
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
float hit_completeness
The fraction of the best true particle&#39;s hits contained by the reconstructed object.
int parent_pdg
PDG Code of parent particle ID.
std::vector< int > HitToTrackIds(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
float eff_cryo
Slice efficiency for this interaction for energy in the slice&#39;s cryostat.
Definition: SRTruthMatch.h:23
float energy
Total energy matching between reco track and true particle across all three planes [GeV]...
std::map< int, caf::HitsEnergy > SetupIDHitEnergyMap(const std::vector< art::Ptr< recob::Hit >> &allHits, const detinfo::DetectorClocksData &clockData, const cheat::BackTrackerService &backtracker)
Definition: FillTrue.cxx:657
bool contained
Whether the particle is contained in a single active volume.
caf::mevprtlchannel_ gen
Generator physics channel for this event.
Definition: SRMeVPrtl.h:21
Wall_t wallout
Wall of cryostat particle exits (wNone if stopping in detector)
process_name gaushit a
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
int pdg
PDG code of probe neutrino.
while getopts h
std::vector< std::pair< int, float > > AllTrueParticleIDEnergyMatches(const detinfo::DetectorClocksData &clockData, const std::vector< art::Ptr< recob::Hit > > &hits, bool rollup_unsaved_ids=1)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
std::vector< SRTrueParticle > prim
Primary daughters, lepton comes first in vector.
caf::SRVector3D position
Decay location [cm].
Definition: SRMeVPrtl.h:22
T abs(T value)
TMatrixD * fCovarianceMatrix
Covariance matrix for correlated throws (optional)
std::vector< SRTrueInteraction > nu
Vector of true nu or cosmic.
Definition: SRTruthBranch.h:21
ReweightType fRWType
Type of throws (the same for all parameters in a set)
unsigned int nhitprim
Number of hits from primary particles on plane.
size_t fCovIndex
Index in the covariance matrix (if any)
bool ischarm
Is a charmed quark in interaction.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
void FillShowerTruth(const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &id_hits_map, const std::vector< caf::SRTrueParticle > &particles, const detinfo::DetectorClocksData &clockData, caf::SRShower &srshower, bool allowEmpty)
Definition: FillTrue.cxx:134
unsigned int nhit
Number of hits on plane.
bool crosses_tpc
Whether the particle crosses a TPC boundary.
int pid
Fake-reco particle ID.
A single parameter to be reweighted.
SRVector3D genp
Momentum at generation point [GeV/c].
caf::g4_process_ GetG4ProcessID(const std::string &name)
Definition: FillTrue.cxx:1094
ReweightType_t
Definition: SREnums.h:224
Ionization at a point of the TPC sensitive volume.
Definition: SimChannel.h:86
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int id) const
g4_process_ end_process
End G4 process of the particle.
float length
Trajectory length in active TPC volume the particle first enters [cm].
double M
Portal Mass [GeV].
Definition: SRMeVPrtl.h:26
SRVector3D momentum
Neutrino three-momentum.
std::vector< SRWeightMapEntry > map
Definition: SRWeightPSet.h:21
float energy
energy deposited by ionization by this track ID and time [MeV]
Definition: SimChannel.h:118
bool FRFillNueCC(const simb::MCTruth &mctruth, const std::vector< caf::SRTrueParticle > &srparticle, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand, caf::SRFakeReco &fakereco)
Definition: FillTrue.cxx:873
Container for a set of reweightable parameters.
pdgs pi
Definition: selectors.fcl:22
int nhad
Number of hadrons.
Definition: SRFakeReco.h:25
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
float nuE
Fake-reco neutrino Energy [GeV].
Definition: SRFakeReco.h:21
double MinZ() const
Returns the world z coordinate of the start of the box.
bool FRFillNumuCC(const simb::MCTruth &mctruth, const std::vector< art::Ptr< sim::MCTrack >> &mctracks, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand, caf::SRFakeReco &fakereco)
Definition: FillTrue.cxx:710
float bjorkenX
Bjorken x = (k-k&#39;)^2/(2*p.q) [Dimensionless].
std::map< EventWeightParameter, std::vector< float > > fParameterMap
Mapping of definitions to the set of values.
unsigned int npizero
Number of &#39;s after neutrino reaction, before FSI.
bool isnc
same as LArSoft &quot;ccnc&quot; - 0=CC, 1=NC
void FillFakeReco(const std::vector< art::Ptr< simb::MCTruth >> &mctruths, const std::vector< caf::SRTrueParticle > &srparticles, const std::vector< art::Ptr< sim::MCTrack >> &mctracks, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand, std::vector< caf::SRFakeReco > &srfakereco)
Definition: FillTrue.cxx:636
float startT
Start time of first TPC point [us – t=0 is spill time].
genie_interaction_type_
Definition: SREnums.h:82
caf::SRVector3D enter
Entry position of particle into Active Volume.
Definition: SRMeVPrtl.h:35
float costh
Fake-reco cosine of angle w.r.t. beam direction.
void FillMeVPrtlTruth(const evgen::ldm::MeVPrtlTruth &truth, const std::vector< geo::BoxBoundedGeo > &active_volumes, caf::SRMeVPrtl &srtruth)
Definition: FillTrue.cxx:182
float genT
Start time of gen point [us – t=0 is spill time].
float endE
Energy at last pt in active TPC volume [GeV].
float wgt
Weight for this interaction.
Definition: SRFakeReco.h:26
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
float energy_purity
The fraction of the reconstructed object&#39;s energy that originates from the best true particle...
j template void())
Definition: json.hpp:3108
Description of geometry of one entire detector.
size_t fNuniverses
Number of universes (i.e. random throws)
float w
Hadronic invariant mass W.
An SRSlice contains overarching information for a slice.
Definition: SRSlice.h:24
double E
Portal Energy [GeV].
Definition: SRMeVPrtl.h:25
std::string name
Definition: SRWeightPSet.h:16
SRTrueInteractionPlaneInfo plane[2][3]
Per-plane, per-cryostat deposition information.
float pur
Slice purity for this interaction.
Definition: SRTruthMatch.h:24
int index
Index of the matched true neutrino interaction (-1 if not matched to neutrino)
Definition: SRTruthMatch.h:27
SRTrackTruth truth
truth information
Definition: SRTrack.h:54
caf::SRTrackTruth MatchTrack2Truth(const detinfo::DetectorClocksData &clockData, const std::vector< caf::SRTrueParticle > &particles, const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &all_hits_map)
Definition: FillTrue.cxx:1279
double MaxY() const
Returns the world y coordinate of the end of the box.
float q0_lab
q0, lab frame
void FillTrueG4Particle(const simb::MCParticle &particle, const std::vector< geo::BoxBoundedGeo > &active_volumes, const std::vector< std::vector< geo::BoxBoundedGeo >> &tpc_volumes, const std::map< int, std::vector< std::pair< geo::WireID, const sim::IDE * >>> &id_to_ide_map, const std::map< int, std::vector< art::Ptr< recob::Hit >>> &id_to_truehit_map, const cheat::BackTrackerService &backtracker, const cheat::ParticleInventoryService &inventory_service, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, caf::SRTrueParticle &srparticle)
Definition: FillTrue.cxx:434
int G4ID
ID of the particle match, taken from G4 */.
std::vector< SRFakeRecoParticle > hadrons
Fake-reco information on hadronic state.
Definition: SRFakeReco.h:24
bool iscc
CC (true) or NC/interference (false)
float parent_dcy_E
Neutrino parent energy at decay [GeV].
SRFakeReco fake_reco
Definition: SRSlice.h:43
int interaction_id
Neutrino interaction ID of the source of this particle (-1 if cosmic)
SRVector3D end
End position in the active TPC volume [cm].
float startE
Energy at first pt in active TPC volume [GeV].
g4_process_ start_process
Start G4 process of the particle.
float baseline
Distance from decay to interaction [m].
int cryostat
Cryostat that the decay occurs in.
Definition: SRMeVPrtl.h:28
void CopyTMatrixDToVector(const TMatrixD &m, std::vector< float > &v)
Definition: FillTrue.cxx:79
process_name can override from command line with o or output muon
Definition: runPID.fcl:28
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:33
static const TDatabasePDG * PDGTable(new TDatabasePDG)
SRVector3D endp
Momentum at last point in the active TPC volume [GeV/c].
void FillTrackTruth(const std::vector< art::Ptr< recob::Hit >> &hits, const std::map< int, caf::HitsEnergy > &id_hits_map, const std::vector< caf::SRTrueParticle > &particles, const detinfo::DetectorClocksData &clockData, caf::SRTrack &srtrack, bool allowEmpty)
Definition: FillTrue.cxx:118
Contains all timing reference information for the detector.
void FillSliceFakeReco(const std::vector< art::Ptr< recob::Hit >> &hits, const std::vector< art::Ptr< simb::MCTruth >> &neutrinos, const caf::SRTruthBranch &srmc, const cheat::ParticleInventoryService &inventory_service, const detinfo::DetectorClocksData &clockData, caf::SRSlice &srslice, const std::vector< caf::SRTrueParticle > &srparticles, const std::vector< art::Ptr< sim::MCTrack >> &mctracks, const std::vector< geo::BoxBoundedGeo > &volumes, TRandom &rand)
Definition: FillTrue.cxx:238
Wall_t wallin
Wall of cryostat particle enters (wNone if starting in detector)
std::map< int, std::vector< art::Ptr< recob::Hit > > > PrepTrueHits(const std::vector< art::Ptr< recob::Hit >> &allHits, const detinfo::DetectorClocksData &clockData, const cheat::BackTrackerService &backtracker)
Definition: FillTrue.cxx:674
caf::SRVector3D exit
Exit position of particle into Active Volume.
Definition: SRMeVPrtl.h:36
float hit_purity
The fraction of the reconstructed object&#39;s hits that originate from the best true particle...
double MaxZ() const
Returns the world z coordinate of the end of the box.
#define MATCH_PROCESS(name)
int G4ID
ID of the particle (taken from G4 – -1 if this particle is not propogated by G4)
std::vector< float > covmx
Definition: SRWeightPSet.h:19
Vectors of reconstructed vertices found by various algorithms.
Definition: SRTruthBranch.h:15
TLorentzVector mevprtl_start
Definition: MeVPrtlTruth.h:26
do i e
std::vector< TVector3 > GetIntersections(TVector3 const &TrajectoryStart, TVector3 const &TrajectoryDirect) const
Calculates the entry and exit points of a trajectory on the box surface.
std::string fName
Name of the parameter set.
unsigned int npiminus
Number of &#39;s after neutrino reaction, before FSI.
Representation of a simb::MCParticle, knows energy, direction,.
int index
Index of the matched true neutrino interaction (-1 if not matched to neutrino)
const MCStep & Start() const
Definition: MCTrack.h:44
caf::SRVector3D start
Start position of Portal in detector coordinates [cm].
Definition: SRMeVPrtl.h:37
float TotalHitEnergy(const detinfo::DetectorClocksData &clockData, const std::vector< art::Ptr< recob::Hit > > &hits)
int parent_dcy_mode
Parent hadron/muon decay mode.
float energy_completeness
The fraction of the best true particle&#39;s energy contained by the reconstructed object.
SRVector3D gen
Generation position [cm].
genie_interaction_mode_ genie_mode
Interaction mode (as for LArSoft MCNeutrino::Mode() )
pdgs k
Definition: selectors.fcl:22
float visEcosmic
True slice deposited energy from cosmics.
Definition: SRTruthMatch.h:26
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
SRVector3D vtx
Interaction vertex in detector coordinates [cm].
Definition: SRFakeReco.h:22
const TLorentzVector & Position() const
Definition: MCStep.h:40
Match from a reconstructed track to a true particle */.
float A
Definition: dedx.py:137
std::vector< SRMultiverse > wgt
Systematic weights.
bool cont_tpc
Whether the particle is contained in a single TPC.
std::vector< Point_t > Intersection(const AABox_t &box, const HalfLine_t &line, bool back=false) const
Intersection between a HalfLine and an AABox.
std::vector< unsigned > daughters
ID&#39;s of daughter particles from this particle.
SRFakeRecoParticle lepton
Fake-reco lepton information.
Definition: SRFakeReco.h:23
void FillEventWeight(const sbn::evwgh::EventWeightMap &wgtmap, caf::SRTrueInteraction &srint, const std::map< std::string, unsigned int > &weightPSetIndex)
Definition: FillTrue.cxx:414
int pdg
Particle ID code.
double MinY() const
Returns the world y coordinate of the start of the box.
bool empty(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:555
The SRFakeReco is a faked reconstruction using estimates from the SBN proposal.
Definition: SRFakeReco.h:15
Ionization energy from a Geant4 track.
Definition: SimChannel.h:26
BEGIN_PROLOG SN nu
void FillSRGlobal(const sbn::evwgh::EventWeightParameterSet &pset, caf::SRGlobal &srglobal, std::map< std::string, unsigned int > &weightPSetIndex)
Definition: FillTrue.cxx:89
int cryostat
Cryostat the the Interaction originates in. -1 if it originates outside a cryostat.
float visE
Sum of energy deposited on plane [GeV].
float modq_lab
|q|, lab frame
SRTrueParticlePlaneInfo plane[2][3]
Per-plane, per-cryostat deposition information.
TLorentzVector mevprtl_mom
Definition: MeVPrtlTruth.h:25
physics associatedGroupsWithLeft p1
BEGIN_PROLOG could also be cout
#define MATCH_PROCESS_NAMED(strname, id)
double decay_weight
Weight associated with the Portal decaying.
Definition: SRMeVPrtl.h:32
float visE
Sum of energy deposited on plane [GeV].
SRTrackTruth truth
truth information TODO: make seperate showe info class
Definition: SRShower.h:50
unsigned int nhit
Number of hits on plane.
caf::Wall_t GetWallCross(const geo::BoxBoundedGeo &volume, const TVector3 p0, const TVector3 p1)
Definition: FillTrue.cxx:1052
BEGIN_PROLOG sequence::SlidingWindowTriggerPatternsOppositeWindows END_PROLOG process_name