All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NumuReco.cxx
Go to the documentation of this file.
1 #include <list>
2 #include <string>
3 #include <iostream>
4 #include <cmath>
5 #include <vector>
6 #include <queue>
7 
8 #include "fhiclcpp/ParameterSet.h"
9 
10 #include <TParameter.h>
11 #include <TH2D.h>
12 #include <TH1D.h>
13 
14 #include "gallery/ValidHandle.h"
15 #include "canvas/Utilities/InputTag.h"
16 #include "canvas/Persistency/Common/FindMany.h"
17 
18 #include "nusimdata/SimulationBase/MCTruth.h"
19 #include "nusimdata/SimulationBase/MCNeutrino.h"
20 #include "nusimdata/SimulationBase/MCNeutrino.h"
32 
36 
37 #include "core/Event.hh"
38 #include "core/Experiment.hh"
39 #include "NumuReco.h"
40 #include "../SBNOsc/Utilities.h"
41 #include "../RecoUtils/RecoUtils.h"
42 #include "../RecoUtils/GeoUtil.h"
43 #include "../NumuReco/PrimaryTrack.h"
44 #include "../NumuReco/TruthMatch.h"
46 
47 #include "ubcore/LLBasicTool/GeoAlgo/GeoAABox.h"
48 #include "canvas/Persistency/Provenance/ProductID.h"
49 
53 #ifdef CRTTrack_hh_
54 #undef CRTTrack_hh_
55 #endif
59 
60 // copied in RecoUtils here to not use art services
61 
62 namespace ana {
63  namespace SBNOsc {
64 
65 const static TVector3 InvalidTVector3 = TVector3(-999, -999, -999);
66 
67 void DumpTrueStart(const gallery::Event &ev, int mcparticle_id) {
68  // track.match.mcparticle_id);
69  const std::vector<simb::MCParticle> &mcparticle_list = *ev.getValidHandle<std::vector<simb::MCParticle>>("largeant");
70  std::cout << "Track: " << mcparticle_id;
71  for (const simb::MCParticle &part: mcparticle_list) {
72  if (mcparticle_id == part.TrackId()) {
73  std::cout << " start T: " << part.Position().T() << " to: " << part.EndPosition().T() << std::endl;
74  }
75  }
76  return;
77 }
78 
79 numu::Wall GetWallCross(const geo::BoxBoundedGeo &volume, const TVector3 p0, const TVector3 p1) {
80  TVector3 direction = (p1 - p0) * ( 1. / (p1 - p0).Mag());
81  std::vector<TVector3> intersections = volume.GetIntersections(p0, direction);
82 
83  /*
84  std::cout << "p0: " << p0.X() << " " << p0.Y() << " " << p0.Z() << std::endl;
85  std::cout << "p1: " << p1.X() << " " << p1.Y() << " " << p1.Z() << std::endl;
86  std::cout << "i0: " << intersections[0].X() << " " << intersections[0].Y() << " " << intersections[0].Z() << std::endl;
87  std::cout << "i1: " << intersections[1].X() << " " << intersections[1].Y() << " " << intersections[1].Z() << std::endl;
88  */
89 
90  assert(intersections.size() == 2);
91 
92  // get the intersection point closer to p0
93  int intersection_i = ((intersections[0] - p0).Mag() < (intersections[1] - p0).Mag()) ? 0 : 1;
94 
95 
96  double eps = 1e-3;
97  if (abs(intersections[intersection_i].X() - volume.MinX()) < eps) {
98  //std::cout << "Left\n";
99  return numu::wLeft;
100  }
101  else if (abs(intersections[intersection_i].X() - volume.MaxX()) < eps) {
102  //std::cout << "Right\n";
103  return numu::wRight;
104  }
105  else if (abs(intersections[intersection_i].Y() - volume.MinY()) < eps) {
106  //std::cout << "Bottom\n";
107  return numu::wBottom;
108  }
109  else if (abs(intersections[intersection_i].Y() - volume.MaxY()) < eps) {
110  //std::cout << "Top\n";
111  return numu::wTop;
112  }
113  else if (abs(intersections[intersection_i].Z() - volume.MinZ()) < eps) {
114  //std::cout << "Front\n";
115  return numu::wFront;
116  }
117  else if (abs(intersections[intersection_i].Z() - volume.MaxZ()) < eps) {
118  //std::cout << "Back\n";
119  return numu::wBack;
120  }
121  else assert(false);
122  //std::cout << "None\n";
123 
124  return numu::wNone;
125 }
126 
127 int NumuReco::GetPhotonMotherID(int mcparticle_id) {
128  bool is_cosmic = _true_particles_to_truth.at(mcparticle_id)->Origin() != simb::Origin_t::kBeamNeutrino;
129  if (is_cosmic) {
130  unsigned truth_index = _true_particles_to_generator_info.at(mcparticle_id)->generatedParticleIndex();
131  return (int) truth_index +1;
132  }
133  else {
134  return mcparticle_id;
135  }
136 }
137 
139  sbn::crt::CRTHit ret;
140  ret.feb_id = inp.feb_id;
141  ret.pesmap = inp.pesmap;
142  // convert ADC -> PE's
143  // TODO: fix -- hardcoded for now as temporary hack
144  unsigned n_strip = 2;
145  double baseline = 63.6; // ADC
146  double gain = 70; // ADC / PE
147  ret.peshit = (inp.peshit - n_strip*baseline) / (gain * n_strip);
148  ret.ts0_s = inp.ts0_s;
149  ret.ts0_s_corr = inp.ts0_s_corr;
150  ret.ts0_ns = inp.ts0_ns;
151  ret.ts0_ns_corr = inp.ts0_ns_corr;
152  ret.ts1_ns = inp.ts1_ns;
153  ret.plane = inp.plane;
154  ret.x_pos = inp.x_pos;
155  ret.x_err = inp.x_err;
156  ret.y_pos = inp.y_pos;
157  ret.y_err = inp.y_err;
158  ret.z_pos = inp.z_pos;
159  ret.z_err = inp.z_err;
160  ret.tagger = inp.tagger;
161  return ret;
162 }
163 
165  SelectionBase(),
166  _event_counter(0),
167  _nu_count(0),
168  _selected(new std::vector<numu::RecoInteraction>) {}
169 
170 void NumuReco::Initialize(fhicl::ParameterSet* config) {
171  if (config) {
172  fhicl::ParameterSet pconfig = config->get<fhicl::ParameterSet>("NumuReco");
173 
174  // configure the Cosmic ID algorithms
175  _crt_track_matchalg = new sbnd::CRTTrackMatchAlg(fhicl::Table<sbnd::CRTTrackMatchAlg::Config>(pconfig.get<fhicl::ParameterSet>("CRTTrackMatchAlg"))(),
177 
178  _crt_hit_matchalg = new sbnd::CRTT0MatchAlg(fhicl::Table<sbnd::CRTT0MatchAlg::Config>(pconfig.get<fhicl::ParameterSet>("CRTT0MatchAlg"))(),
180 
181  _apa_cross_cosmic_alg.reconfigure(*fProviderManager, fhicl::Table<ApaCrossCosmicIdAlg::Config>(pconfig.get<fhicl::ParameterSet>("ApaCrossCosmicIdAlg"))());
182 
183  _stopping_cosmic_alg.reconfigure(*fProviderManager, fhicl::Table<StoppingParticleCosmicIdAlg::Config>(pconfig.get<fhicl::ParameterSet>("StoppingParticleCosmicIdAlg"))());
184 
185 
188 
189  // get the beam center
190  _config.beamCenterX = pconfig.get<float>("beamCenterX", 130.);
191  _config.beamCenterY = pconfig.get<float>("beamCenterY", 0.);
192 
193  _config.verbose = pconfig.get<bool>("verbose", false);
194 
195  _config.requireTrack = pconfig.get<bool>("requireTrack", false);
196 
197  _config.trackMatchContainmentCut = pconfig.get<double>("trackMatchContainmentCut", -1);
198 
199  _config.TSMode = pconfig.get<int>("TSMode", 1);
200  _config.MakeOpHits = pconfig.get<bool>("MakeOpHits", false);
201 
202  _config.requireMatched = pconfig.get<bool>("requireMatched", false);
203  _config.requireContained = pconfig.get<bool>("requireContained", false);
204  _config.CRTHitTimeCorrection = pconfig.get<double>("CRTHitTimeCorrection", 0.);
205 
206  _config.BeamSpillWindow = pconfig.get<std::array<float, 2>>("BeamSpillWindow", {-25., 10.}); // default -- give 0.2us buffer on each side
207 
208  // setup weight config
209  _config.uniformWeights = pconfig.get<std::vector<std::string>>("uniformWeights", {});
210  _config.constantWeight = pconfig.get<double>("constantWeight", 1.0);
211  _config.cosmicWeight = pconfig.get<double>("cosmicWeight", 1.0);
212 
213  // flash match method
214  _config.FlashMatchMethod = pconfig.get<int>("FlashMatchMethod", 2);
215  _config.flashMatchTimeDifference = pconfig.get<double>("flashMatchTimeDifference");
216 
217  _config.PMTTriggerThreshold = pconfig.get<int>("PMTTriggerThreshold");
218 
219  _config.CosmicIDAllTracks = pconfig.get<bool>("CosmicIDAllTracks", false);
220 
221  // whether to use flash matching in makin CRT decision
222  _config.CRT2OPTimeWidth = pconfig.get<double>("CRT2OPTimeWidth", 0.);
223  _config.CRTHitinOpHitRange = pconfig.get<bool>("CRTHitinOpHitRange", false);
224 
225  // get tag names
226  _config.RecoTrackTag = config->get<std::string>("RecoTrackTag", "pandoraTrack");
227  _config.RecoSliceTag = config->get<std::string>("RecoSliceTag", "pandora");
228  _config.RecoVertexTag = config->get<std::string>("RecoVertexTag", "pandora");
229  _config.PFParticleTag = config->get<std::string>("PFParticleTag", "pandora");
230  _config.FlashMatchTag = config->get<std::string>("FlashMatchTag ", "fmatch");
231  _config.CaloTag = config->get<std::string>("CaloTag", "pandoraCalo");
232  _config.PIDTag = config->get<std::string>("PIDTag", "pandoraPid");
233  _config.CorsikaTag = config->get<std::string>("CorsikaTag", "cosmgen");
234  _config.CRTTrackTag = config->get<std::string>("CRTTrackTag", "crttrack");
235  _config.CRTHitTag = config->get<std::string>("CRTHitTag", "crthit");
236  _config.OpFlashTag = config->get<std::string>("OpFlashTag", "ophit");
237  _config.MCParticleTag = config->get<std::string>("MCParticleTag", "largeant");
238  _config.TPCRecoTagSuffixes = config->get<std::vector<std::string>>("TPCRecoTagSuffixes", { "" });
239 
240  {
241  fhicl::ParameterSet dCV = \
242  pconfig.get<fhicl::ParameterSet>("containment_volume_inset");
243  double dx = dCV.get<double>("x");
244  double dy = dCV.get<double>("y");
245  double zfront = dCV.get<double>("zfront");
246  double zback = dCV.get<double>("zback");
247  for (const geo::BoxBoundedGeo &geo: _config.active_volumes) {
248  _config.containment_volumes.emplace_back(geo.MinX() + dx, geo.MaxX() - dx, geo.MinY() + dy, geo.MaxY() - dy, geo.MinZ() + zfront, geo.MaxZ() - zback);
249  }
250  }
251 
252  // initialize things to do with reconstruction
253  double min_track_length = pconfig.get<double>("MinTrackLength", 10.);
255  _mcs_fitter = new trkf::TrajectoryMCSFitter(pconfig.get<fhicl::ParameterSet>("MCSFitter", {}));
256 
257  _op_hit_maker = (_config.MakeOpHits) ? new opdet::opHitFinderSBND(pconfig.get<fhicl::ParameterSet>("OpHitMaker"), fProviderManager->GetDetectorClocksProvider()) :
258  NULL;
259  }
260 
261  // Setup histo's for root output
262  fOutputFile->cd();
263 
264  sbnd::CRTGeoAlg crt_geo(fProviderManager->GetGeometryProvider(), fProviderManager->GetAuxDetGeometryProvider());
265  std::vector<double> tagger_volumes = crt_geo.CRTLimits();
266 
267  // crt histograms
268  _crt_histograms.Initialize("crt_all", tagger_volumes);
269 
270  // add branches
271  fTree->Branch("reco_event", &_recoEvent);
272  fTree->Branch("reco_vertices", &_selected);
273 
274  hello();
275 }
276 
277 
278 void NumuReco::Finalize() {
279  // cleanup pointers to algorithms
280  if (_crt_track_matchalg != NULL) delete _crt_track_matchalg;
281  if (_crt_hit_matchalg != NULL) delete _crt_hit_matchalg;
282  if (_op_hit_maker != NULL) delete _op_hit_maker;
283  if (_track_momentum_calculator != NULL) delete _track_momentum_calculator;
284  if (_mcs_fitter != NULL) delete _mcs_fitter;
285  fOutputFile->cd();
286  // finish histograms
287  _crt_histograms.Write();
288 }
289 
290 event::RecoInteraction NumuReco::CoreRecoInteraction(const std::vector<event::Interaction> &truth, const numu::RecoInteraction &vertex, double weight) {
292  if (vertex.match.mctruth_vertex_id >= 0) {
293  ret.truth_index = vertex.match.mctruth_vertex_id;
294  }
295  ret.reco_energy = vertex.nu_energy;
296  ret.weight = weight;
297  return ret;
298 }
299 
300 bool NumuReco::ProcessEvent(const gallery::Event& ev, const std::vector<event::Interaction> &core_truth, std::vector<event::RecoInteraction>& reco) {
301  if (_event_counter % 10 == 0) {
302  std::cout << "NumuReco: Processing event " << _event_counter << " "
303  << "(" << _nu_count << " neutrinos selected)"
304  << std::endl;
305  }
306  // on the first event, store the type of MC we are processing
307  if (_event_counter == 0) {
308  // Get neutrino truth
309  gallery::Handle<std::vector<simb::MCTruth>> mctruth_handle;
310  bool has_mctruth = ev.getByLabel(fTruthTag, mctruth_handle);
311 
312  // also cosmics
313  gallery::Handle<std::vector<simb::MCTruth>> cosmics;
314  bool has_cosmics = ev.getByLabel(_config.CorsikaTag, cosmics);
315 
316  // cosmic + neutrino -- overlay
317  if (has_mctruth && has_cosmics) {
318  fType = numu::fOverlay;
319  }
320  else if (has_cosmics) {
321  fType = numu::fIntimeCosmic;
322  }
323  else {
324  fType = numu::fUnknown;
325  }
326  TParameter<int> mc_type("MCType", (int)fType);
327  fOutputFile->cd();
328  mc_type.Write();
329  }
330 
331 
332  std::cout << "New Event! " << _event_counter << std::endl;
333  std::cout << "ART Event no: " << ev.eventAuxiliary().event() << std::endl;
334  // clear out old containers
335  _selected->clear();
336 
337  bool selected = false;
338 
339  _event_counter++;
340  CollectTruthInformation(ev);
341 
342  std::map<size_t, numu::TrueParticle> particles = MCParticleInfos();
343 
344  // get the event info
345  _recoEvent = Reconstruct(ev, core_truth);
346 
347  // complete the information
348  _recoEvent.particles = std::move(particles);
349 
350  // set the file type
351  _recoEvent.type = fType;
352 
353  // save the information
354  for (unsigned i = 0; i < _recoEvent.reco.size(); i++) {
355  const numu::RecoInteraction &vertex = _recoEvent.reco[i];
356  // compute the weight for this interaction
357  double weight = 1.;
358  weight *= _config.constantWeight;
359  // TODO: what about cosmics?
360  // if (vertex.match.mctruth_vertex_id >= 0) {
361  // for (auto const &key: _config.uniformWeights) {
362  // weight *= core_truth[vertex.match.mctruth_vertex_id].weightmap.at(key)[0];
363  // }
364  // }
365  if (vertex.match.mode == numu::mCosmic) {
366  weight *= _config.cosmicWeight;
367  }
368 
369  // store reco interaction
370  _selected->push_back(vertex);
371  // store sbncode reco interaction
372  reco.push_back(CoreRecoInteraction(core_truth, vertex, weight));
373  selected = true;
374  _nu_count++;
375  }
376 
377  return true;
378 }
379 
380 // get information associated with true particle
381 numu::TrueParticle NumuReco::MCParticleInfo(const simb::MCParticle &particle) {
382  numu::TrueParticle ret;
383 
384  // default values
385  ret.length = 0.;
386  ret.crosses_tpc = false;
387  ret.wall_enter = numu::wNone;
388  ret.wall_exit = numu::wNone;
389  ret.deposited_energy = 0.;
390 
391  // If the interaction is outside the active volume, then g4 won't generate positions for the particle.
392  // So size == 0 => outside FV
393  //
394  // If size != 0, then we have to check volumes
395  ret.contained_in_cryo = particle.NumberTrajectoryPoints() > 0;
396  ret.contained_in_tpc = particle.NumberTrajectoryPoints() > 0;
397  ret.is_contained = particle.NumberTrajectoryPoints() > 0;
398 
399  // get the point at which the Trajectory enters the cryostat (which may be non-zero for cosmics)
400  int entry_point = -1;
401 
402  int cryostat_index = -1;
403  int tpc_index = -1;
404 
405  for (unsigned j = 0; j < particle.NumberTrajectoryPoints(); j++) {
406  for (unsigned i = 0; i < _config.active_volumes.size(); i++) {
407  if (_config.active_volumes[i].ContainsPosition(particle.Position(j).Vect())) {
408  entry_point = j;
409  cryostat_index = i;
410  break;
411  }
412  }
413  if (entry_point != -1) break;
414  }
415 
416  // find the entering wall
417  if (entry_point > 0) {
418  ret.wall_enter = GetWallCross(_config.active_volumes[cryostat_index], particle.Position(entry_point).Vect(), particle.Position(entry_point-1).Vect());
419  }
420 
421  std::vector<geo::BoxBoundedGeo> volumes;
422  if (entry_point >= 0) {
423  volumes = _config.tpc_volumes[cryostat_index];
424  // setup the initial TPC index
425  for (int i = 0; i < volumes.size(); i++) {
426  if (volumes[i].ContainsPosition(particle.Position(entry_point).Vect())) {
427  tpc_index = i;
428  ret.contained_in_tpc = entry_point == 0;
429  break;
430  }
431  }
432  ret.is_contained = entry_point == 0;
433  ret.contained_in_cryo = entry_point == 0;
434  }
435  // if we couldn't find a volume for the intial point, set not contained
436  else {
437  ret.contained_in_cryo = false;
438  ret.is_contained = false;
439  }
440  if (tpc_index < 0) {
441  ret.contained_in_tpc = false;
442  }
443 
444  // setup aa volumes too for length calc
445  std::vector<geoalgo::AABox> aa_volumes;
446  for (auto const &v: volumes) {
447  aa_volumes.emplace_back(v.MinX(), v.MinY(), v.MinZ(), v.MaxX(), v.MaxY(), v.MaxZ());
448  }
449 
450  int exit_point = -1;
451 
452  // Get the length and determine if any point leaves the active volume
453  //
454  // Use every trajectory point if possible
455  if (entry_point >= 0) {
456  // particle trajectory
457  const simb::MCTrajectory &trajectory = particle.Trajectory();
458  TVector3 pos = trajectory.Position(entry_point).Vect();
459  for (int i = entry_point+1; i < particle.NumberTrajectoryPoints(); i++) {
460  TVector3 this_point = trajectory.Position(i).Vect();
461  // get the exit point
462  // update if particle is contained
463  if (ret.contained_in_cryo) {
464  ret.contained_in_cryo = _config.active_volumes[cryostat_index].ContainsPosition(this_point);
465  }
466  // check if particle has crossed TPC
467  if (!ret.crosses_tpc) {
468  for (int j = 0; j < volumes.size(); j++) {
469  if (volumes[j].ContainsPosition(this_point) && j != tpc_index) {
470  ret.crosses_tpc = true;
471  break;
472  }
473  }
474  }
475  // check if particle has left tpc
476  if (ret.contained_in_tpc) {
477  ret.contained_in_tpc = volumes[tpc_index].ContainsPosition(this_point);
478  }
479 
480  if (ret.is_contained) {
481  ret.is_contained = _config.containment_volumes[cryostat_index].ContainsPosition(this_point);
482  }
483 
484  // update length
485  ret.length += containedLength(this_point, pos, aa_volumes);
486 
487  if (!_config.active_volumes[cryostat_index].ContainsPosition(this_point) && _config.active_volumes[cryostat_index].ContainsPosition(pos)) {
488  exit_point = i-1;
489  }
490 
491  // update energy
492  if (InActive(this_point) && InActive(pos)) {
493  ret.deposited_energy += trajectory.Momentum(i-1).E() - trajectory.Momentum(i).E();
494  }
495  pos = trajectory.Position(i).Vect();
496  }
497  }
498  if (exit_point < 0 && entry_point >= 0) {
499  exit_point = particle.NumberTrajectoryPoints() - 1;
500  }
501  if (exit_point < particle.NumberTrajectoryPoints() - 1) {
502  ret.wall_exit = GetWallCross(_config.active_volumes[cryostat_index], particle.Position(exit_point).Vect(), particle.Position(exit_point+1).Vect());
503  }
504 
505  // get the generation mode
506  ret.is_cosmic = _true_particles_to_truth.at(particle.TrackId())->Origin() != simb::kBeamNeutrino;
507 
508  //double costh = (entry_point >= 0 && particle.Momentum(entry_point).Vect().Mag() > 1e-4) ? particle.Pz(entry_point) / particle.Momentum(entry_point).Vect().Mag(): -999.;
509  //double kinetic_energy = (entry_point >= 0) ? particle.E(entry_point) /* already in GeV*/ - PDGMass(pdgid) / 1000. /* MeV -> GeV */: -999.;
510 
511  // other truth information
512  ret.pdgid = particle.PdgCode();
513 
514  ret.start = (entry_point >= 0) ? particle.Position(entry_point).Vect(): TVector3(-9999, -9999, -9999);
515  ret.start_time = (entry_point >= 0) ? particle.Position(entry_point).T() / 1000. /* ns-> us*/: -9999;
516  ret.end = (exit_point >= 0) ? particle.Position(exit_point).Vect(): TVector3(-9999, -9999, -9999);
517  ret.end_time = (exit_point >= 0) ? particle.Position(exit_point).T() / 1000. /* ns -> us */ : -9999;
518 
519  ret.start_momentum = (entry_point >= 0) ? particle.Momentum(entry_point).Vect() : TVector3(-9999, -9999, -9999);
520  ret.start_energy = (entry_point >= 0) ? particle.Momentum(entry_point).E() : -9999.;
521  ret.end_momentum = (exit_point >= 0) ? particle.Momentum(exit_point).Vect() : TVector3(-9999, -9999, -9999);
522  ret.end_energy = (exit_point >= 0) ? particle.Momentum(exit_point).E() : -9999.;
523 
524  ret.ID = particle.TrackId();
525 
526  return ret;
527 }
528 
529 std::map<size_t, numu::TrueParticle> NumuReco::MCParticleInfos() {
530  std::map<size_t, numu::TrueParticle> ret;
531  for (unsigned i = 0; i < _true_particles.size(); i++) {
532  ret[_true_particles[i]->TrackId()] = MCParticleInfo(*_true_particles[i]);
533  }
534  return ret;
535 }
536 
537 double RecoTrackLength(const art::Ptr<recob::Track> &track) {
538  if (track->CountValidPoints() == 0) return 0.;
539  double dist = 0.;
540  geo::Point_t first = track->Start();
541  for (size_t i = 1; i < track->CountValidPoints(); i++) {
542  geo::Point_t second = track->LocationAtPoint(i);
543  dist += sqrt((second - first).Mag2());
544  first = second;
545  }
546  return dist;
547 }
548 
549 std::array<bool, 4> NumuReco::RecoTrackTopology(const art::Ptr<recob::Track> &track) {
550  // returned info
551  bool contained_in_cryo = true;
552  bool contained_in_tpc = true;
553  bool crosses_tpc = false;
554 
555  bool is_contained = true;
556 
557  // start point
558  geo::Point_t start = track->Start();
559  // get the active volume that the start position is in
560  int cryostat_index = -1;
561  int tpc_index = -1;
562  int containment_index = -1;
563  for (int i = 0; i < _config.containment_volumes.size(); i++) {
564  if (_config.containment_volumes[i].ContainsPosition(start)) {
565  containment_index = i;
566  }
567  break;
568  }
569  for (int i = 0; i < _config.active_volumes.size(); i++) {
570  if (_config.active_volumes[i].ContainsPosition(start)) {
571  cryostat_index = i;
572  break;
573  }
574  }
575  if (containment_index < 0) {
576  is_contained = false;
577  }
578  std::vector<geo::BoxBoundedGeo> volumes;
579  if (cryostat_index >= 0) {
580  volumes = _config.tpc_volumes[cryostat_index];
581  for (int i = 0; i < volumes.size(); i++) {
582  if (volumes[i].ContainsPosition(start)) {
583  tpc_index = i;
584  break;
585  }
586  }
587  }
588  else {
589  contained_in_cryo = false;
590  }
591  if (tpc_index < 0) {
592  contained_in_tpc = false;
593  }
594 
595  // now check for all track points
596  for (int i = 1; i < track->CountValidPoints(); i++) {
597  geo::Point_t this_point = track->LocationAtPoint(i);
598  if (is_contained) {
599  is_contained = _config.containment_volumes[containment_index].ContainsPosition(this_point);
600  }
601  if (contained_in_cryo) {
602  contained_in_cryo = _config.active_volumes[cryostat_index].ContainsPosition(this_point);
603  }
604  if (contained_in_cryo && !crosses_tpc) {
605  for (int j = 0; j < volumes.size(); j++) {
606  if (volumes[j].ContainsPosition(this_point) && j != tpc_index) {
607  crosses_tpc = true;
608  break;
609  }
610  }
611  }
612  if (contained_in_tpc) {
613  contained_in_tpc = volumes[tpc_index].ContainsPosition(this_point);
614  }
615  }
616 
617  return {contained_in_cryo, contained_in_tpc, crosses_tpc, is_contained};
618 }
619 
620 
621 std::map<size_t, numu::RecoTrack> NumuReco::RecoTrackInfo() {
622  std::map<size_t, numu::RecoTrack> ret;
623  for (unsigned pfp_track_index = 0; pfp_track_index < _tpc_tracks.size(); pfp_track_index++) {
624  const art::Ptr<recob::Track> &track = _tpc_tracks[pfp_track_index];
625 
626  // information to be saved
627  numu::RecoTrack this_track;
628 
629  // Use the particle ID as a global ID
630  this_track.ID = _tpc_tracks_to_particle_index.at(pfp_track_index);
631 
632  // track length
633  this_track.length = track->Length();
634 
635  // get the associated PID and Calo
636  assert(_tpc_tracks_to_pid.at(pfp_track_index).size() == 3); //one per plane
637 
638  // sum up all the pid scores weighted by n dof
639  double chi2_proton = 0.;
640  double chi2_kaon = 0.;
641  double chi2_muon = 0.;
642  double chi2_pion = 0.;
643  int n_dof = 0;
644  int particle_pdg = 0;
645  double min_chi2 = 0.;
646  for (int i =0; i < 3; i++) {
647  // invalid plane means invalid calorimetry
648  if (!_tpc_tracks_to_pid.at(pfp_track_index).at(i)->PlaneID()) continue;
649  const art::Ptr<anab::ParticleID> &particle_id = _tpc_tracks_to_pid.at(pfp_track_index).at(i);
650  // only use particle ID on collection plane
651  if (fProviderManager->GetGeometryProvider()->SignalType(particle_id->PlaneID()) == geo::kCollection) {
652  n_dof += particle_id->Ndf();
653  chi2_proton += particle_id->Chi2Proton() * particle_id->Ndf();
654  chi2_kaon += particle_id->Chi2Kaon() * particle_id->Ndf();
655  chi2_pion += particle_id->Chi2Pion() * particle_id->Ndf();
656  chi2_muon += particle_id->Chi2Muon() * particle_id->Ndf();
657  }
658  }
659  if (n_dof > 0) {
660  /*
661  chi2_proton /= n_dof;
662  chi2_kaon /= n_dof;
663  chi2_pion /= n_dof;
664  chi2_muon /= n_dof;*/
665  // min chi2 is PID
666  std::vector<double> chi2s {chi2_proton, chi2_muon, chi2_kaon, chi2_pion};
667  int min_ind = std::distance(chi2s.begin(), std::min_element(chi2s.begin(), chi2s.end()));
668  min_chi2 = *std::min_element(chi2s.begin(), chi2s.end());
669  if (min_ind == 0) {
670  particle_pdg = 2212;
671  }
672  else if (min_ind == 1) {
673  particle_pdg = 13;
674  }
675  else if (min_ind == 2) {
676  particle_pdg = 312;
677  }
678  else if (min_ind == 3) {
679  particle_pdg = 211;
680  }
681  else {
682  assert(false);
683  }
684  }
685  else {
686  // No particle ID was provided -- set things to nonsense
687  chi2_proton = -1;
688  chi2_kaon = -1;
689  chi2_muon = -1;
690  chi2_pion = -1;
691  min_chi2 = -1.5;
692  }
693  this_track.pdgid = particle_pdg;
694  this_track.chi2_proton = chi2_proton;
695  this_track.chi2_kaon = chi2_kaon;
696  this_track.chi2_pion = chi2_pion;
697  this_track.chi2_muon = chi2_muon;
698  this_track.min_chi2 = min_chi2;
699  this_track.pid_n_dof = n_dof;
700 
701  // TODO: add in calo stuff??
702  assert(_tpc_tracks_to_calo.at(pfp_track_index).size() == 3);
703 
704  // calculator only has inputs for protons and muons
705  this_track.range_momentum_proton = _track_momentum_calculator->GetTrackMomentum(this_track.length, 2212);
706  this_track.range_momentum_muon = _track_momentum_calculator->GetTrackMomentum(this_track.length, 13);
707 
708  recob::MCSFitResult mcs_fit_muon = _mcs_fitter->fitMcs(*track, 13);
709  this_track.mcs_muon.fwd_mcs_momentum = mcs_fit_muon.fwdMomentum();
710  this_track.mcs_muon.fwd_mcs_momentum_err = mcs_fit_muon.fwdMomUncertainty();
711  this_track.mcs_muon.bwd_mcs_momentum = mcs_fit_muon.bwdMomentum();
712  this_track.mcs_muon.bwd_mcs_momentum_err = mcs_fit_muon.bwdMomUncertainty();
713 
714  recob::MCSFitResult mcs_fit_pion = _mcs_fitter->fitMcs(*track, 211);
715  this_track.mcs_pion.fwd_mcs_momentum = mcs_fit_pion.fwdMomentum();
716  this_track.mcs_pion.fwd_mcs_momentum_err = mcs_fit_pion.fwdMomUncertainty();
717  this_track.mcs_pion.bwd_mcs_momentum = mcs_fit_pion.bwdMomentum();
718  this_track.mcs_pion.bwd_mcs_momentum_err = mcs_fit_pion.bwdMomUncertainty();
719 
720  recob::MCSFitResult mcs_fit_proton = _mcs_fitter->fitMcs(*track, 2212);
721  this_track.mcs_proton.fwd_mcs_momentum = mcs_fit_proton.fwdMomentum();
722  this_track.mcs_proton.fwd_mcs_momentum_err = mcs_fit_proton.fwdMomUncertainty();
723  this_track.mcs_proton.bwd_mcs_momentum = mcs_fit_proton.bwdMomentum();
724  this_track.mcs_proton.bwd_mcs_momentum_err = mcs_fit_proton.bwdMomUncertainty();
725 
726  recob::MCSFitResult mcs_fit_kaon = _mcs_fitter->fitMcs(*track, 321);
727  this_track.mcs_kaon.fwd_mcs_momentum = mcs_fit_kaon.fwdMomentum();
728  this_track.mcs_kaon.fwd_mcs_momentum_err = mcs_fit_kaon.fwdMomUncertainty();
729  this_track.mcs_kaon.bwd_mcs_momentum = mcs_fit_kaon.bwdMomentum();
730  this_track.mcs_kaon.bwd_mcs_momentum_err = mcs_fit_kaon.bwdMomUncertainty();
731 
732  this_track.costh = track->StartDirection().Z() / sqrt( track->StartDirection().Mag2() );
733 
734  // get track topology
735  std::array<bool, 4> topology = RecoTrackTopology(track);
736  this_track.crosses_tpc = topology[2];
737 
738  this_track.start = TVector3(track->Start().X(), track->Start().Y(), track->Start().Z());
739  this_track.end = TVector3(track->End().X(), track->End().Y(), track->End().Z());
740 
741  // do truth matching
742  this_track.match = MatchTrack2Truth(pfp_track_index);
743 
744  // if configured, apply Cosmic ID to all tracks
745  if (_config.CosmicIDAllTracks) {
746  ApplyCosmicID(this_track);
747  }
748 
749  ret[this_track.ID] = this_track;
750  }
751  return ret;
752 }
753 
754 void NumuReco::ApplyCosmicID(numu::RecoTrack &track) {
755  unsigned track_id = _tpc_particles_to_track_index.at(track.ID);
756  const art::Ptr<recob::Track> &pfp_track = _tpc_tracks[track_id];
757 
758  // do CRT matching
759  track.crt_match = CRTMatching(track, *pfp_track, _tpc_tracks_to_hits.at(track_id));
760 
761  // Cosmic ID:
762  //
763  // See if start or end looks like stopping
764  track.stopping_chisq_start = _stopping_cosmic_alg.StoppingChiSq(pfp_track->Vertex(), _tpc_tracks_to_calo.at(track_id));
765  track.stopping_chisq_finish = _stopping_cosmic_alg.StoppingChiSq(pfp_track->End(), _tpc_tracks_to_calo.at(track_id));
766 }
767 
768 
769 std::vector<size_t> NumuReco::RecoSliceTracks(
770  const std::map<size_t, numu::RecoTrack> &tracks,
771  const std::map<size_t, numu::RecoParticle> &particles) {
772 
773  std::vector<size_t> ret;
774 
775  for (const auto &particle_pair: particles) {
776  if (tracks.count(particle_pair.first)) {
777  ret.push_back(particle_pair.first);
778  }
779  }
780 
781  return ret;
782 }
783 
784 std::vector<numu::RecoParticle> NumuReco::RecoParticleInfo() {
785  // ret
786  std::vector<numu::RecoParticle> ret;
787 
788  // iterate over all of the pfparticles
789  for (size_t i = 0; i < _tpc_particles.size(); i++) {
790  // new reco particle
791  numu::RecoParticle this_particle;
792  this_particle.ID = i;
793 
794  // get the PFParticle
795  const recob::PFParticle& this_pfp = *_tpc_particles.at(i);
796 
797  // assign pandora PDG
798  this_particle.pandora_pid = this_pfp.PdgCode();
799 
800  // get its daughters in the partcle "flow"
801  this_particle.daughters.assign(_tpc_particles_to_daughters[i].begin(), _tpc_particles_to_daughters[i].end());
802  // get the metadata
803  const larpandoraobj::PFParticleMetadata& this_metadata = *_tpc_particles_to_metadata.at(i);
804  // and the properties dict
805  auto const &properties = this_metadata.GetPropertiesMap();
806  // get the reco vertices
807  for (const art::Ptr<recob::Vertex> vert: _tpc_particles_to_vertex.at(i)) {
808  TVector3 vect(vert->position().X(), vert->position().Y(), vert->position().Z());
809  this_particle.vertices.push_back(vect);
810  }
811 
812  // access pandora special values
813  if (properties.count("IsClearCosmic")) {
814  this_particle.p_is_clear_cosmic = properties.at("IsClearCosmic");
815  }
816  else {
817  this_particle.p_is_clear_cosmic = false;
818  }
819  if (properties.count("NuScore")) {
820  this_particle.p_nu_score = properties.at("NuScore");
821  }
822  else {
823  this_particle.p_nu_score = -1;
824  }
825  if (properties.count("IsNeutrino")) {
826  this_particle.p_is_neutrino = properties.at("IsNeutrino");
827  }
828  else {
829  this_particle.p_is_neutrino = false;
830  }
831 
832  ret.push_back(std::move(this_particle));
833  }
834 
835  return ret;
836 }
837 
838 
839 bool NumuReco::HasPrimaryTrack(const std::map<size_t, numu::RecoTrack> &tracks, const numu::RecoSlice &slice) {
840  if (slice.primary_index < 0) return false;
841 
842  std::cout << "Checking slice particle: " << slice.primary_index << std::endl;
843  for (const auto &part_pair: slice.particles) {
844  std::cout << "ID: " << part_pair.first << "\n";
845  }
846  const numu::RecoParticle &neutrino = slice.particles.at(slice.primary_index);
847  for (size_t pfp_index: neutrino.daughters) {
848  std::cout << "Neutrino daughter ID: " << pfp_index << std::endl;
849  const numu::RecoParticle &daughter = slice.particles.at(pfp_index);
850  if (tracks.count(daughter.ID)) {
851  if (tracks.at(daughter.ID).length > 1e-4) {
852  return true;
853  }
854  }
855  }
856 
857  return false;
858 }
859 
861  return slice.primary_index >= 0 &&
862  slice.particles.at(slice.primary_index).p_is_neutrino &&
863  abs(slice.particles.at(slice.primary_index).pandora_pid) == 14;
864 }
865 
867  // get the service
868  const cheat::ParticleInventory *inventory_service = fProviderManager->GetParticleInventoryProvider();
869 
870  // get its hits
871  std::vector<art::Ptr<recob::Hit>> hits = _tpc_tracks_to_hits.at(pfp_track_id);
872 
873  // this id is the same as the mcparticle ID as long as we got it from geant4
874  // int id = SBNRecoUtils::TrueParticleIDFromTotalRecoHits(*fProviderManager, hits, false);
875  int mcp_track_id = SBNRecoUtils::TrueParticleIDFromTotalTrueEnergy(*fProviderManager, hits, true);
876 
877 
878  int mcparticle_index = -1;
879  for (int i = 0; i < _true_particles.size(); i++) {
880  if (_true_particles[i]->TrackId() == mcp_track_id) {
881  mcparticle_index = i;
882  break;
883  }
884  }
885 
886  // number returned to mean "NULL"
887  // no match
888  if (mcparticle_index == -1) return numu::TrackTruthMatch();
889 
890  // We got a match! Try to identify it to an origin
891  art::Ptr<simb::MCTruth> truth = inventory_service->TrackIdToMCTruth_P(mcp_track_id);
892  // and calculate the completion
893  double completion = SBNRecoUtils::TrackCompletion(*fProviderManager, mcp_track_id, hits);
894 
896  // ret.mctruth = truth.get();
897  ret.has_match = true;
898  ret.mctruth_has_neutrino = truth->NeutrinoSet();
899  ret.mctruth_vertex = ret.mctruth_has_neutrino ? truth->GetNeutrino().Nu().Position().Vect() : TVector3(-999, -999, -999);
900  ret.mctruth_origin = truth->Origin();
901 
902  // TODO: fix -- in time cosmics will not have the origin set correctly. Fix and set this to 2.
903  if (ret.mctruth_origin == simb::kUnknown) {
905  }
906 
907  ret.mctruth_ccnc = ret.mctruth_has_neutrino ? truth->GetNeutrino().CCNC() : -1;
908  ret.mcparticle_id = mcp_track_id;
909  ret.completion = completion;
910  ret.match_pdg = _true_particles[mcparticle_index]->PdgCode();
911  ret.is_primary = _true_particles[mcparticle_index]->Process() == "primary";
912  return ret;
913 }
914 
915 std::vector<numu::RecoSlice> NumuReco::RecoSliceInfo(
916  std::map<size_t, numu::RecoTrack> &reco_tracks,
917  const std::vector<numu::RecoParticle> &particles) {
918 
919  std::vector<numu::RecoSlice> ret;
920  // store all the particles in the slice
921  for (size_t i = 0; i < _tpc_slices.size(); i++) {
922  const recob::Slice &slice = *_tpc_slices[i];
923  numu::RecoSlice slice_ret;
924  slice_ret.primary_index = -1;
925  bool primary_particle_set = false;
926  // get the particles
927  const std::vector<art::Ptr<recob::PFParticle>> &pfp_particles = _tpc_slices_to_particles.at(i);
928  // find the primary one and store all of them
929  // Find the priamry particle
930  for (unsigned j = 0; j < pfp_particles.size(); j++) {
931  const art::Ptr<recob::PFParticle> pfp_part = pfp_particles[j];
932  if (pfp_part->IsPrimary()) {
933  assert(!primary_particle_set);
934  primary_particle_set = true;
935  slice_ret.primary_index = _tpc_slices_to_particle_index[i][j];
936  }
937  }
938  // match the RecoParticle's to the once that match this slice
939  for (const numu::RecoParticle &part: particles) {
940  if (std::find(_tpc_slices_to_particle_index[i].begin(), _tpc_slices_to_particle_index[i].end(), (unsigned)part.ID) != _tpc_slices_to_particle_index[i].end()) {
941  slice_ret.particles[part.ID] = part;
942  }
943  }
944  // throw away bad slices
945  if (!SelectSlice(slice_ret)) continue;
946 
947  // now get information from particles which are tracks
948  slice_ret.tracks = RecoSliceTracks(reco_tracks, slice_ret.particles);
949 
950  std::cout << "Primary index: " << slice_ret.primary_index << std::endl;
951  std::cout << "Is primary: " << _tpc_particles[slice_ret.primary_index]->IsPrimary() << std::endl;
952  if (_tpc_particles_to_flashT0.size() && _tpc_particles_to_flashT0.at(slice_ret.primary_index).size()) {
953  const anab::T0 &fmatch = *_tpc_particles_to_flashT0.at(slice_ret.primary_index).at(0);
954  slice_ret.flash_match.present = true;
955  slice_ret.flash_match.time = fmatch.Time();
956  slice_ret.flash_match.score = fmatch.TriggerConfidence();
957  slice_ret.flash_match.pe = fmatch.TriggerType();
958  std::cout << "Match time: " << slice_ret.flash_match.time << std::endl;
959  std::cout << "Match score: " << slice_ret.flash_match.score << std::endl;
960  std::cout << "Match PE: " << slice_ret.flash_match.pe << std::endl;
961  }
962  else {
963  slice_ret.flash_match.present = false;
964  std::cout << "No match :(\n";
965  }
966 
967  // throw away slices which do not have a primary track candidate
968  if (!HasPrimaryTrack(reco_tracks, slice_ret)) continue;
969 
970  // First guess of primary track
971  slice_ret.primary_track_index = numu::SelectLongestTrack(reco_tracks, slice_ret);
972  assert(slice_ret.primary_track_index >= 0);
973 
974  // if we didn't do the cosmic ID for all tracks, do it for all priamry track candidates
975  if (!_config.CosmicIDAllTracks) {
976  const numu::RecoParticle &neutrino = slice_ret.particles.at(slice_ret.primary_index);
977  for (size_t ind: neutrino.daughters) {
978  const numu::RecoParticle &daughter = slice_ret.particles.at(ind);
979  if (reco_tracks.count(daughter.ID)) {
980  ApplyCosmicID(reco_tracks.at(daughter.ID));
981  }
982  }
983  }
984 
985  ret.push_back(std::move(slice_ret));
986  }
987 
988  return ret;
989 }
990 
991 void NumuReco::CollectTruthInformation(const gallery::Event &ev) {
992  _true_particles.clear();
993  _true_particles_to_truth.clear();
994  _true_particles_to_generator_info.clear();
995 
996  // mc particles
997  auto const &mcparticles = ev.getValidHandle<std::vector<simb::MCParticle>>(fMCParticleTag);
998  art::fill_ptr_vector(_true_particles, mcparticles);
999 
1000  // MC particle (G4) to MCTruth (generator -- corsika or genie)
1001  art::FindManyP<simb::MCTruth, sim::GeneratedParticleInfo> particles_to_truth(mcparticles, ev, "largeant");
1002  for (unsigned i = 0; i < mcparticles->size(); i++) {
1003  _true_particles_to_truth[mcparticles->at(i).TrackId()] = particles_to_truth.at(i).at(0);
1004  _true_particles_to_generator_info[mcparticles->at(i).TrackId()] = particles_to_truth.data(i).at(0);
1005  }
1006 }
1007 
1008 void NumuReco::CollectTPCInformation(const gallery::Event &ev) {
1009  // clear out old stuff
1010  _tpc_slices.clear();
1011  _tpc_tracks.clear();
1012  _tpc_particles.clear();
1013  _tpc_slices_to_particles.clear();
1014  _tpc_slices_to_particle_index.clear();
1015  _tpc_tracks_to_particles.clear();
1016  _tpc_tracks_to_particle_index.clear();
1017  _tpc_particles_to_track_index.clear();
1018  _tpc_tracks_to_calo.clear();
1019  _tpc_tracks_to_pid.clear();
1020  _tpc_tracks_to_hits.clear();
1021  _tpc_particles_to_T0.clear();
1022  _tpc_particles_to_vertex.clear();
1023  _tpc_particles_to_daughters.clear();
1024  _tpc_particles_to_metadata.clear();
1025  _tpc_particles_to_flashT0.clear();
1026 
1027  for (const std::string &suffix: _config.TPCRecoTagSuffixes) {
1028  // Offset to convert a pandora particle ID to a NumuReco particle ID
1029  //
1030  // The different ID's are required because in ICARUS TPC reconstruction
1031  // is done per-cryostat. Thus, the pandora particle ID's may not be unique
1032  unsigned particle_id_offset = _tpc_particles.size();
1033 
1034  // get the slices
1035  const auto &slice_handle = ev.getValidHandle<std::vector<recob::Slice>>(_config.RecoSliceTag + suffix);
1036  art::fill_ptr_vector(_tpc_slices, slice_handle);
1037 
1038  // get the particles
1039  const auto &particle_handle = ev.getValidHandle<std::vector<recob::PFParticle>>(_config.PFParticleTag + suffix);
1040  art::fill_ptr_vector(_tpc_particles, particle_handle);
1041 
1042  // get the tracks
1043  const auto &track_handle = ev.getValidHandle<std::vector<recob::Track>>(_config.RecoTrackTag + suffix);
1044  art::fill_ptr_vector(_tpc_tracks, track_handle);
1045 
1046  // slice to particle
1047  art::FindManyP<recob::PFParticle> slice_to_particle(slice_handle, ev, _config.PFParticleTag + suffix);
1048  unsigned i0 = _tpc_slices_to_particle_index.size();
1049  for (unsigned i = 0; i < slice_handle->size(); i++) {
1050  unsigned iset = i + i0;
1051  _tpc_slices_to_particles.push_back(slice_to_particle.at(i));
1052  _tpc_slices_to_particle_index.emplace_back();
1053  for (unsigned j = 0; j < slice_to_particle.at(i).size(); j++) {
1054  _tpc_slices_to_particle_index[iset].push_back(slice_to_particle.at(i)[j]->Self() + particle_id_offset);
1055  assert(_tpc_particles[_tpc_slices_to_particle_index[iset][j]] == _tpc_slices_to_particles[iset][j]);
1056  }
1057  }
1058 
1059  // track to particle and particle to track
1060  art::FindManyP<recob::PFParticle> track_to_particle(track_handle, ev, _config.RecoTrackTag + suffix);
1061  i0 = _tpc_tracks_to_particles.size();
1062  for (unsigned i = 0; i < track_handle->size(); i++) {
1063  unsigned iset = i + i0;
1064  _tpc_tracks_to_particles.push_back(track_to_particle.at(i).at(0));
1065  _tpc_tracks_to_particle_index.push_back(particle_id_offset + _tpc_tracks_to_particles[iset]->Self());
1066  _tpc_particles_to_track_index[particle_id_offset + _tpc_tracks_to_particles[iset]->Self()] = iset;
1067  // if this isn't true something went wrong
1068  assert(_tpc_particles[_tpc_tracks_to_particle_index[iset]] == _tpc_tracks_to_particles[iset]);
1069  }
1070 
1071  // track to Calo
1072  art::FindManyP<anab::Calorimetry> track_to_calo(track_handle, ev, _config.CaloTag + suffix);
1073  for (unsigned i = 0; i < track_handle->size(); i++) {
1074  _tpc_tracks_to_calo.push_back(track_to_calo.at(i));
1075  }
1076 
1077  // track to PID
1078  art::FindManyP<anab::ParticleID> track_to_pid(track_handle, ev, _config.PIDTag + suffix);
1079  for (unsigned i = 0; i < track_handle->size(); i++) {
1080  _tpc_tracks_to_pid.push_back(track_to_pid.at(i));
1081  }
1082 
1083  // track to hits
1084  art::FindManyP<recob::Hit> track_to_hits(track_handle, ev, _config.RecoTrackTag + suffix);
1085  for (unsigned i = 0; i < track_handle->size(); i++) {
1086  _tpc_tracks_to_hits.push_back(track_to_hits.at(i));
1087  }
1088 
1089  // particle to T0
1090  art::FindManyP<anab::T0> particle_to_T0(particle_handle, ev, _config.PFParticleTag + suffix);
1091  for (unsigned i = 0; i < particle_handle->size(); i++) {
1092  _tpc_particles_to_T0.push_back(particle_to_T0.at(i));
1093  }
1094 
1095  gallery::Handle<art::Assns<recob::PFParticle,anab::T0,void>> assns_check;
1096  ev.getByLabel(_config.FlashMatchTag + suffix, assns_check);
1097  if (assns_check.isValid()) {
1098  // particle to flash match
1099  art::FindManyP<anab::T0> particle_to_flash(particle_handle, ev, _config.FlashMatchTag + suffix);
1100  for (unsigned i = 0; i < particle_handle->size(); i++) {
1101  assert(particle_to_flash.at(i).size() == 0 || particle_to_flash.at(i).size() == 1);
1102  _tpc_particles_to_flashT0.push_back(particle_to_flash.at(i));
1103  }
1104  }
1105 
1106  // particle to vertex
1107  art::FindManyP<recob::Vertex> particle_to_vertex(particle_handle, ev, _config.PFParticleTag + suffix);
1108  for (unsigned i = 0; i < particle_handle->size(); i++) {
1109  assert(particle_to_vertex.at(i).size() == 0 || particle_to_vertex.at(i).size() == 1);
1110  _tpc_particles_to_vertex.push_back(particle_to_vertex.at(i));
1111  }
1112 
1113  // particle to daughters
1114  for (unsigned i = 0; i < particle_handle->size(); i++) {
1115  std::vector<unsigned> daughters;
1116  for (unsigned d: _tpc_particles[i+particle_id_offset]->Daughters()) {
1117  daughters.push_back(particle_id_offset + d);
1118  }
1119  _tpc_particles_to_daughters.push_back(std::move(daughters));
1120  }
1121 
1122  // particle to metadata
1123  art::FindManyP<larpandoraobj::PFParticleMetadata> pfp_metadatas(particle_handle, ev, _config.PFParticleTag + suffix);
1124  for (unsigned i = 0; i < particle_handle->size(); i++) {
1125  _tpc_particles_to_metadata.push_back(pfp_metadatas.at(i).at(0));
1126  }
1127  }
1128 }
1129 
1130 
1131 void NumuReco::CollectCRTInformation(const gallery::Event &ev) {
1132  _crt_tracks_local.clear();
1133  _crt_hits_local.clear();
1134 
1135  // collect the CRT Tracks
1136  gallery::Handle<std::vector<sbn::crt::CRTTrack>> crt_tracks_sbnd;
1137  bool has_crt_tracks_sbnd = ev.getByLabel(_config.CRTTrackTag, crt_tracks_sbnd);
1138  gallery::Handle<std::vector<sbn::crt::CRTTrack>> crt_tracks_icarus;
1139  // bool has_crt_tracks_icarus = ev.getByLabel(_config.CRTTrackTag, crt_tracks_icarus);
1140  bool has_crt_tracks_icarus = false;
1141  _has_crt_tracks = has_crt_tracks_sbnd || has_crt_tracks_icarus;
1142 
1143  if (has_crt_tracks_icarus) {
1144  for (unsigned i = 0; i < crt_tracks_icarus->size(); i++) {
1145  _crt_tracks_local.emplace_back();
1146  memcpy(&_crt_tracks_local[i], &crt_tracks_icarus->at(i), sizeof(sbn::crt::CRTTrack));
1147  }
1148  }
1149  _crt_tracks = (_has_crt_tracks) ?
1150  ( (has_crt_tracks_sbnd) ? crt_tracks_sbnd.product() : &_crt_tracks_local) :
1151  NULL;
1152 
1153  // collect the CRT Hits
1154  gallery::Handle<std::vector<sbn::crt::CRTHit>> crt_hits_sbnd;
1155  bool has_crt_hits_sbnd = ev.getByLabel(_config.CRTHitTag, crt_hits_sbnd);
1156  gallery::Handle<std::vector<sbn::crt::CRTHit>> crt_hits_icarus;
1157  bool has_crt_hits_icarus = ev.getByLabel(_config.CRTHitTag, crt_hits_icarus);
1158  _has_crt_hits = has_crt_hits_sbnd || has_crt_hits_icarus;
1159 
1160  // Convert ICARUS Hits to SBND Hits
1161  if (has_crt_hits_icarus) {
1162  for (unsigned i = 0; i < crt_hits_icarus->size(); i++) {
1163  _crt_hits_local.push_back(ICARUS2SBNDCrtHit(crt_hits_icarus->at(i)));
1164  }
1165  }
1166 
1167  _crt_hits = (_has_crt_hits) ?
1168  ( (has_crt_hits_sbnd) ? crt_hits_sbnd.product() : &_crt_hits_local) :
1169  NULL;
1170 }
1171 
1172 numu::CRTMatch NumuReco::CRTMatching(
1173  const numu::RecoTrack &track,
1174  const recob::Track &pandora_track,
1175  const std::vector<art::Ptr<recob::Hit>> &hits) {
1176 
1177  numu::CRTMatch match;
1178 
1179  std::pair<sbn::crt::CRTTrack, double> closest_crt_track = { {}, -99999 };
1180  // try to find a match to CRT Track -- if we have one
1181  if (_has_crt_tracks) {
1182  closest_crt_track = _crt_track_matchalg->ClosestCRTTrackByAngle(pandora_track, hits, *_crt_tracks);
1183  }
1184 
1185  // if there is a track match, fill out the info
1186  if (closest_crt_track.second > -10000 /* Null value */) {
1187  match.track.present = true;
1188  if (_config.TSMode == 0) match.track.time = closest_crt_track.first.ts0_ns / 1000. /* ns -> us */;
1189  else match.track.time = closest_crt_track.first.ts1_ns / 1000. /* ns -> us */;
1190  match.track.angle = closest_crt_track.second;
1191  }
1192  else {
1193  match.track.present = false;
1194  match.track.time = -99999.;
1195  match.track.angle = -99999.;
1196  }
1197 
1198  // try to match a hit
1199  std::pair<sbn::crt::CRTHit, double> hit_pair = std::pair<sbn::crt::CRTHit, double>({sbn::crt::CRTHit(), -1});
1200  if (_has_crt_hits) {
1201  numu::FlashMatch flash_match; // TODO: fix
1202  if (_config.CRTHitinOpHitRange && flash_match.present) {
1203  const numu::FlashMatch &match = flash_match;
1204  double time_width = (_config.CRT2OPTimeWidth) / 2;
1205  std::pair<double, double> time_range;
1206  time_range.first = match.time - time_width;
1207  time_range.second = match.time + time_width;
1208  int drift_dir = sbnd::TPCGeoUtil::DriftDirectionFromHits(fProviderManager->GetGeometryProvider(), hits);
1209  hit_pair = _crt_hit_matchalg->ClosestCRTHit(pandora_track, time_range, *_crt_hits, drift_dir);
1210  }
1211  else {
1212  std::cout << "Tryin CRT Hit match\n";
1213  hit_pair = _crt_hit_matchalg->ClosestCRTHit(pandora_track, hits, *_crt_hits);
1214  }
1215  }
1216 
1217  double distance = hit_pair.second;
1218  if (distance >= 0 /* matching succeeded*/) {
1219  match.hit_match.present = true;
1220  match.hit_match.distance = distance;
1221  match.hit = SBND2numuCRTHit(hit_pair.first);
1222  match.hit_match.time = match.hit.time;
1223  std::cout << "Match: " << match.hit.location.X() << std::endl;
1224  }
1225  else {
1226  match.hit_match.present = false;
1227  match.hit_match.distance = -99999.;
1228  }
1229 
1230  return match;
1231 }
1232 
1233 void NumuReco::CollectPMTInformation(const gallery::Event &ev) {
1234  // std::vector<art::Ptr<recob::OpHit>> op_hit_ptrs;
1235  // std::vector<recob::OpHit> op_hits;
1236 
1237  _op_hit_ptrs.clear();
1238  _op_hits_local.clear();
1239 
1240  return;
1241 
1242  // get the OpDet hits
1243  art::ProductID local_opdets("local_opdets");
1244  if (_config.MakeOpHits) {
1245  const std::vector<raw::OpDetWaveform> &op_waveforms = *ev.getValidHandle<std::vector<raw::OpDetWaveform>>("opdaq");
1246  _op_hits_local = _op_hit_maker->MakeHits(op_waveforms);
1247  for (unsigned i = 0; i < _op_hits_local.size(); i++) {
1248  _op_hit_ptrs.emplace_back(local_opdets, &_op_hits_local[i], i);
1249  }
1250  }
1251  else {
1252  gallery::Handle<std::vector<recob::OpHit>> op_hits;
1253  ev.getByLabel(_config.OpFlashTag, op_hits);
1254  art::fill_ptr_vector(_op_hit_ptrs, op_hits);
1255  }
1256 
1257 }
1258 
1259 
1260 numu::FlashMatch NumuReco::FlashMatching(
1261  const recob::Track &pandora_track,
1262  const numu::RecoTrack &track) {
1263 
1264  numu::FlashMatch ret;
1265  ret.present = false;
1266 
1267  // don't run if back tracker is not setup
1268  if (fProviderManager->GetPhotonBackTrackerProvider() == NULL) {
1269  return ret;
1270  }
1271 
1272  // see if we can do the match
1273  if (track.match.has_match) {
1274  // DumpTrueStart(ev, track.match.mcparticle_id);
1275  // get the correct index
1276  int photon_mother_id = GetPhotonMotherID(track.match.mcparticle_id);
1277  const std::vector<art::Ptr<recob::OpHit>> hit_matches = fProviderManager->GetPhotonBackTrackerProvider()->TrackIdToOpHits_Ps(photon_mother_id, _op_hit_ptrs);
1278  if (hit_matches.size() > 0) {
1279  // average the times weighted by PE
1280  double average = 0.;
1281  double match_pe = 0.;
1282  double min_time = 99999999.;
1283  for (const art::Ptr<recob::OpHit> op_hit: hit_matches) {
1284  average += op_hit->PE() * op_hit->PeakTime();
1285  match_pe += op_hit->PE();
1286  if (op_hit->PeakTime() < min_time) {
1287  min_time = op_hit->PeakTime();
1288  }
1289  }
1290  if (match_pe > 0) {
1291  double match_time = average / match_pe;
1292  numu::FlashMatch match;
1293  match.time = min_time;
1294  return match;
1295  }
1296  }
1297  }
1298  return ret;
1299 }
1300 
1301 bool NumuReco::InBeamSpill(float time) {
1302  return time > _config.BeamSpillWindow[0] && time < _config.BeamSpillWindow[1];
1303 }
1304 
1305 numu::CRTHit NumuReco::SBND2numuCRTHit(const sbn::crt::CRTHit &hit) {
1306  numu::CRTHit ret;
1307  if (_config.TSMode == 0) ret.time = (int)hit.ts0_ns / 1000. /* ns -> us */;
1308  else ret.time = (int)hit.ts1_ns / 1000. /* ns -> us */;
1309  ret.time += _config.CRTHitTimeCorrection;
1310  ret.pes = hit.peshit;
1311  ret.location = TVector3(hit.x_pos, hit.y_pos, hit.z_pos);
1312  ret.uncertainty = TVector3(hit.x_err, hit.y_err, hit.z_err);
1313  return ret;
1314 }
1315 
1316 void NumuReco::FillCRTHits() {
1317  for (const sbn::crt::CRTHit &hit: *_crt_hits) {
1318  _crt_histograms.Fill(hit);
1319  }
1320 }
1321 
1322 std::vector<numu::CRTHit> NumuReco::InTimeCRTHits() {
1323  std::vector<numu::CRTHit> ret;
1324 
1325  for (const sbn::crt::CRTHit &hit: *_crt_hits) {
1326  numu::CRTHit this_hit = NumuReco::SBND2numuCRTHit(hit);
1327  if (InBeamSpill(this_hit.time)) {
1328  ret.push_back(this_hit);
1329  }
1330  }
1331 
1332  return std::move(ret);
1333 }
1334 
1335 numu::RecoEvent NumuReco::Reconstruct(const gallery::Event &ev, const std::vector<event::Interaction> &truth) {
1336  // setup products
1337  CollectCRTInformation(ev);
1338  CollectPMTInformation(ev);
1339  CollectTPCInformation(ev);
1340 
1341  // colect PFParticle information
1342  std::vector<numu::RecoParticle> reco_particles = RecoParticleInfo();
1343 
1344  // collect track information
1345  std::map<size_t, numu::RecoTrack> reco_tracks = RecoTrackInfo();
1346 
1347  // collect Pandora slice information
1348  std::vector<numu::RecoSlice> reco_slices = RecoSliceInfo(reco_tracks, reco_particles);
1349 
1350  std::vector<numu::RecoInteraction> reco;
1351  for (unsigned reco_i = 0; reco_i < reco_slices.size(); reco_i++) {
1352  const numu::RecoParticle &neutrino = reco_slices[reco_i].particles.at(reco_slices[reco_i].primary_index);
1353 
1354  numu::RecoInteraction this_interaction;
1355 
1356  this_interaction.slice = reco_slices[reco_i];
1357  this_interaction.position = neutrino.vertices[0];
1358 
1359  // TODO: get the enrgy
1360  this_interaction.nu_energy = -1;
1361 
1362  // Track multiplicity
1363  this_interaction.multiplicity = this_interaction.slice.particles.at(this_interaction.slice.primary_index).daughters.size();
1364 
1365  // do initial truth matching
1366  this_interaction.match = numu::InteractionTruthMatch(truth, reco_tracks, this_interaction);
1367 
1368  // store
1369  reco.push_back(std::move(this_interaction));
1370  }
1371 
1372  numu::RecoEvent event;
1373  event.reco = std::move(reco);
1374  event.tracks = std::move(reco_tracks);
1375 
1376  // collect spare detector information
1377  event.in_time_crt_hits = InTimeCRTHits();
1378  gallery::Handle<std::vector<raw::OpDetWaveform>> waveforms;
1379  if (ev.getByLabel("opdaq", waveforms)) {
1380  double tick_period = fProviderManager->GetDetectorClocksProvider()->OpticalClock().TickPeriod();
1381  int threshold = _config.PMTTriggerThreshold;
1382  bool is_sbnd = fExperimentID == kExpSBND;
1383  std::pair<double, double> window;
1384  if (is_sbnd) window = {0., 2.}; // go out to 0.4us past end of beam gate
1385  else window = {1500., 1502.};
1386  event.flash_trigger_primitives = numu::TriggerPrimitives(*waveforms, tick_period, window, threshold, is_sbnd);
1387  }
1388 
1389  // fill spare histograms
1390  FillCRTHits();
1391 
1392 
1393  return std::move(event);
1394 }
1395 
1396 bool NumuReco::InActive(const TVector3 &v) const {
1397  for (auto const& active: _config.active_volumes) {
1398  if (active.ContainsPosition(v)) return true;
1399  }
1400  return false;
1401 }
1402 
1403 
1404  } // namespace SBNOsc
1405 } // namespace ana
1406 
1407 
1409 
std::map< int, art::Ptr< simb::MCTruth > > _true_particles_to_truth
Definition: NumuReco.h:380
bool verbose
Whether to print out info associated w/ selection.
Definition: NumuReco.h:102
InteractionMode mode
Mode of the interaction.
float z_err
position uncertainty in z-direction (cm).
Definition: CRTHit.hh:43
process_name vertex
Definition: cheaterreco.fcl:51
bool mctruth_has_neutrino
Whether the MCTruth object this track matches to is a neutrino interaction.
Track track
CRT Track match.
Definition: CRTMatch.h:30
int pdgid
Particle ID that minimizes chi2.
Definition: RecoTrack.h:46
TVector3 start_momentum
Particle directional momentum for first trajectory point inside TPC AV [GeV].
Definition: TrueParticle.h:24
float x_err
position uncertainty in x-direction (cm).
Definition: CRTHit.hh:39
std::map< uint8_t, std::vector< std::pair< int, float > > > pesmap
Saves signal hit information (FEB, local-channel and PE) .
Definition: CRTHit.hh:26
bool requireTrack
Apply cut that requires each reconstructed vertex to have an associated primary track.
Definition: NumuReco.h:108
void Initialize(fhicl::ParameterSet *config=NULL)
Definition: NumuReco.cxx:170
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
std::vector< geo::BoxBoundedGeo > ActiveVolumes(const geo::GeometryCore *geometry)
Definition: GeoUtil.cc:3
std::array< float, 2 > BeamSpillWindow
Definition: NumuReco.h:126
float chi2_muon
Chi2 of dE/dx to muon hypotheis. Combined agaisnt all planes.
Definition: RecoTrack.h:43
float chi2_kaon
Chi2 of dE/dx to kaon hypotheis. Combined against all planes.
Definition: RecoTrack.h:41
int ID
ID/index of this particle (taken from MCParticle ID)
Definition: TrueParticle.h:47
int mctruth_ccnc
CC (1) / NC (0) value of the MCTruth this object matches to.
void reconfigure(const core::ProviderManager &manager, const Config &config)
int pandora_pid
Particle ID from pandora.
Definition: RecoParticle.h:19
float bwd_mcs_momentum_err
MCS momentum calculation fit error under hypothesis track is backward.
Definition: RecoTrack.h:17
MCSFitResult mcs_proton
MCS calculation result for Proton PID hypothesis.
Definition: RecoTrack.h:37
MCSFitResult mcs_pion
MCS calculation result for Pion PID hypothesis.
Definition: RecoTrack.h:36
std::vector< uint8_t > feb_id
FEB address.
Definition: CRTHit.hh:25
ClusterModuleLabel join with tracks
double ts1_ns
Timestamp T1 ([signal time w.r.t. Trigger time]), in UTC absolute time scale in nanoseconds from the ...
Definition: CRTHit.hh:34
Encapsulate the construction of a single cyostat.
float distance
//!&lt; Distance from projected track to CRT Hit. Nonsense if present is false.
Definition: CRTMatch.h:26
const unsigned int & TriggerType() const
Definition: T0.h:45
int mctruth_origin
Value of Origin_t enum of the MCTruth object this track matches to.
int GetPhotonMotherID(int mcparticle_id)
Definition: NumuReco.cxx:127
bool is_cosmic
Whether this particle is of cosmic origin.
Definition: TrueParticle.h:45
CRTMatch crt_match
CRTMatch.
Definition: RecoTrack.h:59
int plane
Name of the CRT wall (in the form of numbers).
Definition: CRTHit.hh:36
bool present
Whether this CRTMatch has a matching track.
Definition: CRTMatch.h:16
const double & Time() const
Definition: T0.h:44
float peshit
Total photo-electron (PE) in a crt hit.
Definition: CRTHit.hh:27
float bwdMomentum() const
momentum value from fit assuming a backward track direction
Definition: MCSFitResult.h:38
TruthMatch match
Info for mathing to truth.
Definition: RecoEvent.h:42
StoppingParticleCosmicIdAlg _stopping_cosmic_alg
Algorithm for doing cosmic ID using a fit to the energy deposits.
Definition: NumuReco.h:345
float y_err
position uncertainty in y-direction (cm).
Definition: CRTHit.hh:41
std::vector< std::vector< geo::BoxBoundedGeo > > tpc_volumes
List of active tpc volumes – retreived from Geoemtry service.
Definition: NumuReco.h:100
Declaration of signal hit object.
int mcparticle_id
MCParticle ID of the particle this track matches to (same as the ID of the RecoTrack of that particle...
std::string CRTTrackTag
art tag for CRT tracks
Definition: NumuReco.h:139
float min_chi2
Minimum chi2 value across all hypotheses.
Definition: RecoTrack.h:44
int primary_track_index
Index of the primary track.
Definition: RecoEvent.h:27
float fwdMomUncertainty() const
momentum uncertainty from fit assuming a forward track direction
Definition: MCSFitResult.h:32
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:88
const detinfo::DetectorPropertiesStandard * GetDetectorPropertiesProvider() const
std::vector< FlashTriggerPrimitive > TriggerPrimitives(const std::vector< raw::OpDetWaveform > &waveforms, double tick_period, std::pair< double, double > &window, int thresh, bool is_sbnd)
Definition: PMTTrigger.cc:7
unsigned pe
number of photo electons in flash
return track match has_match and!particle is_contained
Definition: selectors.fcl:108
TVector3 end_momentum
Particle directional momentum for last trajectory point inside TPC AV [GeV].
Definition: TrueParticle.h:25
int PdgCode() const
Return the type of particle as a PDG ID.
Definition: PFParticle.h:83
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:91
void reconfigure(const core::ProviderManager &manager, const Config &config)
process_name use argoneut_mc_hitfinder track
sbn::crt::CRTHit ICARUS2SBNDCrtHit(const sbn::crt::CRTHit &inp)
Definition: NumuReco.cxx:138
Definition: T0.h:16
process_name hit
Definition: cheaterreco.fcl:51
process_name opflashCryoW ana
size_t ID
ID of particle.
Definition: RecoParticle.h:18
bool is_contained
is it contained in a single cryostat active volume
Definition: TrueParticle.h:40
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
std::vector< size_t > daughters
Daughters of the particle in the &quot;particle flow&quot;. Value represents index into pandora information...
Definition: RecoParticle.h:17
float length
Length of track contained in any TPC active volume [cm].
Definition: TrueParticle.h:42
double ts0_ns_corr
[Honestly, not sure at this point, it was there since long time (BB)]
Definition: CRTHit.hh:33
TVector3 start
start position of track
Definition: TrueParticle.h:30
std::vector< std::string > TPCRecoTagSuffixes
Definition: NumuReco.h:133
float stopping_chisq_finish
Chi2 fraction of stopping vs. not-stopping hypotheis to track end point.
Definition: RecoTrack.h:64
ApaCrossCosmicIdAlg _apa_cross_cosmic_alg
Algorithm for doing cosmic ID by looking for tracks crossing APA.
Definition: NumuReco.h:344
const geo::GeometryCore * GetGeometryProvider() const
double ts0_s_corr
[Honestly, not sure at this point, it was there since long time (BB)]
Definition: CRTHit.hh:30
TVector3 uncertainty
Uncertainty on the location of the hit.
Definition: DetInfo.h:17
uint64_t ts0_s
Second-only part of timestamp T0.
Definition: CRTHit.hh:29
trkf::TrackMomentumCalculator * _track_momentum_calculator
Calculator for range-based track momentum.
Definition: NumuReco.h:335
TVector3 location
Location of the hit.
Definition: DetInfo.h:16
float p_nu_score
Take from Pandora metadata &quot;nu_score&quot;.
Definition: RecoParticle.h:15
bool SelectSlice(const caf::SRSlice &slice, bool cut_clear_cosmic)
Definition: FillReco.cxx:14
std::vector< RecoInteraction > reco
List of reconstructed vertices.
Definition: RecoEvent.h:50
float bwd_mcs_momentum
MCS momentum calculation under hypothesis track is backward.
Definition: RecoTrack.h:16
float z_pos
position in z-direction (cm).
Definition: CRTHit.hh:42
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
double ts0_ns
Timestamp T0 (from White Rabbit), in UTC absolute time scale in nanoseconds from the Epoch...
Definition: CRTHit.hh:32
Access the description of detector geometry.
bool crosses_tpc
does it cross a tpc?
Definition: TrueParticle.h:39
float end_energy
Particle energy for last point inside TPC AV [GeV].
Definition: TrueParticle.h:27
T abs(T value)
TVector3 position
location of the vertex
Definition: RecoEvent.h:40
Contains truth level information and additional fields for selection-defined reconstruction informati...
Definition: Event.hh:178
float reco_energy
Reconstructed neutrino energy [GeV].
Definition: Event.hh:195
std::vector< std::string > uniformWeights
Weights taken from &quot;EventWeight&quot; that should be applied to the weight of each event.
Definition: NumuReco.h:103
MCSFitResult mcs_kaon
MCS calculation result for Kaon PID hypothesis.
Definition: RecoTrack.h:38
process_name standard_reco_uboone reco
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
Metadata associated to PFParticles.
double TrackCompletion(const core::ProviderManager &manager, int mcparticle_id, const std::vector< art::Ptr< recob::Hit >> &reco_track_hits)
bool requireContained
Apply cut that requires each primary track to be contained inside the containment volume...
Definition: NumuReco.h:109
bool contained_in_cryo
is it contained a single cryostat?
Definition: TrueParticle.h:37
sbnd::CRTTrackMatchAlg * _crt_track_matchalg
Algorithm for matching reco Tracks -&gt; CRT Tracks.
Definition: NumuReco.h:342
TVector3 start
start position of track
Definition: RecoTrack.h:54
float range_momentum_muon
Range momentum calculation of the track using range under the assumption it is a muon [GeV]...
Definition: RecoTrack.h:33
TVector3 mctruth_vertex
The interaction vertex of the MCTruth object this track matches to.
float start_energy
Particle energy for first point inside TPC AV [GeV].
Definition: TrueParticle.h:26
FlashMatch flash_match
Result of flash matching algorithm on this slice.
Definition: RecoEvent.h:30
TVector3 end
end position of track
Definition: TrueParticle.h:31
float weight
Selection-defined event weight.
Definition: Event.hh:196
float chi2_pion
Chi2 of dE/dx to pion hypotheis. Combined against all planes.
Definition: RecoTrack.h:42
numu::Wall GetWallCross(const geo::BoxBoundedGeo &volume, const TVector3 p0, const TVector3 p1)
Definition: NumuReco.cxx:79
double cosmicWeight
Weight applied to all events matched to a cosmic track.
Definition: NumuReco.h:105
bool requireMatched
Apply cut that requires each reconstructed vertex to be matched to a truth vertex.
Definition: NumuReco.h:107
float length
Length of track.
Definition: RecoTrack.h:48
const PropertiesMap & GetPropertiesMap() const
std::map< int, const sim::GeneratedParticleInfo * > _true_particles_to_generator_info
Definition: NumuReco.h:381
sbnd::CRTT0MatchAlg * _crt_hit_matchalg
Algorithm for matching reco Tracks -&gt; CRT hits (T0&#39;s)
Definition: NumuReco.h:343
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
double MinZ() const
Returns the world z coordinate of the start of the box.
bool present
Whether this CRTMatch has a matching hit.
Definition: CRTMatch.h:25
BEGIN_PROLOG baseline
int TrueParticleIDFromTotalTrueEnergy(const core::ProviderManager &manager, const std::vector< art::Ptr< recob::Hit > > &hits, bool rollup_unsaved_ids=1)
float completion
Fraction of energy deposits by true particle matched by this track.
const Cut kCosmicRay
opdet::opHitFinderSBND * _op_hit_maker
Optical hit maker.
Definition: NumuReco.h:346
#define DECLARE_SBN_PROCESSOR(classname)
Electron neutrino event selection.
Definition: NumuReco.h:69
back track the reconstruction to the simulation
float time
CRT Hit time.
Definition: DetInfo.h:13
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch fmatch
Definition: reco_sbnd.fcl:182
float fwd_mcs_momentum
MCS momentum calculation under hypothesis track is forward.
Definition: RecoTrack.h:14
TruthMatch InteractionTruthMatch(const std::vector< event::Interaction > &truth, const std::map< size_t, numu::RecoTrack > &reco_tracks, const numu::RecoInteraction &reco)
Definition: TruthMatch.cc:10
float stopping_chisq_start
Chi2 fraction of stopping vs. not-stopping hypothesis to track start points.
Definition: RecoTrack.h:63
std::vector< TVector3 > vertices
List of vertices associated with the particle.
Definition: RecoParticle.h:16
const detinfo::DetectorClocksStandard * GetDetectorClocksProvider() const
bool has_match
Whether a track match exists.
bool crosses_tpc
does it cross a tpc?
Definition: RecoTrack.h:51
Provides recob::Track data product.
std::vector< std::vector< geo::BoxBoundedGeo > > TPCVolumes(const geo::GeometryCore *geometry)
Definition: GeoUtil.cc:49
std::vector< geo::BoxBoundedGeo > containment_volumes
List of volumes for containment cuts – set by &quot;containment_volumes&quot;.
Definition: NumuReco.h:98
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
std::string CorsikaTag
art tag for corsika MCTruth
Definition: NumuReco.h:138
double MaxY() const
Returns the world y coordinate of the end of the box.
Class storing the result of the Maximum Likelihood fit of Multiple Coulomb Scattering angles between ...
Definition: MCSFitResult.h:19
void DumpTrueStart(const gallery::Event &ev, int mcparticle_id)
Definition: NumuReco.cxx:67
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
static const TVector3 InvalidTVector3
Definition: NumuReco.cxx:65
bool is_primary
Whether this track was produced as the &quot;primary&quot; process.
std::vector< geo::BoxBoundedGeo > active_volumes
List of active volumes per cryostat.
Definition: NumuReco.h:99
float deposited_energy
Total particle energy depositive in TPC AV [GeV].
Definition: TrueParticle.h:28
float y_pos
position in y-direction (cm).
Definition: CRTHit.hh:40
TrackTruthMatch match
Truth matching information.
Definition: RecoTrack.h:57
bool p_is_neutrino
Taken from Pandora metadata &quot;is_neutrino&quot;.
Definition: RecoParticle.h:14
int SelectLongestTrack(const std::map< size_t, RecoTrack > &tracks, const RecoSlice &slice)
Definition: PrimaryTrack.cc:3
float nu_energy
true/reconstructed neutrino energy
Definition: RecoEvent.h:41
bool p_is_clear_cosmic
Taken from Pandora metadata &quot;is_clear_cosmic&quot;.
Definition: RecoParticle.h:13
float bwdMomUncertainty() const
momentum uncertainty from fit assuming a backward track direction
Definition: MCSFitResult.h:41
RecoSlice slice
Particle content of the interaction.
Definition: RecoEvent.h:39
Hierarchical representation of particle flow.
Definition: PFParticle.h:44
const double & TriggerConfidence() const
Definition: T0.h:48
int pid_n_dof
Number of d.o.f. in chi2 fit.
Definition: RecoTrack.h:45
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:33
std::string PFParticleTag
art tag for PFParticles
Definition: NumuReco.h:136
int mctruth_vertex_id
index of the truth vertex into the list of MCThruths. -1 if no match
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
int DriftDirectionFromHits(const geo::GeometryCore *GeometryService, std::vector< art::Ptr< recob::Hit >> hits)
float x_pos
position in x-direction (cm).
Definition: CRTHit.hh:38
double containedLength(const TVector3 &v0, const TVector3 &v1, const std::vector< geoalgo::AABox > &boxes)
int pdgid
Particle ID code.
Definition: TrueParticle.h:43
double MaxZ() const
Returns the world z coordinate of the end of the box.
float pes
Number of PE&#39;s in hit.
Definition: DetInfo.h:15
trkf::TrajectoryMCSFitter * _mcs_fitter
Calculator for MCS based momentum.
Definition: NumuReco.h:336
Config _config
The config.
Definition: NumuReco.h:332
bool contained_in_tpc
is it contained in a single TPC?
Definition: TrueParticle.h:38
std::map< size_t, RecoParticle > particles
Map of particle index to particle information.
Definition: RecoEvent.h:28
int multiplicity
Number of tracks in this interaction.
Definition: RecoEvent.h:43
ProviderManager * fProviderManager
Interface for provider access.
double constantWeight
Constant weight to apply uniformly to each event.
Definition: NumuReco.h:104
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.
int tick_period
Definition: constants.py:3
std::vector< size_t > tracks
List of track indices contained in this slice.
Definition: RecoEvent.h:29
Class for Maximum Likelihood fit of Multiple Coulomb Scattering angles between segments within a Trac...
float angle
Angle between TPC track and CRT track.
Definition: CRTMatch.h:18
Header for the ParticleInvenotry Service Provider.
float range_momentum_proton
Range momentum calculation of track using range using the assumption it is a proton [GeV]...
Definition: RecoTrack.h:34
TVector3 end
end position of track
Definition: RecoTrack.h:55
CRTHit hit
Definition: CRTMatch.h:32
int primary_index
Index of the primary particle of this slice.
Definition: RecoEvent.h:25
float fwdMomentum() const
momentum value from fit assuming a forward track direction
Definition: MCSFitResult.h:29
int match_pdg
PDG of the MCParticle this track matches to.
std::string MCParticleTag
art tag for MCParticle
Definition: NumuReco.h:142
MCSFitResult mcs_muon
MCS calculation result for Muon PID hypothesis.
Definition: RecoTrack.h:35
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
int ID
ID/index of this track. Does not necessarily correspond to the Pandora index.
Definition: RecoTrack.h:61
Wall wall_enter
the face of the TPC that the particle crosses on enter
Definition: TrueParticle.h:35
Wall wall_exit
the face of the TPC that the particle crosses on exit
Definition: TrueParticle.h:36
double MinY() const
Returns the world y coordinate of the start of the box.
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int const &id) const
std::string tagger
Name of the CRT wall (in the form of strings).
Definition: CRTHit.hh:45
float fwd_mcs_momentum_err
MCS momentum calculation fit error under hypothesis track is forward.
Definition: RecoTrack.h:15
HitMatch hit_match
CRT Hit match.
Definition: CRTMatch.h:31
physics associatedGroupsWithLeft p1
BEGIN_PROLOG could also be cout
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a &quot;fitted&quot; track:
std::string RecoTrackTag
art tag for reconstructed tracks
Definition: NumuReco.h:131
float costh
cosine of angle to z axis
Definition: RecoTrack.h:49
Encapsulate the construction of a single detector plane.
double RecoTrackLength(const art::Ptr< recob::Track > &track)
Definition: NumuReco.cxx:537
Signal from collection planes.
Definition: geo_types.h:146
float start_time
start time of track
Definition: TrueParticle.h:32
std::string RecoVertexTag
art tag for reconstructed vertices
Definition: NumuReco.h:132
float end_time
end time of track
Definition: TrueParticle.h:33
float time
Matching time [us] of track. T==0 is set to beam spill start time.
Definition: CRTMatch.h:17
float chi2_proton
Chi2 of dE/dx to proton hypothesis. Combined against all planes.
Definition: RecoTrack.h:40