All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NumuSelection.cxx
Go to the documentation of this file.
1 #include <iostream>
2 #include <cmath>
3 #include <vector>
4 
5 #include "fhiclcpp/ParameterSet.h"
6 
7 #include <TH2D.h>
8 #include <TH1D.h>
9 
10 #include "gallery/ValidHandle.h"
11 #include "canvas/Utilities/InputTag.h"
12 #include "canvas/Persistency/Common/FindMany.h"
13 
14 #include "nusimdata/SimulationBase/MCTruth.h"
15 #include "nusimdata/SimulationBase/MCNeutrino.h"
16 #include "nusimdata/SimulationBase/MCTruth.h"
17 #include "nusimdata/SimulationBase/MCNeutrino.h"
21 
22 #include "core/Event.hh"
23 #include "NumuSelection.h"
24 #include "Utilities.h"
25 
26 namespace ana {
27  namespace SBNOsc {
28 
30  SelectionBase(),
31  _event_counter(0),
32  _nu_count(0),
33  _rand(57 /* seed */),
34  _interactionInfo(new std::vector<NuMuInteraction>) {
35  // setup the event categories
36  _eventCategories["CC0pi"] = 0;
37  _eventCategories["CC1pi"] = 0;
38  _eventCategories["CC2pi"] = 0;
39  _eventCategories["CCnpi"] = 0;
40 
41  _eventCategories["NC0pi"] = 0;
42  _eventCategories["NC1pi"] = 0;
43  _eventCategories["NC2pi"] = 0;
44  _eventCategories["NCnpi"] = 0;
45 
46  // more
47  _eventCategories["CCnoMU"] = 0;
48  _eventCategories["NCwiMU"] = 0;
49 
50  // more
51  _eventCategories["CCQE"] = 0;
52  _eventCategories["CCRES"] = 0;
53  _eventCategories["CCDIS"] = 0;
54  _eventCategories["CCCOH"] = 0;
55  _eventCategories["CCMEC"] = 0;
56  _eventCategories["CCCOHE"] = 0;
57  _eventCategories["CCother"] = 0;
58 }
59 
60 
61 double aaBoxesMin(const std::vector<geoalgo::AABox> &boxes, unsigned dim) {
62  return std::min_element(boxes.begin(), boxes.end(), [dim](auto &lhs, auto &rhs) { return lhs.Min()[dim] < rhs.Min()[dim]; })->Min()[dim];
63 }
64 
65 double aaBoxesMax(const std::vector<geoalgo::AABox> &boxes, unsigned dim) {
66  return std::max_element(boxes.begin(), boxes.end(), [dim](auto &lhs, auto &rhs) { return lhs.Max()[dim] < rhs.Max()[dim]; })->Max()[dim];
67 }
68 
69 geoalgo::AABox shaveVolume(const geoalgo::AABox &select_volume, double delta) {
70 
71  double xmin = select_volume.Min()[0] + 5.;
72  double ymin = select_volume.Min()[1] + 5.;
73  double zmin = select_volume.Min()[2] + 5.;
74 
75  double xmax = select_volume.Max()[0] - 5.;
76  double ymax = select_volume.Max()[1] - 5.;
77  double zmax = select_volume.Max()[2] - 5.;
78 
79  return geoalgo::AABox(xmin, ymin, zmin, xmax, ymax, zmax);
80 }
81 
82 
83 void NumuSelection::Initialize(fhicl::ParameterSet* config) {
84  if (config) {
85  fhicl::ParameterSet pconfig = config->get<fhicl::ParameterSet>("NumuSelection");
86 
87  // setup active volume bounding boxes
88  std::vector<fhicl::ParameterSet> AVs = \
89  pconfig.get<std::vector<fhicl::ParameterSet> >("active_volumes");
90  for (auto const& AV : AVs) {
91  double xmin = AV.get<double>("xmin");
92  double ymin = AV.get<double>("ymin");
93  double zmin = AV.get<double>("zmin");
94  double xmax = AV.get<double>("xmax");
95  double ymax = AV.get<double>("ymax");
96  double zmax = AV.get<double>("zmax");
97  _config.active_volumes.emplace_back(xmin, ymin, zmin, xmax, ymax, zmax);
98  }
99 
100  std::vector<fhicl::ParameterSet> FVs = \
101  pconfig.get<std::vector<fhicl::ParameterSet> >("fiducial_volumes");
102  for (auto const& FV : FVs) {
103  double xmin = FV.get<double>("xmin");
104  double ymin = FV.get<double>("ymin");
105  double zmin = FV.get<double>("zmin");
106  double xmax = FV.get<double>("xmax");
107  double ymax = FV.get<double>("ymax");
108  double zmax = FV.get<double>("zmax");
109  _config.fiducial_volumes.emplace_back(xmin, ymin, zmin, xmax, ymax, zmax);
110  }
111 
112  _config.doFVCut = pconfig.get<bool>("doFVcut", true);
113  _config.trajPointLength = pconfig.get<bool>("trajPointLength", true);
114  _config.vertexDistanceCut = pconfig.get<double>("vertexDistance", -1);
115  _config.minLengthContainedTrack = pconfig.get<double>("minLengthContainedTrack", -1);
116  _config.minLengthExitingTrack = pconfig.get<double>("minLengthExitingTrack", -1);
117  _config.trackVisibleEnergyThreshold = pconfig.get<double>("trackVisibleEnergyThreshold", 0.);
118  _config.showerEnergyDistortion = pconfig.get<double>("showerEnergyDistortion", 0.);
119  _config.trackEnergyDistortion = pconfig.get<double>("trackEnergyDistortion", 0.);
120  _config.leptonEnergyDistortionContained = pconfig.get<double>("leptonEnergyDistortionContained", 0.);
121  _config.leptonEnergyDistortionLeavingA = pconfig.get<double>("leptonEnergyDistortionLeavingA", 0.);
122  _config.leptonEnergyDistortionLeavingB = pconfig.get<double>("leptonEnergyDistortionLeavingB", 0.);
123  _config.acceptShakyTracks = pconfig.get<bool>("acceptShakyTracks", false);
124  _config.verbose = pconfig.get<bool>("verbose", false);
125  _config.cutKMEC = pconfig.get<bool>("cutKMEC", false);
126  _config.selectMode = pconfig.get<int>("selectMode", -1);
127  _config.selectCCNC = pconfig.get<int>("selectCCNC", -1);
128  _config.onlyKMEC = pconfig.get<bool>("onlyKMEC", false);
129 
130  // setup weight config
131  _config.selectionEfficiency = pconfig.get<double>("selectionEfficiency", 1.0);
132  _config.backgroundRejection = pconfig.get<double>("backgroundRejection", 0.0);
133  _config.uniformWeights = pconfig.get<std::vector<std::string>>("uniformWeights", {});
134  _config.constantWeight = pconfig.get<double>("constantWeight", 1.0);
135  _config.constantCCWeight = pconfig.get<double>("constantCCWeight", 1.0);
136  _config.constantNCWeight = pconfig.get<double>("constantNCWeight", 1.0);
137  _config.constantEnergyScale = pconfig.get<double>("constantEnergyScale", 1.0);
138 
139  }
140 
141  // Setup histo's for root output
142  fOutputFile->cd();
143  auto cut_names = cutNames();
144  for (unsigned i = 0; i < nCuts; i++) {
145  _root_histos[i].h_numu_ccqe = new TH1D(("numu_ccqe_" + cut_names[i]).c_str(), "numu_ccqe", 100, 0, 10);
146  _root_histos[i].h_numu_trueE = new TH1D(("numu_trueE_" + cut_names[i]).c_str(), "numu_trueE", 100, 0 , 10);
147  _root_histos[i].h_numu_visibleE = new TH1D(("numu_visibleE_" + cut_names[i]).c_str(), "numu_visibleE", 100, 0, 10);
148  _root_histos[i].h_numu_true_v_visibleE = new TH1D(("numu_true_v_visibleE_" + cut_names[i]).c_str(), "numu_true_v_visibleE", 100, -10, 10);
149  _root_histos[i].h_numu_t_length = new TH1D(("numu_t_length_" + cut_names[i]).c_str(), "numu_t_length", 101, -10, 1000);
150  _root_histos[i].h_numu_contained_L = new TH1D(("numu_contained_L_" + cut_names[i]).c_str(), "numu_contained_L", 101, -10 , 1000);
151  _root_histos[i].h_numu_t_is_contained = new TH1D(("t_is_contained_" + cut_names[i]).c_str(), "t_is_contained", 3, -1.5, 1.5);
152  _root_histos[i].h_numu_t_is_muon = new TH1D(("t_is_muon_" + cut_names[i]).c_str(), "t_is_muon", 3, -1.5, 1.5);
153  _root_histos[i].h_numu_Vxy = new TH2D(("numu_Vxy_" + cut_names[i]).c_str(), "numu_Vxy",
156  _root_histos[i].h_numu_Vxz = new TH2D(("numu_Vxz_" + cut_names[i]).c_str(), "numu_Vxz",
159  _root_histos[i].h_numu_Vyz = new TH2D(("numu_Vyz_" + cut_names[i]).c_str(), "numu_Vyz",
162 
163  _root_histos[i].h_numu_Vx_sig = new TH1D(("numu_Vx_sig" + cut_names[i]).c_str(), "numu_Vx_sig", 20,
165  _root_histos[i].h_numu_Vy_sig = new TH1D(("numu_Vy_sig" + cut_names[i]).c_str(), "numu_Vy_sig", 20,
167  _root_histos[i].h_numu_Vz_sig = new TH1D(("numu_Vz_sig" + cut_names[i]).c_str(), "numu_Vz_sig", 20,
169 
170  _root_histos[i].h_numu_Vx_bkg = new TH1D(("numu_Vx_bkg" + cut_names[i]).c_str(), "numu_Vx_bkg", 20,
172  _root_histos[i].h_numu_Vy_bkg = new TH1D(("numu_Vy_bkg" + cut_names[i]).c_str(), "numu_Vy_bkg", 20,
174  _root_histos[i].h_numu_Vz_bkg = new TH1D(("numu_Vz_bkg" + cut_names[i]).c_str(), "numu_Vz_bkg", 20,
176 
177  _root_histos[i].h_numu_t_is_muon_sig = new TH1D(("t_is_muon_sig_" + cut_names[i]).c_str(), "t_is_muon_sig", 3, -1.5, 1.5);
178  _root_histos[i].h_numu_t_is_muon_bkg = new TH1D(("t_is_muon_bkg_" + cut_names[i]).c_str(), "t_is_muon_bkg", 3, -1.5, 1.5);
179 
180  }
181 
182  // set up TGraph keeping track of cut counts
183  _cut_counts = new TGraph(NumuSelection::nCuts + 1);
184 
185  // add branches
186  fTree->Branch("numu_interaction", &_interactionInfo);
187 
188  hello();
189 }
190 
191 
193  // write out histos
194  fOutputFile->cd();
195  for (unsigned i = 0; i < nCuts; i++) {
196  _root_histos[i].h_numu_ccqe->Write();
197  _root_histos[i].h_numu_trueE->Write();
198  _root_histos[i].h_numu_visibleE->Write();
200  _root_histos[i].h_numu_t_length->Write();
201  _root_histos[i].h_numu_t_is_muon->Write();
202  _root_histos[i].h_numu_contained_L->Write();
204  _root_histos[i].h_numu_Vxy->Write();
205  _root_histos[i].h_numu_Vxz->Write();
206  _root_histos[i].h_numu_Vyz->Write();
207 
208  _root_histos[i].h_numu_Vx_sig->Write();
209  _root_histos[i].h_numu_Vy_sig->Write();
210  _root_histos[i].h_numu_Vz_sig->Write();
211  _root_histos[i].h_numu_Vx_bkg->Write();
212  _root_histos[i].h_numu_Vy_bkg->Write();
213  _root_histos[i].h_numu_Vz_bkg->Write();
214 
217  }
218  _cut_counts->Write();
219 
220  // print out event stats
221  std::map<std::string, double>::iterator it = _eventCategories.begin();
222  while (it != _eventCategories.end()) {
223  std::cout << "Category: " << it->first << " " << it->second << std::endl;
224  it ++;
225  }
226 }
227 
228 
229 bool NumuSelection::ProcessEvent(const gallery::Event& ev, const std::vector<event::Interaction> &truth, std::vector<event::RecoInteraction>& reco) {
230  if (_event_counter % 10 == 0) {
231  std::cout << "NumuSelection: Processing event " << _event_counter << " "
232  << "(" << _nu_count << " neutrinos selected)"
233  << std::endl;
234  }
235  // clean up containers
236  _event_counter++;
237  _interactionInfo->clear();
238 
239  // Get truth
240  auto const& mctruths = \
241  *ev.getValidHandle<std::vector<simb::MCTruth> >(fTruthTag);
242  // get tracks and showers
243  auto const& mctracks = \
244  *ev.getValidHandle<std::vector<sim::MCTrack> >(fMCTrackTag);
245  auto const& mcshowers = \
246  *ev.getValidHandle<std::vector<sim::MCShower> >(fMCShowerTag);
247 
248  // update total count of interactions
249  _cut_counts->SetPoint(0, 0, _cut_counts->GetY()[0] + mctruths.size());
250 
251  // categorize events:
252  for (unsigned i = 0; i < mctruths.size(); i++) {
253  auto const &mctruth = mctruths[i];
254  event::Interaction interaction = truth[i];
255  double weight = 1.;
256  // maybe cut MEC
257  bool pass_kMEC = !(_config.cutKMEC && mctruth.GetNeutrino().Mode() == simb::kMEC) && !(_config.onlyKMEC && mctruth.GetNeutrino().Mode() != simb::kMEC);
258  if (!pass_kMEC) continue;
259  for (auto const &key: _config.uniformWeights) {
260  weight *= interaction.weights.at(key)[0];
261  }
262  if (containedInAV(mctruth.GetNeutrino().Nu().Position().Vect())) {
263  bool iscc = mctruth.GetNeutrino().CCNC() == 0;
264  unsigned n_pions = 0;
265  for (auto const &mctrack: mctracks) {
266  if (isFromNuVertex(mctruth, mctrack) && abs(mctrack.PdgCode()) == 211 && mctrack.Process() == "primary") {
267  n_pions += 1;
268  }
269  // categorize on number of pions
270  }
271  if (iscc) {
272  if (n_pions == 0) _eventCategories["CC0pi"] += weight;
273  else if (n_pions == 1) _eventCategories["CC1pi"] += weight;
274  else if (n_pions == 2) _eventCategories["CC2pi"] += weight;
275  else _eventCategories["CCnpi"] += weight;
276  }
277  else {
278  if (n_pions == 0) _eventCategories["NC0pi"] += weight;
279  else if (n_pions == 1) _eventCategories["NC1pi"] += weight;
280  else if (n_pions == 2) _eventCategories["NC2pi"] += weight;
281  else _eventCategories["NCnpi"] += weight;
282  }
283  // categorize on event mode
284  if (iscc) {
285  int mode = mctruth.GetNeutrino().Mode();
286  if (mode == simb::kQE) _eventCategories["CCQE"] += weight;
287  else if (mode == simb::kCoh) _eventCategories["CCCOH"] += weight;
288  else if (mode == simb::kRes) _eventCategories["CCRES"] += weight;
289  else if (mode == simb::kMEC) _eventCategories["CCMEC"] += weight;
290  else if (mode == simb::kDIS) _eventCategories["CCDIS"] += weight;
291  else if (mode == simb::kCohElastic) _eventCategories["CCCOHE"] += weight;
292  else _eventCategories["CCother"] += weight;
293  }
294  }
295  }
296 
297  // Iterate through the neutrinos
298  bool selected = false;
299  for (size_t i=0; i<mctruths.size(); i++) {
300  auto const& mctruth = mctruths.at(i);
301  // get the neutrino
302  const simb::MCNeutrino& nu = mctruth.GetNeutrino();
303 
304  // setup energy calculations
305  VisibleEnergyCalculator calculator;
306  calculator.lepton_pdgid = 13;
313 
314  // build the interaction
315  event::Interaction interaction = truth[i];
316 
317  // Get selection-specific info
318  //
319  // Start with the interaction stuff
320  // This also sets the lepton variables in the calculator
321  NuMuInteraction intInfo = interactionInfo(ev, mctruth, calculator);
322 
323  // double visible_energy = visibleEnergyProposalMCParticles(_rand, mctruth, mctracks, calculator);
324  double visible_energy = visibleEnergyProposal(_rand, mctruth, mctracks, calculator);
325 
326  event::RecoInteraction reco_interaction(i);
327  // apply energy scale shift
328  visible_energy *= _config.constantEnergyScale;
329  reco_interaction.reco_energy = visible_energy;
330 
331  // Build the weight of this event
332  double weight = 1.;
333  // apply uniofrm weights (e.g. bnbcorrection)
334  for (auto const &key: _config.uniformWeights) {
335  weight *= interaction.weights.at(key)[0];
336  }
337  // whether this event is signal or background
338  // bool is_signal = abs(intInfo.t_pdgid) == 13; // muon
339  bool is_signal = interaction.neutrino.iscc;
340  // selection efficiency
341  if (is_signal) {
342  if (abs(intInfo.t_pdgid) != 13) {
343  _eventCategories["CCnoMU"] += weight;
344  }
345  weight *= _config.selectionEfficiency;
346  }
347  else {
348  if (abs(intInfo.t_pdgid) == 13) {
349  _eventCategories["NCwiMU"] += weight;
350  }
351  weight *= 1 - _config.backgroundRejection;
352  }
353  // apply constant weight
354  weight *= _config.constantWeight;
355 
356  // apply weight to CC events
357  // Operationally, these weights are the same as signal/bkg efficiencies, but they have
358  // a very different semantic meaning, so we separate out the two
359  if (interaction.neutrino.iscc) {
360  weight *= _config.constantCCWeight;
361  }
362  else {
363  weight *= _config.constantNCWeight;
364  }
365  reco_interaction.weight = weight;
366 
367  // run selection
368  std::array<bool, NumuSelection::nCuts> selection = Select(ev, mctruth, i, intInfo);
369 
370  // pass iff pass each cut
371  bool pass_selection = std::find(selection.begin(), selection.end(), false) == selection.end();
372  if (pass_selection) {
373  // store interaction in reco tree
374  reco.push_back(reco_interaction);
375  // store local info
376  _interactionInfo->push_back(intInfo);
377 
378  _nu_count++;
379  selected = true;
380  }
381 
382  // fill histos
383  for (size_t select_i=0; select_i < selection.size(); select_i++) {
384  if (selection[select_i]) {
385  _root_histos[select_i].h_numu_trueE->Fill(interaction.neutrino.energy);
386  _root_histos[select_i].h_numu_ccqe->Fill(ECCQE(interaction.lepton.momentum, interaction.lepton.energy));
387  _root_histos[select_i].h_numu_visibleE->Fill(visible_energy);
388  _root_histos[select_i].h_numu_true_v_visibleE->Fill(visible_energy - interaction.neutrino.energy);
389  _root_histos[select_i].h_numu_t_length->Fill(intInfo.t_length);
390  _root_histos[select_i].h_numu_contained_L->Fill(intInfo.t_contained_length);
391  _root_histos[select_i].h_numu_t_is_muon->Fill(abs(intInfo.t_pdgid) == 13);
392  _root_histos[select_i].h_numu_t_is_contained->Fill(intInfo.t_is_contained);
393  _root_histos[select_i].h_numu_Vxy->Fill(nu.Nu().Vx(), nu.Nu().Vy());
394  _root_histos[select_i].h_numu_Vxz->Fill(nu.Nu().Vx(), nu.Nu().Vz());
395  _root_histos[select_i].h_numu_Vyz->Fill(nu.Nu().Vy(), nu.Nu().Vz());
396 
397  if (is_signal) {
398  _root_histos[select_i].h_numu_Vx_sig->Fill(nu.Nu().Vx());
399  _root_histos[select_i].h_numu_Vy_sig->Fill(nu.Nu().Vy());
400  _root_histos[select_i].h_numu_Vz_sig->Fill(nu.Nu().Vz());
401 
402  _root_histos[select_i].h_numu_t_is_muon_sig->Fill(abs(intInfo.t_pdgid) == 13);
403  }
404  else {
405  _root_histos[select_i].h_numu_Vx_bkg->Fill(nu.Nu().Vx());
406  _root_histos[select_i].h_numu_Vy_bkg->Fill(nu.Nu().Vy());
407  _root_histos[select_i].h_numu_Vz_bkg->Fill(nu.Nu().Vz());
408 
409  _root_histos[select_i].h_numu_t_is_muon_bkg->Fill(abs(intInfo.t_pdgid) == 13);
410  }
411 
412  // also update cut count
413  _cut_counts->SetPoint(select_i+1, select_i+1, _cut_counts->GetY()[select_i+1] + 1);
414  }
415  }
416  }
417 
418  return selected;
419 }
420 
421 // get information associated with track
423  double contained_length = 0;
424  double length = 0;
425  // If the interaction is outside the active volume, then g4 won't generate positions for the track.
426  // So size == 0 => outside FV
427  //
428  // If size != 0, then we have to check active volume
429  bool contained_in_AV = track.size() > 0;
430 
431  // Get the length and determine if any point leaves the active volume
432  //
433  // Use every trajectory point if configured and if the MCTrack has trajectory points
434  if (track.size() != 0 && _config.trajPointLength) {
435  TLorentzVector pos = track.Start().Position();
436  // get the active volume that the start position is in
437  int active_volume_index = -1;
438  // contruct pos Point
439  geoalgo::Point_t pos_point(pos);
440  for (int i = 0; i < _config.active_volumes.size(); i++) {
441  if (_config.active_volumes[i].Contain(pos_point)) {
442  active_volume_index = i;
443  }
444  }
445 
446  // only consider contained length in the active volume containing the interaction
447  std::vector<geoalgo::AABox> volumes;
448  if (active_volume_index >= 0) {
449  volumes.push_back(_config.active_volumes[active_volume_index]);
450  }
451 
452  for (int i = 1; i < track.size(); i++) {
453  // update if track is contained
454  if (contained_in_AV) contained_in_AV = containedInAV(pos.Vect());
455 
456  // update length
457  contained_length += containedLength(track[i].Position().Vect(), pos.Vect(), volumes);
458  length += (track[i].Position().Vect() - pos.Vect()).Mag();
459 
460  pos = track[i].Position();
461  }
462  }
463  // length calculation method used in proposal
464  else if (track.size() != 0 && !_config.trajPointLength) {
465  TLorentzVector pos = track.Start().Position();
466  // get the active volume that the start position is in
467  int active_volume_index = -1;
468  // contruct pos Point
469  geoalgo::Point_t pos_point(pos);
470  for (int i = 0; i < _config.active_volumes.size(); i++) {
471  if (_config.active_volumes[i].Contain(pos_point)) {
472  active_volume_index = i;
473  }
474  }
475  if (active_volume_index >= 0) {
476  // setup the "shaved" volume used in the proposal
477  geoalgo::AABox volume = shaveVolume(_config.active_volumes[active_volume_index], 5.);
478  if (volume.Contain(pos_point)) {
479  int i = 1;
480  TLorentzVector this_pos = pos;
481  for (; i < track.size(); i++) {
482  this_pos = track[i].Position();
483  geoalgo::Point_t p(this_pos.Vect());
484  if (!volume.Contain(p)) {
485  contained_in_AV = false;
486  break;
487  }
488  }
489  // Length of track is distance from start to last contained position
490  length = (pos.Vect() - this_pos.Vect()).Mag();
491  std::vector<geoalgo::AABox> volumes {volume};
492  contained_length = containedLength(pos.Vect(), this_pos.Vect(), volumes);
493  }
494  else contained_in_AV = false;
495  }
496  else contained_in_AV = false;
497 
498  }
499  // If active volume is misconfigured, then tracks may be generated w/out points.
500  // Optionally, we can accept them.
501  //
502  // Also, use this method if configured
503  else if (_config.acceptShakyTracks) {
504  contained_length = containedLength(track.Start().Position().Vect(), track.End().Position().Vect(), _config.active_volumes);
505  length = (track.Start().Position().Vect() - track.End().Position().Vect()).Mag();
506  contained_in_AV = containedInAV(track.Start().Position().Vect()) && containedInAV(track.End().Position().Vect());
507 
508  //std::cout << "WARNING: SHAKY TRACK." << std::endl;
509  //std::cout << "CONTAINED IN FV: " << contained_in_AV << std::endl;
510  //std::cout << "CONTAINED LENGTH: " << contained_length << std::endl;
511  //std::cout << "LENGTH: " << length << std::endl;
512  //
513  //TVector3 start = track.Start().Position().Vect();
514  //TVector3 end = track.End().Position().Vect();
515  //std::cout << "START: " << start.X() << " " << start.Y() << " " << start.Z() << std::endl;
516  //std::cout << "END: " << end.X() << " " << end.Y() << " " << end.Z() << std::endl;
517  }
518  // else {
519  // assert(false); //bad
520  // }
521  return NumuSelection::TrackInfo({contained_in_AV, contained_length, length});
522 }
523 
524 NumuSelection::NuMuInteraction NumuSelection::interactionInfo(const gallery::Event &ev, const simb::MCTruth &mctruth, VisibleEnergyCalculator &calculator) {
525  // get handle to tracks and showers
526  auto const& mctrack_list = \
527  *ev.getValidHandle<std::vector<sim::MCTrack> >(fMCTrackTag);
528  auto const& mcshower_list = \
529  *ev.getValidHandle<std::vector<sim::MCShower> >(fMCShowerTag);
530 
531  // print out track/shower info
532  if (_config.verbose) {
533  std::cout << "\n\nINTERACTION:\n";
534  std::cout << "MODE: " << mctruth.GetNeutrino().Mode() << std::endl;
535  std::cout << "CC: " << mctruth.GetNeutrino().CCNC() << std::endl;
536  std::cout << "\nTRACKS:\n";
537  for (auto const &mct: mctrack_list) {
538  std::cout << "TRACK:\n";
539  std::cout << "PDG: " << mct.PdgCode() << std::endl;
540  std::cout << "Vertex: " << isFromNuVertex(mctruth, mct) << std::endl;
541  std::cout << "Energy: " << mct.Start().E() << std::endl;
542  std::cout << "Kinetic: " << mct.Start().E() - PDGMass(mct.PdgCode()) << std::endl;
543  std::cout << "Length: " << (mct.Start().Position().Vect() - mct.End().Position().Vect()).Mag() << std::endl;
544  std::cout << "Process: " << mct.Process() << std::endl;
545  }
546  std::cout << "\nSHOWERS:\n";
547  for (auto const &mcs: mcshower_list) {
548  std::cout << "SHOWER:\n";
549  std::cout << "PDG: " << mcs.PdgCode() << std::endl;
550  std::cout << "Vertex: " << isFromNuVertex(mctruth, mcs) << std::endl;
551  std::cout << "Energy: " << mcs.Start().E() << std::endl;
552  std::cout << "Kinetic: " << mcs.Start().E() - PDGMass(mcs.PdgCode()) << std::endl;
553  std::cout << "Length: " << (mcs.Start().Position().Vect() - mcs.End().Position().Vect()).Mag() << std::endl;
554  std::cout << "Process: " << mcs.Process() << std::endl;
555  }
556  }
557 
558  // and particles
559  auto const& mcparticle_list = \
560  *ev.getValidHandle<std::vector<simb::MCParticle>>(fMCParticleTag);
561 
562  // Get the length and determine if any point leaves the active volume
563  //
564  // get lepton track
565  // if multiple, get the one with the highest energy
566  int track_ind = -1;
567  for (int i = 0; i < mctrack_list.size(); i++) {
568  if (isFromNuVertex(mctruth, mctrack_list[i]) && abs(mctrack_list[i].PdgCode()) == 13 && mctrack_list[i].Process() == "primary") {
569  if (track_ind == -1 || mctrack_list[track_ind].Start().E() < mctrack_list[i].Start().E()) {
570  track_ind = i;
571  }
572  }
573  }
574  // if there's no lepton, look for a pi+ that can "fake" a muon
575  // if there's multiple, get the one with the highest energy
576  if (track_ind == -1) {
577  double track_contained_length = -1;
578  for (int i = 0; i < mctrack_list.size(); i++) {
579  if (isFromNuVertex(mctruth, mctrack_list[i]) && abs(mctrack_list[i].PdgCode()) == 211 && mctrack_list[i].Process() == "primary") {
580  if (track_ind == -1 || mctrack_list[track_ind].Start().E() < mctrack_list[i].Start().E()) {
581  track_ind = i;
582  }
583  //double this_contained_length = trackInfo(mctrack_list[i]).t_contained_length;
584  //if (track_contained_length < 0 || this_contained_length > track_contained_length) {
585  // track_ind = i;
586  // track_contained_length = this_contained_length;
587  //}
588  }
589  }
590  }
591 
592  // if there's no track, return nonsense
593  if (track_ind == -1) {
594  // set calculator variables
595  calculator.lepton_contained = false;
596  calculator.lepton_contained_length = -1;
597  calculator.lepton_index = -1;
598  return NumuSelection::NuMuInteraction({false, -1, -1, -1, -1, -1, TVector3()});
599  }
600  // otherwise get the track info and energy info
601  else {
602  // get track info for our lepton
603  NumuSelection::TrackInfo t_info = trackInfo(mctrack_list[track_ind]);
604 
605  // set calculator variables
606  calculator.lepton_contained = t_info.t_is_contained;
607  calculator.lepton_contained_length = t_info.t_contained_length;
608  calculator.lepton_index = track_ind;
609 
610  // smear the energy
611  double smeared_energy = smearLeptonEnergy(_rand, mctrack_list[track_ind], calculator);
612  // truth kinetic energy
613  double truth_energy = (mctrack_list[track_ind].Start().E()) / 1000.; /* MeV -> GeV */
614  TVector3 momentum = mctrack_list[track_ind].Start().Momentum().Vect();
615  return NumuSelection::NuMuInteraction({t_info.t_is_contained, t_info.t_contained_length, t_info.t_length, mctrack_list[track_ind].PdgCode(), truth_energy, smeared_energy, momentum});
616  }
617 }
618 
619 std::array<bool, NumuSelection::nCuts> NumuSelection::Select(const gallery::Event& ev, const simb::MCTruth& mctruth,
620  unsigned truth_ind, const NumuSelection::NuMuInteraction &intInfo) {
621  // get the neutrino
622  const simb::MCNeutrino& nu = mctruth.GetNeutrino();
623 
624  // has valid track
625  bool pass_valid_track = intInfo.t_pdgid != -1;
626 
627  // pass fiducial volume cut
628  bool pass_FV = passFV(nu.Nu().Position().Vect());
629 
630  // min length cut
631  bool pass_min_length = passMinLength(intInfo.t_contained_length, intInfo.t_is_contained);
632 
633  // pass vertex reconstruction cut
634  bool pass_reco_vertex = true;
635  if (_config.vertexDistanceCut > 0) {
636  double truth_v[3];
637  truth_v[0] = nu.Nu().Vx();
638  truth_v[1] = nu.Nu().Vy();
639  truth_v[2] = nu.Nu().Vz();
640 
641  // get the reco vertex information
642  auto const pfp_handle = ev.getValidHandle<std::vector<recob::PFParticle>>("pandoraNu");
643  art::FindMany<recob::Vertex> fvtx(pfp_handle, ev, "pandoraNu");
644  // index of truth info is same as index of vertex info
645  std::vector<const recob::Vertex*> vertices = fvtx.at(truth_ind);
646  // neutrino will only have one associated vetex
647  auto vertex = vertices[0]->position();
648  TVector3 reco_v(vertex.X(), vertex.Y(), vertex.Z());
649 
650  pass_reco_vertex = passRecoVertex(nu.Nu().Position().Vect(), reco_v);
651  }
652 
653  // print selection information
654  if (_config.verbose) {
655  std::cout << "NEW EVENT" << std::endl;
656  std::cout << "CCNC: " << nu.CCNC() << " MODE: " << nu.Mode() << " PDG: " << nu.Nu().PdgCode() << std::endl;
657  std::cout << "Track PDG: " << intInfo.t_pdgid <<std::endl;
658  std::cout << "pass Valid Track: " << pass_valid_track << std::endl;
659  std::cout << "Pos: " << nu.Nu().Vx() << " " << nu.Nu().Vy() << " " << nu.Nu().Vz() << std::endl;
660  std::cout << "pass FV: " << pass_FV << std::endl;
661  std::cout << "pass Reco: " << pass_reco_vertex << std::endl;
662  std::cout << "Length: " << intInfo.t_contained_length << " Contained: " << intInfo.t_is_contained << std::endl;
663  std::cout << "pass Length: " << pass_min_length << std::endl;
664  }
665 
666  // TEMP: add in an active volume cut
667  bool pass_AV = false;
668  geoalgo::Point_t interaction(nu.Nu().Position().Vect());
669  for (auto const& AV: _config.active_volumes) {
670  if (AV.Contain(interaction)) pass_AV = true;
671  }
672 
673  // STUDY KMEC: remove MEC events
674  bool pass_kMEC = !(_config.cutKMEC && nu.Mode() == simb::kMEC) && !(_config.onlyKMEC && nu.Mode() != simb::kMEC);
675  // select another mode if necessary
676  bool pass_Mode = _config.selectMode < 0 || nu.Mode() == _config.selectMode;
677  // maybe require cc or nc
678  bool pass_CCNC = _config.selectCCNC < 0 || nu.CCNC() == _config.selectCCNC;
679  pass_kMEC = pass_kMEC && pass_Mode && pass_CCNC;
680 
681  // retrun list of cuts
682  return {pass_kMEC, pass_AV && pass_kMEC, pass_valid_track && pass_kMEC && pass_AV, pass_valid_track && pass_kMEC && pass_FV, pass_valid_track && pass_kMEC && pass_FV && pass_min_length};
683 }
684 
685 bool NumuSelection::containedInAV(const TVector3 &v) {
686  geoalgo::Point_t p(v);
687  for (auto const& AV: _config.active_volumes) {
688  if (AV.Contain(p)) return true;
689  }
690  return false;
691 }
692 
693 bool NumuSelection::containedInFV(const TVector3 &v) {
694  geoalgo::Point_t p(v);
695  for (auto const& FV: _config.fiducial_volumes) {
696  if (FV.Contain(p)) return true;
697  }
698  return false;
699 }
700 
701 bool NumuSelection::passRecoVertex(const TVector3 &truth_v, const TVector3 &reco_v) {
702  if (_config.vertexDistanceCut < 0) return true;
703 
704  return (truth_v - reco_v).Mag() < _config.vertexDistanceCut;
705 }
706 
707 bool NumuSelection::passMinLength(double length, bool stop_in_tpc) {
708  bool pass_stopped = _config.minLengthContainedTrack < 0 || length > _config.minLengthContainedTrack;
709  bool pass_exiting = _config.minLengthExitingTrack < 0 || length > _config.minLengthExitingTrack;
710  if (!stop_in_tpc)
711  return pass_stopped && pass_exiting;
712  else
713  return pass_stopped;
714 }
715 
716  } // namespace SBNOsc
717 } // namespace ana
718 
719 
721 
TH1D * h_numu_t_is_muon_bkg
histogram of whether associated track is a muon
process_name vertex
Definition: cheaterreco.fcl:51
std::vector< NuMuInteraction > * _interactionInfo
Branch holder.
bool doFVCut
Whether to apply fiducial volume cut.
Definition: NumuSelection.h:91
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
double showerEnergyDistortion
Energy distortion of showers for visible energy calculation (%).
TrackInfo trackInfo(const sim::MCTrack &track)
TGraph * _cut_counts
Keep track of neutrinos per cut.
int lepton_index
Index of lepton in the mctrack object.
double constantEnergyScale
constant scale to apply to reco_energy calculation
double track_energy_distortion
Distortion of energies of tracks (%).
double visibleEnergyProposal(TRandom &rand, const simb::MCTruth &mctruth, const std::vector< sim::MCTrack > &mctrack_list, const VisibleEnergyCalculator &calculator)
TH1D * h_numu_contained_L
histogram w/ FV contained length of track in CC event [cm]
TH1D * h_numu_t_length
histogram w/ total length of associated track [cm]
TVector3 momentum
Three-momentum.
Definition: Event.hh:129
double t_length
total length of (maybe faked) lepton track [cm]
float energy
Energy.
Definition: Event.hh:128
bool containedInAV(const TVector3 &v)
double lepton_energy_distortion_leaving_A
Parameter in function to calculate primary lepton energy resolution.
double trackVisibleEnergyThreshold
Energy threshold for track to be acounted in visible energy calculation [GeV].
art::InputTag fTruthTag
art tag for MCTruth information
FinalStateParticle lepton
The primary final state lepton.
Definition: Event.hh:153
TH1D * h_numu_ccqe
histogram w/ CCQE energy veriable [GeV]
TH2D * h_numu_Vxy
2D x-y vertex histogram [cm]
bool isFromNuVertex(const simb::MCTruth &mc, const simb::MCParticle &mcp, float distance)
pdgs p
Definition: selectors.fcl:22
bool verbose
Whether to print out info associated w/ selection.
Definition: NumuSelection.h:95
TTree * fTree
The output ROOT tree.
Representation of a 3D rectangular box which sides are aligned w/ coordinate axis. A representation of an Axis-Aligned-Boundary-Box, a simple &amp; popular representation of 3D boundary box for collision detection. The concept was taken from the reference, Real-Time-Collision-Detection (RTCD), and in particular Ch. 4.2 (page 77): .
TH1D * h_numu_t_is_muon
histogram of whether associated track is a muon
TFile * fOutputFile
The output ROOT file.
Neutrino neutrino
The neutrino.
Definition: Event.hh:152
double backgroundRejection
Rejection applied to background (NC) events.
bool cutKMEC
Whether to remove MEC events (useful for studying difference w.r.t. proposal)
bool passFV(const TVector3 &v)
double lepton_energy_distortion_contained
Distortion of energies of primary lepton whose tracks are contained within the TPC (%)...
std::vector< geoalgo::AABox > fiducial_volumes
List of FV containers – set by &quot;fiducial_volumes&quot;.
Definition: NumuSelection.h:92
process_name use argoneut_mc_hitfinder track
bool passRecoVertex(const TVector3 &truth_v, const TVector3 &reco_v)
process_name opflashCryoW ana
Config _config
The config.
bool iscc
CC (true) or NC/interference (false)
Definition: Event.hh:75
const MCStep & End() const
Definition: MCTrack.h:45
TH1D * h_numu_t_is_muon_sig
histogram of whether associated track is a muon
bool onlyKMEC
Whether to remove all non-MEC events.
const Point_t & Min() const
Minimum point getter.
double constantNCWeight
constant weight to apply to each NC event
Electron neutrino event selection.
Definition: NumuSelection.h:44
void Initialize(fhicl::ParameterSet *config=NULL)
double t_length
total length of (maybe faked) lepton track [cm]
Definition: NumuSelection.h:72
std::map< std::string, double > _eventCategories
double leptonEnergyDistortionLeavingB
Parameter to be used in the energy distortion of primary lepton for visible energy calculation...
int t_pdgid
PDGID of primary track (muon or pi+)
Definition: NumuSelection.h:73
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
double leptonEnergyDistortionLeavingA
Parameter to be used in the energy distortion of primary lepton for visible energy calculation...
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
double minLengthContainedTrack
Minimum length [cm] of contained tracks. Will not apply cut if value is negative. ...
Definition: NumuSelection.h:98
T abs(T value)
double lepton_energy_distortion_leaving_B
Parameter in function to calculate primary lepton energy resolution.
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
double aaBoxesMin(const std::vector< geoalgo::AABox > &boxes, unsigned dim)
process_name standard_reco_uboone reco
bool Contain(const Point_t &pt) const
Test if a point is contained within the box.
double t_contained_length
the length of the (maybe faked) lepton track contained in the active volume [cm]
Definition: NumuSelection.h:71
double smearLeptonEnergy(TRandom &rand, const sim::MCTrack &mct, const VisibleEnergyCalculator &calculator)
double constantCCWeight
constant weight to apply to each CC event
float weight
Selection-defined event weight.
Definition: Event.hh:196
const char mode
Definition: noise_ana.cxx:20
std::vector< std::string > uniformWeights
Weights taken from &quot;EventWeight&quot; that should be applied to the weight of each event.
TRandomMT64 _rand
random number generation
bool ProcessEvent(const gallery::Event &ev, const std::vector< event::Interaction > &truth, std::vector< event::RecoInteraction > &reco)
std::array< bool, nCuts > Select(const gallery::Event &ev, const simb::MCTruth &mctruth, unsigned truth_ind, const NumuSelection::NuMuInteraction &intInfo)
#define DECLARE_SBN_PROCESSOR(classname)
art::InputTag fMCShowerTag
art tag for MCShower
double minLengthExitingTrack
Minimum length [cm] of exiting tracks. Will not apply cut if value is negative.
Definition: NumuSelection.h:99
TH1D * h_numu_trueE
histogram w/ truth energy variable [GeV]
double track_threshold
Energy threshold of track energy counted in calculation [GeV].
TH1D * h_numu_true_v_visibleE
histogram w/ difference of visible and truth energy [GeV]
Provides recob::Track data product.
unsigned _nu_count
Count selected events.
double constantWeight
constant weight to apply uniformly to each event
RootHistos _root_histos[nCuts]
Histos (one group per cut)
double aaBoxesMax(const std::vector< geoalgo::AABox > &boxes, unsigned dim)
unsigned _event_counter
Count processed events.
double shower_energy_distortion
Distortion of energies of showers (%).
TH1D * h_numu_visibleE
histogram w/ visible energy variable (total muon momentum + kinetic hadron energy) [GeV] ...
TH2D * h_numu_Vxz
2D x-z vertex histogram [cm]
double ECCQE(const TVector3 &l_momentum, double l_energy, double energy_distortion, double angle_distortion)
bool trajPointLength
Whether to use trajectory points to calculate length.
Definition: NumuSelection.h:97
std::vector< geoalgo::AABox > active_volumes
List of active volumes.
Definition: NumuSelection.h:93
double containedLength(const TVector3 &v0, const TVector3 &v1, const std::vector< geoalgo::AABox > &boxes)
float energy
Neutrino energy (GeV)
Definition: Event.hh:90
double t_contained_length
the length of the (maybe faked) lepton track contained in the active volume [cm]
double trackEnergyDistortion
Energy distortion of tracks for visible energy calculation (%).
double lepton_contained_length
Length of section of primary lepton&#39;s track that is contained within the TPC.
const Point_t & Max() const
Maximum point getter.
art::InputTag fMCParticleTag
art tag for MCParticle
geoalgo::AABox shaveVolume(const geoalgo::AABox &select_volume, double delta)
int lepton_pdgid
PDGID of lepton in the interaction. Used to add.
const MCStep & Start() const
Definition: MCTrack.h:44
bool t_is_contained
whether the (maybe faked) lepton track is totally contained in the active volume
Definition: NumuSelection.h:70
double selectionEfficiency
Signal efficiency weight applied to signal (charged current) events.
static const std::array< std::string, nCuts > cutNames()
TH1D * h_numu_t_is_contained
histogram w/ whether associated track is contained in AV
const TLorentzVector & Position() const
Definition: MCStep.h:40
bool acceptShakyTracks
Whether to calculate length of tracks that don&#39;t have all points generated.
Definition: NumuSelection.h:96
double vertexDistanceCut
Value of max distance [cm] between truth and reconstructed vertex. Will not apply cut if value is neg...
Definition: NumuSelection.h:94
art::InputTag fMCTrackTag
art tag for MCTrack
bool t_is_contained
whether the (maybe faked) lepton track is totally contained in the active volume
bool containedInFV(const TVector3 &v)
BEGIN_PROLOG SN nu
NuMuInteraction interactionInfo(const gallery::Event &ev, const simb::MCTruth &mctruth, VisibleEnergyCalculator &calculator)
static const unsigned nCuts
number of cuts
TH2D * h_numu_Vyz
2D y-z vertex histogram [cm]
All truth information associated with one neutrino interaction.
Definition: Event.hh:150
BEGIN_PROLOG could also be cout
bool lepton_contained
True if primary lepton&#39;s track is contained within TPC.
std::map< std::string, std::vector< float > > weights
Definition: Event.hh:164
bool passMinLength(double length, bool stop_in_tpc)