AssignLabels.cxx
Go to the documentation of this file.
2 
8 
11 
12 #include <iostream>
13 #include <iomanip>
14 #include <limits>
15 
16 namespace cvn
17 {
18  /// Default constructor
20  : nProton(0), nPion(0), nPizero(0), nNeutron(0),
21  pdgCode(0), tauMode(0)
22  {}
23 
24  /// Get Interaction_t from pdg, mode and iscc.
25  /// Setting pdg and mode to zero triggers cosmic ray
27  {
28 
29  //if(truth->NeutrinoSet())
30  //{
31  int pdg = truth.Nu().PdgCode();
32  bool iscc = truth.CCNC() == simb::kCC;
33  int trueMode = truth.Mode();
34 
35  if(iscc)
36  {
37  if(abs(pdg) == 14)
38  {
39  switch(trueMode){
40  case simb::kQE: return kNumuQE; break;
41  case simb::kRes: return kNumuRes; break;
42  case simb::kDIS: return kNumuDIS; break;
43  default: return kNumuOther;
44  }
45  }
46  else if(abs(pdg) == 12)
47  {
48  switch(trueMode){
49  case simb::kQE: return kNueQE; break;
50  case simb::kRes: return kNueRes; break;
51  case simb::kDIS: return kNueDIS; break;
52  default: return kNueOther;
53  }
54  }
55  else if(abs(pdg) == 16)
56  {
57  switch(trueMode){
58  case simb::kQE: return kNutauQE; break;
59  case simb::kRes: return kNutauRes; break;
60  case simb::kDIS: return kNutauDIS; break;
61  default: return kNutauOther;
62  }
63  }
64  }
65  else if(trueMode==simb::kNuElectronElastic){
66  return kNuElectronElastic;
67  }
68  else return kNC;
69  //}
70  //else return kCosmic;
71 
72  return kOther;
73  }
74 
76  {
77 
78  if(iscc){
79 
80  if(abs(pdg) == 14){
81  switch(trueMode){
82  case simb::kQE: return kNumuQE; break;
83  case simb::kRes: return kNumuRes; break;
84  case simb::kDIS: return kNumuDIS; break;
85  default: return kNumuOther;
86  }
87  }
88  else if(abs(pdg) == 12){
89  switch(trueMode){
90  case simb::kQE: return kNueQE; break;
91  case simb::kRes: return kNueRes; break;
92  case simb::kDIS: return kNueDIS; break;
93  default: return kNueOther;
94  }
95  }
96  else if(abs(pdg) == 16){
97  switch(trueMode){
98  case simb::kQE: return kNutauQE; break;
99  case simb::kRes: return kNutauRes; break;
100  case simb::kDIS: return kNutauDIS; break;
101  default: return kNutauOther;
102  }
103  }
104 
105  }
106  else if(trueMode==simb::kNuElectronElastic){
107  return kNuElectronElastic;
108  }
109  else return kNC;
110 
111  return kOther;
112  }
113 
114  // This function uses purely the information from the neutrino generator to
115  // find all of the final-state particles that contribute to the event.
116  void AssignLabels::GetTopology(const art::Ptr<simb::MCTruth> truth, unsigned int nTopologyHits = 0){
117 
118  const simb::MCNeutrino &nu = truth->GetNeutrino();
119 
120  // Get neutrino flavour
121  if(nu.CCNC() == simb::kCC){
122  pdgCode = nu.Nu().PdgCode();
123  }
124  else{
125  pdgCode = 1;
126  }
127 
128  // Get tau topology, if necessary
129  tauMode = kNotNutau;
130  if (abs(pdgCode) == 16) {
131  tauMode = kNutauHad;
132  for (int p = 0; p < truth->NParticles(); ++p) {
133  if (truth->GetParticle(p).StatusCode() != 1) continue;
134  int pdg = abs(truth->GetParticle(p).PdgCode());
135  int parent = truth->GetParticle(p).Mother();
136  while (parent > 0) parent = truth->GetParticle(parent).Mother();
137 
138  if (parent == 0) {
139  if (pdg == 11) {
140  tauMode = kNutauE;
141  break;
142  } else if (pdg == 13) {
143  tauMode = kNutauMu;
144  break;
145  }
146  }
147  }
148  }
149 
150 // std::cout << "Neutrino PDG code is " << pdgCode
151 // << ", tau interaction type is " << tauMode << std::endl;
152 
153  // Now we need to do some final state particle counting.
154 // unsigned int nParticle = truth.NParticles();
155 
156  nProton = 0;
157  nPion = 0; // Charged pions, that is
158  nPizero = 0;
159  nNeutron = 0;
160 
161  // We need an instance of the backtracker to find the number of simulated hits for each track
164 
165  // Loop over all of the particles
166 // for(unsigned int p = 0; p < nParticle; ++p){
167  for(auto const thisPart : partService->MCTruthToParticles_Ps(truth)){
168 
169 // const simb::MCParticle& part = truth.GetParticle(p);
170  const simb::MCParticle& part = *thisPart;
171 
172  int pdg = part.PdgCode();
173 
174  // Make sure this is a final state particle
175  if(part.StatusCode() != 1){
176  continue;
177  }
178 
179  // Make sure this particle is a daughter of the neutrino
180  if(part.Mother() != 0){
181  continue;
182  }
183 
184  // GENIE has some fake particles for energy conservation - eg nuclear binding energy. Ignore these
185  if(pdg > 2000000000){
186  continue;
187  }
188 
189  // Also don't care about nuclear recoils
190  if(pdg > 1000000){
191  continue;
192  }
193 
194  // Find how many SimIDEs the track has
195  unsigned int nSimIDE = backTrack->TrackIdToSimIDEs_Ps(part.TrackId()).size();
196 
197  // Check if we have more than 100 MeV of kinetic energy
198  // float ke = part.E() - part.Mass();
199  // if( ke < 0.0){
200  // continue;
201  // }
202 
203  // Special case for pi-zeros since it is the decay photons and their pair produced electrons that deposit energy
204  if(pdg == 111 || pdg == 2112){
205 // unsigned int nDummyHits = GetNeutralDaughterHitsRecursive(part);
206 // std::cout << "New method of neutral daughters for " << pdg << " = " << nDummyHits << std::endl;
207  // Decay photons
208  for(int d = 0; d < part.NumberDaughters(); ++d){
209  nSimIDE += backTrack->TrackIdToSimIDEs_Ps(part.Daughter(d)).size();
210  }
211 // std::cout << "Old method of neutral daughters for " << pdg << " = " << nSimIDE << std::endl;
212  }
213 
214  // Do we pass the number of hits cut?
215  if(nSimIDE < nTopologyHits){
216  continue;
217  }
218 
219 // std::cout << "Final state particle " << pdg << " with ke " << ke << " GeV, " << nSimIDE << " true hits and " << part.NumberDaughters() << " daughters" << std::endl;
220 
221  switch(abs(pdg)){
222  case 111 : ++nPizero; break;
223  case 211 : ++nPion; break;
224  case 2112: ++nNeutron; break;
225  case 2212: ++nProton; break;
226  default : break;
227  }
228 
229  }
230 
231  // Assign the enums based on the counters
232  // switch(nProton){
233  // case 0 : top = static_cast<cvn::TopologyType>(top | kTop0proton); break;
234  // case 1 : top = static_cast<cvn::TopologyType>(top | kTop1proton); break;
235  // case 2 : top = static_cast<cvn::TopologyType>(top | kTop2proton); break;
236  // default : top = static_cast<cvn::TopologyType>(top | kTopNproton); break;
237  // }
238 
239  // switch(nPion){
240  // case 0 : top = static_cast<cvn::TopologyType>(top | kTop0pion); break;
241  // case 1 : top = static_cast<cvn::TopologyType>(top | kTop1pion); break;
242  // case 2 : top = static_cast<cvn::TopologyType>(top | kTop2pion); break;
243  // default : top = static_cast<cvn::TopologyType>(top | kTopNpion); break;
244  // }
245 
246  // switch(nPizero){
247  // case 0 : top = static_cast<cvn::TopologyType>(top | kTop0pizero); break;
248  // case 1 : top = static_cast<cvn::TopologyType>(top | kTop1pizero); break;
249  // case 2 : top = static_cast<cvn::TopologyType>(top | kTop2pizero); break;
250  // default : top = static_cast<cvn::TopologyType>(top | kTopNpizero); break;
251  // }
252 
253  // switch(nNeutron){
254  // case 0 : top = static_cast<cvn::TopologyType>(top | kTop0neutron); break;
255  // case 1 : top = static_cast<cvn::TopologyType>(top | kTop1neutron); break;
256  // case 2 : top = static_cast<cvn::TopologyType>(top | kTop2neutron); break;
257  // default : top = static_cast<cvn::TopologyType>(top | kTopNneutron); break;
258  // }
259 
260  std::cout << "Particle counts: " << nProton << ", " << nPion << ", " << nPizero << ", " << nNeutron << std::endl;
261 
262  // return top;
263 
264  }
265 
267 
268  std::cout << "== Topology Information ==" << std::endl;
269 
270  std::cout << " - Neutrino PDG code = " << pdgCode << std::endl;
271 
272  std::cout << " - Number of protons (3 means >2) = " << nProton << std::endl;
273 
274  std::cout << " - Number of charged pions (3 means >2) = " << nPion << std::endl;
275 
276  std::cout << " - Number of pizeros (3 means >2) = " << nPizero << std::endl;
277 
278  std::cout << " - Number of neutrons (3 means >2) = " << nNeutron << std::endl;
279 
280  std::cout << " - Topology type is " << GetTopologyType() << std::endl;
281 
282  std::cout << " - Alternate topology type is " << GetTopologyTypeAlt() << std::endl;
283 
284  }
285 
287 
288  if (pdgCode < 0) return true;
289  else return false;
290 
291  }
292 
293  unsigned short AssignLabels::GetTopologyType() {
294 
295  if (abs(pdgCode) == 12) return kTopNue;
296  if (abs(pdgCode) == 14) return kTopNumu;
297  if (abs(pdgCode) == 16) {
298  if (tauMode == kNutauE) return kTopNutauE;
299  if (tauMode == kNutauMu) return kTopNutauMu;
300  if (tauMode == kNutauHad) return kTopNutauHad;
301  }
302  if (pdgCode == 1) return kTopNC;
303  throw std::runtime_error("Topology type not recognised!");
304  }
305 
307 
308  if (abs(pdgCode) == 12) return kTopNueLike;
309  if (abs(pdgCode) == 14) return kTopNumuLike;
310  if (abs(pdgCode) == 16) {
311  if (tauMode == kNutauE) return kTopNueLike;
312  if (tauMode == kNutauMu) return kTopNumuLike;
313  if (tauMode == kNutauHad) return kTopNutauLike;
314  }
315  if (pdgCode == 1) return kTopNCLike;
316  throw std::runtime_error("Topology type not recognised!");
317  }
318 
319  // Get the beam interaction mode for ProtoDUNE specific code
320  unsigned short AssignLabels::GetProtoDUNEBeamInteractionType(const simb::MCParticle &particle) const {
321 
322  unsigned short baseProcess = std::numeric_limits<unsigned short>::max();
323 
324  // The first thing we can do is look at the process key
325  std::string processName = particle.EndProcess();
326 
327  if(GetProcessKey(processName) > -1){
328  // Base process gives us a value from 0 to 44
329  baseProcess = static_cast<unsigned int>(GetProcessKey(processName));
330  }
331 
332  std::cout << "What interaction type, then? " << processName << std::endl;
333 
334  // In the case that we have an inelastic interaction, maybe we can do more.
336 
337  unsigned int nPi0 = 0; // Pi-zeros
338  unsigned int nPiM = 0; // Pi-minuses
339  unsigned int nPiP = 0; // Pi-pluses
340  unsigned int nNeu = 0; // Neutrons
341  unsigned int nPro = 0; // Protons
342  unsigned int nOth = 0; // Everything else
343 
344  for(int i = 0; i < particle.NumberDaughters(); ++i){
345  const simb::MCParticle* daughter = piService->TrackIdToParticle_P(particle.Daughter(i));
346  switch(daughter->PdgCode()){
347  case 111 : ++nPi0; break;
348  case -211 : ++nPiM; break;
349  case 211 : ++nPiP; break;
350  case 2112 : ++nNeu; break;
351  case 2212 : ++nPro; break;
352  default : ++nOth; break;
353  }
354  }
355 
356  std::cout << "Base process = " << baseProcess << std::endl;
357  std::cout << "Daughters = " << nPi0 << " pi0s, " << nPiM << " pi-s, "
358  << nPiP << " pi+s, " << nNeu << " neutrons, "
359  << nPro << " protons and " << nOth << " other particles." << std::endl;
360 
361  // If we have a pion with a pi0 in the final state we can flag it as charge exchange
362  if(abs(particle.PdgCode()) == 211 && nPi0 == 1){
363  return 45; // First free value after those from the truth utility
364  }
365  else{
366  return baseProcess;
367  }
368  }
369 
370 // Get process key.
372 
373  if(process.compare("primary") == 0) return 0;
374  else if(process.compare("hadElastic") == 0) return 1;
375  else if(process.compare("pi-Inelastic") == 0) return 2;
376  else if(process.compare("pi+Inelastic") == 0) return 3;
377  else if(process.compare("kaon-Inelastic") == 0) return 4;
378  else if(process.compare("kaon+Inelastic") == 0) return 5;
379  else if(process.compare("protonInelastic") == 0) return 6;
380  else if(process.compare("neutronInelastic") == 0) return 7;
381  else if(process.compare("kaon0SInelastic") == 0) return 8;
382  else if(process.compare("kaon0LInelastic") == 0) return 9;
383  else if(process.compare("lambdaInelastic") == 0) return 10;
384  else if(process.compare("omega-Inelastic") == 0) return 11;
385  else if(process.compare("sigma+Inelastic") == 0) return 12;
386  else if(process.compare("sigma-Inelastic") == 0) return 13;
387  else if(process.compare("sigma0Inelastic") == 0) return 14;
388  else if(process.compare("xi-Inelastic") == 0) return 15;
389  else if(process.compare("xi0Inelastic") == 0) return 16;
390  else if(process.compare("anti_protonInelastic") == 0) return 20;
391  else if(process.compare("anti_neutronInelastic") == 0) return 21;
392  else if(process.compare("anti_lambdaInelastic") == 0) return 22;
393  else if(process.compare("anti_omega-Inelastic") == 0) return 23;
394  else if(process.compare("anti_sigma+Inelastic") == 0) return 24;
395  else if(process.compare("anti_sigma-Inelastic") == 0) return 25;
396  else if(process.compare("anti_xi-Inelastic") == 0) return 26;
397  else if(process.compare("anti_xi0Inelastic") == 0) return 27;
398 
399  else if(process.compare("Decay") == 0) return 30;
400  else if(process.compare("FastScintillation") == 0) return 31;
401  else if(process.compare("nKiller") == 0) return 32; // Remove unwanted neutrons: neutron kinetic energy threshold (default 0) or time limit for neutron track
402  else if(process.compare("nCapture") == 0) return 33; // Neutron capture
403 
404  else if(process.compare("compt") == 0) return 40; // Compton Scattering
405  else if(process.compare("rayleigh") == 0) return 41; // Rayleigh Scattering
406  else if(process.compare("phot") == 0) return 42; // Photoelectric Effect
407  else if(process.compare("conv") == 0) return 43; // Pair production
408  else if(process.compare("CoupledTransportation") == 0) return 44; //
409 
410  else return -1;
411 }
412 
413  // Recursive function to get all hits from daughters of a given neutral particle
415 
416  unsigned int nSimIDEs = 0;
417 
418  // The backtrack and particle inventory service will be useful here
421 
422  for(int d = 0; d < particle.NumberDaughters(); ++d){
423 
424  const simb::MCParticle *daughter = partService->TrackIdToParticle_P(particle.Daughter(d));
425  unsigned int localSimIDEs = backTrack->TrackIdToSimIDEs_Ps(daughter->TrackId()).size();
426  std::cout << "Got " << localSimIDEs << " hits from " << daughter->PdgCode() << std::endl;
427  if(localSimIDEs == 0) localSimIDEs = GetNeutralDaughterHitsRecursive(*daughter);
428 
429  nSimIDEs += localSimIDEs;
430  }
431 
432  return nSimIDEs;
433  }
434 
435 }
436 
437 
AssignLabels()
Default constructor.
Nue CC QE interaction.
Nue CC DIS interaction.
int PdgCode() const
Definition: MCParticle.h:212
int CCNC() const
Definition: MCNeutrino.h:148
const simb::MCNeutrino & GetNeutrino() const
Definition: MCTruth.h:77
NC Nu On E Scattering.
Nutau CC, other than above.
neutrino electron elastic scatter
Definition: MCNeutrino.h:140
std::string string
Definition: nybbler.cc:12
Nutau CC DIS interaction.
const simb::MCParticle * TrackIdToParticle_P(int id) const
int Mother() const
Definition: MCParticle.h:213
const simb::MCParticle & Nu() const
Definition: MCNeutrino.h:146
Nutau CC Resonant interaction.
std::vector< const simb::MCParticle * > MCTruthToParticles_Ps(art::Ptr< simb::MCTruth > const &mct) const
std::vector< const sim::IDE * > TrackIdToSimIDEs_Ps(int const &id) const
enum cvn::Interaction InteractionType
int StatusCode() const
Definition: MCParticle.h:211
unsigned short GetTopologyType()
int NParticles() const
Definition: MCTruth.h:75
unsigned int GetNeutralDaughterHitsRecursive(const simb::MCParticle &particle) const
Utility class for truth labels.
Particle class.
InteractionType GetInteractionType(simb::MCNeutrino &truth)
int NumberDaughters() const
Definition: MCParticle.h:217
int TrackId() const
Definition: MCParticle.h:210
int Daughter(const int i) const
Definition: MCParticle.cxx:112
unsigned short GetTopologyTypeAlt()
InteractionType GetInteractionTypeFromSlice(int nuPDG, bool nuCCNC, int nuMode)
unsigned short nPizero
Definition: AssignLabels.h:57
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
def process(f, kind)
Definition: search.py:254
Nue CC Resonant interaction.
T abs(T value)
void GetTopology(const art::Ptr< simb::MCTruth > truth, unsigned int nTopologyHits)
std::string EndProcess() const
Definition: MCParticle.h:216
Nue CC, other than above.
NC interaction.
unsigned short GetProtoDUNEBeamInteractionType(const simb::MCParticle &particle) const
p
Definition: test.py:223
unsigned short tauMode
Definition: AssignLabels.h:60
static int max(int a, int b)
Numu CC Resonant interaction.
const simb::MCParticle & GetParticle(int i) const
Definition: MCTruth.h:76
Something else. Tau? Hopefully we don&#39;t use this.
Numu CC QE interaction.
Nutau CC QE interaction.
unsigned short nPion
Definition: AssignLabels.h:56
Numu CC, other than above.
int GetProcessKey(std::string process) const
Numu CC DIS interaction.
Event generator information.
Definition: MCNeutrino.h:18
unsigned short nNeutron
Definition: AssignLabels.h:58
int Mode() const
Definition: MCNeutrino.h:149
def parent(G, child, parent_type)
Definition: graph.py:67
unsigned short nProton
Definition: AssignLabels.h:55
QTextStream & endl(QTextStream &s)