Belle II Software  release-08-01-10
TauDecayModeModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <analysis/modules/TauDecayMode/TauDecayModeModule.h>
10 #include <framework/datastore/StoreArray.h>
11 #include <framework/datastore/StoreObjPtr.h>
12 #include <framework/logging/Logger.h>
13 #include <framework/particledb/EvtGenDatabasePDG.h>
14 #include <iostream>
15 #include <vector>
16 #include <algorithm>
17 #include <TParticlePDG.h>
18 #include <map>
19 #include <fstream>
20 #include <set>
21 #include <Math/LorentzRotation.h>
22 #include <Math/Boost.h>
23 using namespace std;
24 using namespace Belle2;
25 
26 std::map<std::string, int> make_map(const std::string& file, int chg)
27 {
28  std::string fileName;
29  if (file == "") {
30  if (chg < 0) {
31  B2INFO("Missing input mapping file: use mp_file_minus=basf2.find_file('data/analysis/modules/TauDecayMode/map_tauminus.txt') TauDecayMode.param('file_minus', mp_file_minus) to classify with default mapping.");
32  } else {
33  B2INFO("Missing input mapping file: use mp_file_plus=basf2.find_file('data/analysis/modules/TauDecayMode/map_tauplus.txt') TauDecayMode.param('file_plus', mp_file_plus) to classify with default mapping.");
34  }
35  } else {
36  fileName = file;
37  }
38 
39  ifstream f;
40  f.open(fileName);
41  std::string line;
42  std::string key;
43  int value;
44  std::map <std::string, int> map_tau;
45  while (f.good()) {
46  getline(f, line);
47  istringstream ss(line);
48  ss >> key >> value;
49  map_tau[key] = value;
50  }
51  f.close();
52  return map_tau;
53 }
54 
55 //-----------------------------------------------------------------
56 // Register the Module
57 //-----------------------------------------------------------------
58 REG_MODULE(TauDecayMode);
59 //-----------------------------------------------------------------
60 // Implementation
61 //-----------------------------------------------------------------
62 
63 TauDecayModeModule::TauDecayModeModule() : Module(), m_taum_no(0), m_taup_no(0), m_mmode(-2), m_pmode(-2),
64  m_mprong(0), m_pprong(0), m_megstar(0), m_pegstar(0),
65  tauPair(false), numOfTauMinus(0), numOfTauPlus(0), idOfTauMinus(-1), idOfTauPlus(-1),
66  m_isEtaPizPizPizFromTauMinus(false), m_isEtaPizPizPizFromTauPlus(false),
67  m_isOmegaPimPipFromTauMinus(false), m_isOmegaPimPipFromTauPlus(false)
68 {
69  // Set module properties
70  setDescription("Module to identify generated tau pair decays, using MCParticle information."
71  "By default, each tau decay is numbered as TauolaBelle2DecayMode [Ref: BELLE2-NOTE-PH-2020-055]");
72  //Parameter definition
73  addParam("printmode", m_printmode, "Printout more information from each event", std::string("default"));
74  addParam("file_minus", m_file_minus, "Path for an alternative mapping for tau- decays", std::string(""));
75  addParam("file_plus", m_file_plus, "Path for an alternative mapping for tau+ decays", std::string(""));
76 }
77 
78 //
80 {
81  mode_decay_minus = make_map(m_file_minus, -1);
82  mode_decay_plus = make_map(m_file_plus, 1);
83  m_tauDecay.registerInDataStore();
84  m_event_metadata.isRequired();
85 }
86 
87 //
89 {
90 
92  if (tauPair) {
93 
95 
96  if (m_printmode == "missing") {
97  if (m_mmode == -1) {
98  B2INFO("TauDecayMode:: EventNumber = " << m_event_metadata->getEvent()
99  << " Decay: tau- -> " << m_tauminusdecaymode << " Mode = " << m_mmode);
100  }
101  if (m_pmode == -1) {
102  B2INFO("TauDecayMode:: EventNumber = " << m_event_metadata->getEvent()
103  << " Decay: tau+ -> " << m_tauplusdecaymode << " Mode = " << m_pmode);
104  }
105  }
106 
107  if (m_printmode == "all") {
108  B2INFO("TauDecayMode:: EventNumber = " << m_event_metadata->getEvent()
109  << " Decay: tau- -> " << m_tauminusdecaymode << " Mode = " << m_mmode);
110  B2INFO("TauDecayMode:: EventNumber = " << m_event_metadata->getEvent()
111  << " Decay: tau+ -> " << m_tauplusdecaymode << " Mode = " << m_pmode);
112  }
113 
114  //
115  if (m_mmode == -1) {
116  m_taum_no = m_taum_no - 1;
117  m_mmode = m_taum_no;
118  }
119  if (m_pmode == -1) {
120  m_taup_no = m_taup_no - 1;
121  m_pmode = m_taup_no;
122  }
123 
126 
129 
130  } else {
131  m_pmode = -1;
132  m_mmode = -1;
133  m_pprong = -1;
134  m_mprong = -1;
135  m_megstar = -1;
136  m_pegstar = -1;
137  }
138 
139  if (!m_tauDecay) m_tauDecay.create();
140  m_tauDecay->addTauMinusIdMode(m_mmode);
141  m_tauDecay->addTauPlusIdMode(m_pmode);
142 
143  m_tauDecay->addTauPlusMcProng(m_pprong);
144  m_tauDecay->addTauMinusMcProng(m_mprong);
145 
146  m_tauDecay->addTauMinusEgstar(m_megstar);
147  m_tauDecay->addTauPlusEgstar(m_pegstar);
148 }
149 
151 {
152  // Clear local vectors
153  vec_nut.clear();
154  vec_anut.clear();
155  vec_numu.clear();
156  vec_anumu.clear();
157  vec_nue.clear();
158  vec_anue.clear();
159  vec_em.clear();
160  vec_ep.clear();
161  vec_mum.clear();
162  vec_mup.clear();
163  vec_pim.clear();
164  vec_pip.clear();
165  vec_km.clear();
166  vec_kp.clear();
167  vec_apro.clear();
168  vec_pro.clear();
169  vec_pi0.clear();
170  vec_k0s.clear();
171  vec_k0l.clear();
172  vec_eta.clear();
173  vec_omega.clear();
174  vec_etapr.clear();
175  vec_phi.clear();
176  vec_rhom.clear();
177  vec_rhop.clear();
178  vec_rho0.clear();
179  vec_kstarm.clear();
180  vec_kstarp.clear();
181  vec_kstar0.clear();
182  vec_kstar0_br.clear();
183  vec_a1m.clear();
184  vec_a1p.clear();
185  vec_a00_980.clear();
186  vec_a0m_980.clear();
187  vec_a0p_980.clear();
188  vec_a00_1450.clear();
189  vec_a0m_1450.clear();
190  vec_a0p_1450.clear();
191  vec_b1m.clear();
192  vec_b1p.clear();
193  vec_f1.clear();
194  vec_f0.clear();
195  vec_lambda.clear();
196  vec_lmb_br.clear();
197  vec_alpha.clear();
198  vec_gam.clear();
199  vec_radgam_taum.clear();
200  vec_radgam_taup.clear();
201  //
202  map<int, std::vector<int>> map_vec;
203  //
204  map_vec[11] = vec_em;
205  map_vec[-11] = vec_ep;
206  map_vec[12] = vec_nue;
207  map_vec[-12] = vec_anue;
208  map_vec[13] = vec_mum;
209  map_vec[-13] = vec_mup;
210  map_vec[14] = vec_numu;
211  map_vec[-14] = vec_anumu;
212  map_vec[16] = vec_nut;
213  map_vec[-16] = vec_anut;
214  map_vec[-211] = vec_pim;
215  map_vec[211] = vec_pip;
216  map_vec[-321] = vec_km;
217  map_vec[321] = vec_kp;
218  map_vec[-2212] = vec_apro;
219  map_vec[2212] = vec_pro;
220  map_vec[111] = vec_pi0;
221  map_vec[310] = vec_k0s;
222  map_vec[130] = vec_k0l;
223  map_vec[221] = vec_eta;
224  map_vec[223] = vec_omega;
225  map_vec[331] = vec_etapr;
226  map_vec[333] = vec_phi;
227  map_vec[-213] = vec_rhom;
228  map_vec[213] = vec_rhop;
229  map_vec[113] = vec_rho0;
230  map_vec[-323] = vec_kstarm;
231  map_vec[323] = vec_kstarp;
232  map_vec[313] = vec_kstar0;
233  map_vec[-313] = vec_kstar0_br;
234  map_vec[-20213] = vec_a1m;
235  map_vec[20213] = vec_a1p;
236  map_vec[-9000211] = vec_a0m_980;
237  map_vec[9000211] = vec_a0p_980;
238  map_vec[9000111] = vec_a00_980;
239  map_vec[-10211] = vec_a0m_1450;
240  map_vec[10211] = vec_a0p_1450;
241  map_vec[10111] = vec_a00_1450;
242  map_vec[-10213] = vec_b1m;
243  map_vec[10213] = vec_b1p;
244  map_vec[20223] = vec_f1;
245  map_vec[9010221] = vec_f0;
246  map_vec[3122] = vec_lambda;
247  map_vec[-3122] = vec_lmb_br;
248  map_vec[94144] = vec_alpha;
249  map_vec[22] = vec_gam;
250 
251  bool TauMinusIsLeptonicDecay = false;
252  bool TauPlusIsLeptonicDecay = false;
253 
254  bool elecFirst = true;
255  bool muonFirst = true;
256 
257  bool isPiPizGamTauMinusFirst = true;
258  bool isPiPizGamTauPlusFirst = true;
259 
260  bool isLFVTauMinus2BodyDecayFirst = true;
261  bool isLFVTauPlus2BodyDecayFirst = true;
262 
263  bool isChargedRhoFromTauMinusFirst = true;
264  bool isChargedRhoFromTauPlusFirst = true;
265 
266  bool isChargedA1FromTauMinusFirst = true;
267  bool isChargedA1FromTauPlusFirst = true;
268 
269  bool isEtaPPGFromTauMinusFirst = true;
270  bool isEtaPPGFromTauPlusFirst = true;
271 
272  bool isOmegaPizGamFromTauMinusFirst = true;
273  bool isOmegaPizGamFromTauPlusFirst = true;
274 
275  bool isEtaPizPizPizFromTauMinusFirst = true;
276  bool isEtaPizPizPizFromTauPlusFirst = true;
277 
280 
281  bool isOmegaPimPipFromTauMinusFirst = true;
282  bool isOmegaPimPipFromTauPlusFirst = true;
283 
286 
287  // Loop of MCParticles
288  for (int i = 0; i < MCParticles.getEntries(); i++) {
289 
290  MCParticle& p = *MCParticles[i];
291 
292  int pdgid = p.getPDG();
293 
294  if (pdgid == -Const::Klong.getPDGCode()) pdgid = -pdgid; // Strange feature in TauolaBelle2
295 
296  // Special treatment for photons
297  bool accept_photon = false;
298 
299  if (!p.hasStatus(MCParticle::c_PrimaryParticle))
300  continue; // only consider particles coming from generator, e.g. discard particles added by Geant4
301  if (p.isInitial()) continue; // pick e- e+, but not from the incoming beams
302 
303  // Check IsLeptonicDecay first
304  if (abs(pdgid) == 12 || abs(pdgid) == 14) { // (anti-)nu_e or (anti-)nu_mu
305  int leptonicdecay = 0;
306  const MCParticle* mother = p.getMother(); // tau- or tau+
307  const vector<MCParticle*> daughters = mother->getDaughters();
308  for (MCParticle* d : daughters) {
309  int dauid = abs(d->getPDG());
310  if (dauid == 11 || dauid == 12 || dauid == 13 || dauid == 14 || dauid == 16) {
311  leptonicdecay++;
312  }
313  }
314  if (leptonicdecay == 3) {
315  if (mother->getPDG() == 15) TauMinusIsLeptonicDecay = true;
316  if (mother->getPDG() == -15) TauPlusIsLeptonicDecay = true;
317  }
318  }
319 
320  else if (pdgid == Const::electron.getPDGCode() && elecFirst) {
321  elecFirst = false;
322  const MCParticle* mother = p.getMother();
323  if (not mother) continue; // In some low multiplicity generators there may be no mother
324  const vector<MCParticle*> daughters = mother->getDaughters();
325  int nElMinus = 0;
326  int nElPlus = 0;
327  stringstream elec_ss;
328  for (MCParticle* d : daughters) {
329  if (!d->hasStatus(MCParticle::c_PrimaryParticle)) continue;
330  elec_ss << d->getPDG() << " ";
331  if (d->getPDG() == Const::electron.getPDGCode()) nElMinus++;
332  if (d->getPDG() == -Const::electron.getPDGCode()) nElPlus++;
333  }
334  if (nElMinus == 1 && nElPlus == 1) { // use this information in getRecursiveMotherCharge
335  B2DEBUG(19, "Mother of elec pair is = " << mother->getPDG() << " which has daughters : " << elec_ss.str());
336  }
337  }
338 
339  else if (pdgid == Const::muon.getPDGCode() && muonFirst) {
340  muonFirst = false;
341  const MCParticle* mother = p.getMother();
342  if (not mother) continue; // In some low multiplicity generators there may be no mother
343  const vector<MCParticle*> daughters = mother->getDaughters();
344  int nMuMinus = 0;
345  int nMuPlus = 0;
346  stringstream muon_ss;
347  for (MCParticle* d : daughters) {
348  if (!d->hasStatus(MCParticle::c_PrimaryParticle)) continue;
349  muon_ss << d->getPDG() << " ";
350  if (d->getPDG() == Const::muon.getPDGCode()) nMuMinus++;
351  if (d->getPDG() == -Const::muon.getPDGCode()) nMuPlus++;
352  }
353  if (nMuMinus == 1 && nMuPlus == 1) { // use this information in getRecursiveMotherCharge
354  B2DEBUG(19, "Mother of muon pair is = " << mother->getPDG() << " which has daughters : " << muon_ss.str());
355  }
356  }
357 
358  // Photons from PHOTOS are radiative photons
359  else if (pdgid == Const::photon.getPDGCode() && p.hasStatus(MCParticle::c_IsPHOTOSPhoton)) {
361  if (chg < 0) vec_radgam_taum.push_back(i);
362  if (chg > 0) vec_radgam_taup.push_back(i);
363  }
364 
365  // Photons from PHOTOS do not define tau decay mode
366  else if (pdgid == Const::photon.getPDGCode() && !p.hasStatus(MCParticle::c_IsPHOTOSPhoton)) {
367  const MCParticle* mother = p.getMother();
368  if (not mother) continue; // In some low multiplicity generators there may be no mother
369  int mothid = abs(mother->getPDG());
370 
371  // check if the gamma comes from final state charged particles {e, mu, pi, K, p, b_1}
372  bool isRadiationfromFinalStateChargedParticle = false;
373  if (mothid == 11 ||
374  mothid == 13 ||
375  mothid == 211 ||
376  mothid == 321 ||
377  mothid == 2212 ||
378  mothid == 10213) {
379  isRadiationfromFinalStateChargedParticle = true;
380  }
381 
382  // check if the gamma from ChargedRho
383  bool isRadiationFromChargedRho = false;
384  if (mothid == 213) {
385  int chg = getRecursiveMotherCharge(mother);
386  if (chg < 0 && isChargedRhoFromTauMinusFirst) {
387  isChargedRhoFromTauMinusFirst = false;
388  isRadiationFromChargedRho = true;
389  }
390  if (chg > 0 && isChargedRhoFromTauPlusFirst) {
391  isChargedRhoFromTauPlusFirst = false;
392  isRadiationFromChargedRho = true;
393  }
394  }
395 
396  // check if the gamma from ChargedA1
397  bool isRadiationFromChargedA1 = false;
398  if (mothid == 20213) {
399  int chg = getRecursiveMotherCharge(mother);
400  if (chg < 0 && isChargedA1FromTauMinusFirst) {
401  isChargedA1FromTauMinusFirst = false;
402  isRadiationFromChargedA1 = true;
403  }
404  if (chg > 0 && isChargedA1FromTauPlusFirst) {
405  isChargedA1FromTauPlusFirst = false;
406  isRadiationFromChargedA1 = true;
407  }
408  }
409 
410  // check if the gamma comes from intermediate W+- boson
411  bool isRadiationfromIntermediateWBoson = false;
412  if (mothid == 24) isRadiationfromIntermediateWBoson = true;
413 
414  // check if it is a tau- -> pi- omega nu, omega -> pi0 gamma decay
415  // Note: TauolaBelle2 generator treats this a coherent production
416  // e.g. includes omega in the form factor but not as an explicit final state particle
417  bool isPiPizGam = false;
418  if (isRadiationfromIntermediateWBoson) {
419  const vector<MCParticle*> daughters = mother->getDaughters();
420  int nPiSisters = 0;
421  int nPizSisters = 0;
422  int nTotSisters = 0;
423  int nOtherSisters = 0;
424  for (MCParticle* d : daughters) {
425  if (!d->hasStatus(MCParticle::c_PrimaryParticle)) continue;
426  nTotSisters++;
427  if (abs(d->getPDG()) == Const::pion.getPDGCode()) {
428  nPiSisters++;
429  } else if (abs(d->getPDG()) == Const::pi0.getPDGCode()) {
430  nPizSisters++;
431  } else if (abs(d->getPDG()) != Const::photon.getPDGCode()) {
432  nOtherSisters++;
433  }
434  }
435  // allow final state radiation from the tau lepton, but ignore information on number of photons for decay mode classifiction
436  if (nTotSisters >= 3 && nPiSisters == 1 && nPizSisters == 1 && nOtherSisters == 0) {
437  int chg = getRecursiveMotherCharge(mother);
438  if (chg < 0 && isPiPizGamTauMinusFirst) {
439  isPiPizGamTauMinusFirst = false;
440  isPiPizGam = true;
441  }
442  if (chg > 0 && isPiPizGamTauPlusFirst) {
443  isPiPizGamTauPlusFirst = false;
444  isPiPizGam = true;
445  }
446  }
447  }
448 
449  // check if the gamma comes from tau
450  bool isRadiationfromTau = false;
451  if (mothid == 15) isRadiationfromTau = true;
452 
453  // Photons from LeptonicTauDecays are radiative photons not added by PHOTOS
454  if (isRadiationfromTau) {
456  if (chg < 0 && TauMinusIsLeptonicDecay) vec_radgam_taum.push_back(i);
457  if (chg > 0 && TauPlusIsLeptonicDecay) vec_radgam_taup.push_back(i);
458  }
459 
460  // check if the gamma comes from 2 body LFV decays of tau, e.g. tau- -> e-/mu- gamma with arbitrary number of extra photon radiations from PHOTOS/FSR
461  bool isLFVTau2BodyDecay = false;
462  if (isRadiationfromTau) {
463  bool hasNeutrinoAsSister = false;
464  int numChargedSister = 0;
465  int numNeutralNonNeutrinoNonPhotonSister = 0;
466  const vector<MCParticle*> daughters = mother->getDaughters();
467  for (MCParticle* d : daughters) {
468  if (!d->hasStatus(MCParticle::c_PrimaryParticle)) continue;
469  hasNeutrinoAsSister = find(begin(Neutrinos), end(Neutrinos), abs(d->getPDG())) != end(Neutrinos);
470  if (hasNeutrinoAsSister) break;
471  }
472  if (!hasNeutrinoAsSister) {
473  for (MCParticle* d : daughters) {
474  if (!d->hasStatus(MCParticle::c_PrimaryParticle)) continue;
475  bool isChargedFinalState = find(begin(finalStatePDGs), end(finalStatePDGs), abs(d->getPDG())) != end(finalStatePDGs);
476  if (isChargedFinalState) {
477  numChargedSister++;
478  } else if (d->getPDG() != Const::photon.getPDGCode()) {
479  numNeutralNonNeutrinoNonPhotonSister++;
480  }
481  }
482  if (numChargedSister == 1 && numNeutralNonNeutrinoNonPhotonSister == 0) {
483  if (mother->getPDG() == 15 && isLFVTauMinus2BodyDecayFirst) {
484  isLFVTauMinus2BodyDecayFirst = false;
485  isLFVTau2BodyDecay = true;
486  }
487  if (mother->getPDG() == -15 && isLFVTauPlus2BodyDecayFirst) {
488  isLFVTauPlus2BodyDecayFirst = false;
489  isLFVTau2BodyDecay = true;
490  }
491  }
492  }
493  B2DEBUG(19, "hasNeutrinoAsSister = " << hasNeutrinoAsSister
494  << " numChargedSister = " << numChargedSister
495  << " numNeutralNonNeutrinoNonPhotonSister = " << numNeutralNonNeutrinoNonPhotonSister
496  << " isLFVTau2BodyDecay = " << isLFVTau2BodyDecay);
497  }
498 
499  bool isPi0GG = false;
500  bool isEtaGG = false;
501  bool isEtpGG = false;
502  bool isPi0GEE = false;
503  bool isEtaPPG = false;
504  bool isOmPizG = false;
505  if (mothid == 111 || mothid == 221 || mothid == 331 || mothid == 223) {
506  const vector<MCParticle*> daughters = mother->getDaughters();
507  int numberofTotalDaughters = 0;
508  int numberOfPhotonDaughters = 0;
509  int numberOfElectronDaughters = 0;
510  int numberOfPionDaughters = 0;
511  int numberOfPizDaughters = 0;
512  for (MCParticle* d : daughters) {
513  if (!d->hasStatus(MCParticle::c_PrimaryParticle)) continue;
514  numberofTotalDaughters ++;
515  if (abs(d->getPDG()) == Const::photon.getPDGCode()) numberOfPhotonDaughters++;
516  if (abs(d->getPDG()) == Const::electron.getPDGCode()) numberOfElectronDaughters++;
517  if (abs(d->getPDG()) == Const::pion.getPDGCode()) numberOfPionDaughters++;
518  if (abs(d->getPDG()) == Const::pi0.getPDGCode()) numberOfPizDaughters++;
519  }
520  if (numberofTotalDaughters == 2 && numberOfPhotonDaughters == 2) {
521  if (mothid == Const::pi0.getPDGCode()) isPi0GG = true;
522  if (mothid == 221) isEtaGG = true;
523  if (mothid == 331) isEtpGG = true;
524  }
525  if (numberofTotalDaughters >= 3 && numberOfPhotonDaughters >= 1 && numberOfElectronDaughters == 2 && numberOfPionDaughters == 0
526  && numberOfPizDaughters == 0) {
527  if (mothid == Const::pi0.getPDGCode()) isPi0GEE = true;
528  }
529  if (numberofTotalDaughters >= 3 && numberOfPhotonDaughters >= 1 && numberOfPizDaughters == 0 && numberOfPionDaughters == 2) {
530  if (mothid == 221) {
531  int chg = getRecursiveMotherCharge(mother);
532  if (chg < 0 && isEtaPPGFromTauMinusFirst) {
533  isEtaPPGFromTauMinusFirst = false;
534  isEtaPPG = true;
535  }
536  if (chg > 0 && isEtaPPGFromTauPlusFirst) {
537  isEtaPPGFromTauPlusFirst = false;
538  isEtaPPG = true;
539  }
540  }
541  }
542  if (numberofTotalDaughters >= 2 && numberOfPhotonDaughters >= 1 && numberOfPizDaughters == 1 && numberOfPionDaughters == 0) {
543  if (mothid == 223) {
544  int chg = getRecursiveMotherCharge(mother);
545  if (chg < 0 && isOmegaPizGamFromTauMinusFirst) {
546  isOmegaPizGamFromTauMinusFirst = false;
547  isOmPizG = true;
548  }
549  if (chg > 0 && isOmegaPizGamFromTauPlusFirst) {
550  isOmegaPizGamFromTauPlusFirst = false;
551  isOmPizG = true;
552  }
553  }
554  }
555  }
556 
557  B2DEBUG(19, "isRadiationfromFinalStateChargedParticle = " << isRadiationfromFinalStateChargedParticle);
558  B2DEBUG(19, "isRadiationFromChargedRho = " << isRadiationFromChargedRho);
559  B2DEBUG(19, "isRadiationFromChargedA1 = " << isRadiationFromChargedA1);
560  B2DEBUG(19, "isRadiationfromIntermediateWBoson = " << isRadiationfromIntermediateWBoson << " isPiPizGam = " << isPiPizGam);
561  B2DEBUG(19, "isRadiationfromTau = " << isRadiationfromTau << " isLFVTau2BodyDecay = " << isLFVTau2BodyDecay);
562  B2DEBUG(19, "isPi0GG = " << isPi0GG << " isEtaGG = " << isEtaGG << " isEtpGG = " << isEtpGG << " isPi0GEE = " << isPi0GEE);
563  B2DEBUG(19, "isEtaPPG = " << isEtaPPG << " isOmPizG = " << isOmPizG);
564 
565  // accept photons if (isRadiationfromFinalStateChargedParticle is false) or
566  // if (isRadiationfromIntermediateWBoson is false) or
567  // if (isRadiationfromTau is true) {gamma is from 2 body LFV decays of tau} or
568  // if the radiation is coming from any other decay [except pi0 -> gamma gamma, eta-> gamma gamma, eta' -> gamma gamma]
569  if (isRadiationfromFinalStateChargedParticle) {
570  } else if (isRadiationFromChargedRho) {
571  accept_photon = true;
572  } else if (isRadiationFromChargedA1) {
573  accept_photon = true;
574  } else if (isRadiationfromIntermediateWBoson) {
575  if (isPiPizGam) {
576  accept_photon = true;
577  }
578  } else if (isRadiationfromTau) { // accept one photon from tau -> (charged particle) + gamma [no neutrinos]
579  if (isLFVTau2BodyDecay) {
580  accept_photon = true;
581  }
582  } else if (isPi0GG) {
583  } else if (isEtaGG) {
584  } else if (isEtpGG) {
585  } else if (isPi0GEE) {
586  } else if (isEtaPPG) {
587  accept_photon = true;
588  } else if (isOmPizG) {
589  accept_photon = true;
590  }
591  }
592 
593  // Without further analysis, it is NOT possible to separate
594  // tau- -> pi- 2pi0 eta (-> pi- pi+ pi0) nu decays [Mode 39] from
595  // tau- -> 2pi- pi+ eta (-> pi0 pi0 pi0) nu decays [Mode 42]
596 
597  else if (pdgid == Const::pi0.getPDGCode() && (isEtaPizPizPizFromTauMinusFirst || isEtaPizPizPizFromTauPlusFirst)) {
598  const MCParticle* mother = p.getMother();
599  // In some low multiplicity generators there may be no mother
600  if (mother and (mother->getPDG() == 221)) { // eta -> pi0 pi0 pi0
601  const vector<MCParticle*> daughters = mother->getDaughters();
602  int nPizSisters = 0;
603  for (MCParticle* d : daughters) {
604  if (!d->hasStatus(MCParticle::c_PrimaryParticle)) continue;
605  if (d->getPDG() == Const::pi0.getPDGCode()) nPizSisters++;
606  }
607  B2DEBUG(19, "nPizSisters = " << nPizSisters);
608  if (nPizSisters == 3) {
609  int chg = getRecursiveMotherCharge(mother);
610  if (chg < 0 && isEtaPizPizPizFromTauMinusFirst) {
611  isEtaPizPizPizFromTauMinusFirst = false;
613  }
614  if (chg > 0 && isEtaPizPizPizFromTauPlusFirst) {
615  isEtaPizPizPizFromTauPlusFirst = false;
617  }
618  }
619  }
620  }
621 
622  // Without further analysis, it is NOT possible to separate
623  // tau- -> pi- 2pi0 omega (-> pi- pi+) nu decays [Mode 49] from
624  // tau- -> 2pi- pi+ 2pi0 nu decays [Mode 66]
625  // Note: TauolaBelle2 treats Mode 66 is coherent production,
626  // e.g. includes omega in the form factor but not as an explicit final state particle.
627  // Note2: omega is explicitly included in following mode:
628  // tau- -> pi- pi0 omega (-> pi- pi+ pi0) nu decays [Mode 130]
629  // which is where Mode 49 is mapped to if there is no omega->pi-pi+ decay
630 
631  // Same confusion can also happen for
632  // tau- -> pi- pi0 omega (-> pi- pi+) nu decays [Mode 131]
633  // tau- -> pi- omega (-> pi- pi+ pi0) nu decays [Mode 236]
634 
635  else if (pdgid == -Const::pion.getPDGCode() && (isOmegaPimPipFromTauMinusFirst || isOmegaPimPipFromTauPlusFirst)) {
636  const MCParticle* mother = p.getMother();
637  // In some low multiplicity generators there may be no mother
638  if (mother and (mother->getPDG() == 223)) { // omega -> pi- pi+
639  const vector<MCParticle*> daughters = mother->getDaughters();
640  int nOmegaDaughters = 0;
641  int nPimSisters = 0;
642  int nPipSisters = 0;
643  int nPizSisters = 0;
644  for (MCParticle* d : daughters) {
645  if (!d->hasStatus(MCParticle::c_PrimaryParticle)) continue;
646  nOmegaDaughters++;
647  if (d->getPDG() == -Const::pion.getPDGCode()) nPimSisters++;
648  if (d->getPDG() == Const::pion.getPDGCode()) nPipSisters++;
649  if (d->getPDG() == Const::pi0.getPDGCode()) nPizSisters++;
650  }
651  B2DEBUG(19,
652  "nOmegaDaughters = " << nOmegaDaughters << " "
653  "nPimSisters = " << nPimSisters << " "
654  "nPipSisters = " << nPipSisters << " "
655  "nPizSisters = " << nPizSisters);
656  if (nOmegaDaughters >= 2 && nPimSisters == 1 && nPipSisters == 1 && nPizSisters == 0) { // allow omega->pi-pi+gama
657  int chg = getRecursiveMotherCharge(mother);
658  if (chg < 0 && isOmegaPimPipFromTauMinusFirst) {
659  isOmegaPimPipFromTauMinusFirst = false;
661  }
662  if (chg > 0 && isOmegaPimPipFromTauPlusFirst) {
663  isOmegaPimPipFromTauPlusFirst = false;
665  }
666  }
667  }
668  }
669  B2DEBUG(19,
670  "isEtaPizPizPizFromTauMinusFirst = " << isEtaPizPizPizFromTauMinusFirst << " "
671  "m_isEtaPizPizPizFromTauMinus = " << m_isEtaPizPizPizFromTauMinus << " "
672  "isEtaPizPizPizFromTauPlusFirst = " << isEtaPizPizPizFromTauPlusFirst << " "
673  "m_isEtaPizPizPizFromTauPlus = " << m_isEtaPizPizPizFromTauPlus
674  );
675  B2DEBUG(19,
676  "isOmegaPimPipFromTauMinusFirst = " << isOmegaPimPipFromTauMinusFirst << " "
677  "m_isOmegaPimPipFromTauMinus = " << m_isOmegaPimPipFromTauMinus << " "
678  "isOmegaPimPipFromTauPlusFirst = " << isOmegaPimPipFromTauPlusFirst << " "
679  "m_isOmegaPimPipFromTauPlus = " << m_isEtaPizPizPizFromTauPlus
680  );
681 
682  // Fill up all the vector of particles
683  map<int, std::vector<int>>::iterator ite ;
684  for (ite = map_vec.begin(); ite != map_vec.end(); ++ite) {
685  if (pdgid == ite->first) {
686  if (pdgid == Const::photon.getPDGCode()) {
687  if (accept_photon) {
688  B2DEBUG(19, "Photon accepted");
689  ite-> second.push_back(i);
690  }
691  } else {
692  ite-> second.push_back(i);
693  }
694  break;
695  }
696  }
697 
698  } // End of loop over MCParticles
699 
700  vec_dau_tauminus.clear();
701  vec_dau_tauplus.clear();
702 
703  map<int, std::vector<int>>::iterator itr ;
704  for (itr = map_vec.begin(); itr != map_vec.end(); ++itr) {
705  for (unsigned int i = 0; i < itr-> second.size(); i++) {
706  int ii = itr-> second[i];
707  int chg = getRecursiveMotherCharge(MCParticles[ii]);
708  if (chg < 0) vec_dau_tauminus.push_back(ii);
709  if (chg > 0) vec_dau_tauplus.push_back(ii);
710  }
711  }
712 
714  std::string pdgname;
715 
716  //make decay string for tau-
717  m_tauminusdecaymode = "";
718  for (unsigned iorder = 0; iorder < 46; ++iorder) {
719  int ii = OrderedList[iorder];
720  //
721  for (unsigned int i = 0; i < vec_dau_tauminus.size(); i++) {
723  int pdg = p->getPDG();
724  if (pdg == -Const::Klong.getPDGCode()) pdg = -pdg; // Strange Feature in TauolaBelle2
725  if (pdg != ii) continue;
726  m_tauminusdecaymode.append(".");
727  if (pdg == 94144) {
728  pdgname = "alpha";
729  } else {
730  pdgname = databasePDG->GetParticle(pdg)->GetName();
731  }
732  m_tauminusdecaymode.append(pdgname);
733  }
734  }
735  //
737 
738  //make decay string for tau+
739  m_tauplusdecaymode = "";
740  for (unsigned iorder = 0; iorder < 46; ++iorder) {
741  int ii = OrderedList[iorder];
742  //
743  for (unsigned int i = 0; i < vec_dau_tauplus.size(); i++) {
745  int pdg = p->getPDG();
746  if (pdg == -Const::Klong.getPDGCode()) pdg = -pdg; // Strange Feature in TauolaBelle2
747  if (pdg != ii) continue;
748  m_tauplusdecaymode.append(".");
749  if (pdg == 94144) {
750  pdgname = "alpha";
751  } else {
752  pdgname = databasePDG->GetParticle(pdg)->GetName();
753  }
754  m_tauplusdecaymode.append(pdgname);
755  }
756  }
757  //
759 
760 }
761 
762 //
763 int TauDecayModeModule::TauolaBelle2DecayMode(const std::string& state, int chg)
764 {
765  std::map<std::string, int> mode_decay = (chg < 0) ? mode_decay_minus : mode_decay_plus;
766  map<std::string, int>::iterator itr ;
767  for (itr = mode_decay.begin(); itr != mode_decay.end(); ++itr) {
768  if (state == itr-> first) {
769  int mode = itr-> second;
770  if (mode == 39) {
771  if (chg < 0 && m_isEtaPizPizPizFromTauMinus) mode = 42;
772  if (chg > 0 && m_isEtaPizPizPizFromTauPlus) mode = 42;
773  }
774  if (mode == 49) {
775  if (chg < 0 && !m_isOmegaPimPipFromTauMinus) mode = 130;
776  if (chg > 0 && !m_isOmegaPimPipFromTauPlus) mode = 130;
777  }
778  if (mode == 131) {
779  if (chg < 0 && !m_isOmegaPimPipFromTauMinus) mode = 236;
780  if (chg > 0 && !m_isOmegaPimPipFromTauPlus) mode = 236;
781  }
782  if (mode == 247) {
783  if (chg < 0 && !m_isEtaPizPizPizFromTauMinus) mode = 15;
784  if (chg > 0 && !m_isEtaPizPizPizFromTauPlus) mode = 15;
785  }
786  return mode;
787  }
788  }
789  return -1;
790 }
791 
792 //
794 {
795  const MCParticle* mother = p->getMother();
796  if (mother == nullptr) {
797  return 0;
798  } else if (abs(p->getPDG()) == Const::electron.getPDGCode() && mother->getPDG() == Const::pi0.getPDGCode()) { // pi0 -> e-e+ gamma
799  return 0;
800  } else if (abs(p->getPDG()) == Const::electron.getPDGCode() && mother->getPDG() == 221) { // eta -> e-e+ gamma
801  return 0;
802  } else if (abs(p->getPDG()) == Const::electron.getPDGCode() && mother->getPDG() == 113) { // rho0 -> e-e+
803  return 0;
804  } else if (abs(p->getPDG()) == Const::electron.getPDGCode() && mother->getPDG() == 223) { // omega -> e- e+
805  return 0;
806  } else if (abs(p->getPDG()) == Const::electron.getPDGCode() && mother->getPDG() == 333) { // phi -> e- e+
807  return 0;
808  } else if (abs(p->getPDG()) == Const::muon.getPDGCode() && mother->getPDG() == 221) { // eta -> mu-mu+ gamma
809  return 0;
810  } else if (abs(p->getPDG()) == Const::muon.getPDGCode() && mother->getPDG() == 113) { // rho0 -> mu-mu+
811  return 0;
812  } else if (abs(p->getPDG()) == Const::muon.getPDGCode() && mother->getPDG() == 333) { // phi -> mu-mu+
813  return 0;
814  } else if (mother->getPDG() == 15) {
815  return -1;
816  } else if (mother->getPDG() == -15) {
817  return 1;
818  } else {
819  return getRecursiveMotherCharge(mother);
820  }
821 }
822 
823 //
825 {
826  numOfTauPlus = 0;
827  numOfTauMinus = 0;
828  idOfTauPlus = 0;
829  idOfTauMinus = 0;
830  for (int i = 0; i < MCParticles.getEntries(); i++) {
831  MCParticle& p = *MCParticles[i];
832 
833  if (p.getStatus() == 1 && p.getPDG() == 15) {
834  numOfTauMinus++;
835  idOfTauMinus = p.getIndex();
836  }
837  if (p.getStatus() == 1 && p.getPDG() == -15) {
838  numOfTauPlus++;
839  idOfTauPlus = p.getIndex();
840  }
841  }
842  if (numOfTauPlus == 1 && numOfTauMinus == 1) {
843  tauPair = true;
844  } else tauPair = false;
845 }
846 
847 //
849 {
850  int ret = 0;
851  const vector<MCParticle*> daughters = p.getDaughters();
852  if (daughters.empty()) return ret;
853  for (MCParticle* d : daughters) {
854  if (!d->hasStatus(MCParticle::c_PrimaryParticle)) continue;
855  // TODO: Improve how to identify a final state particle.
856  bool isChargedFinalState = find(begin(finalStatePDGs),
857  end(finalStatePDGs),
858  abs(d->getPDG())) != end(finalStatePDGs);
859  if (isChargedFinalState) ret++;
860  else ret += getProngOfDecay(*d);
861  }
862  return ret;
863 }
864 
865 // Energy of the radiative photon in tau rest frame
866 double TauDecayModeModule::getEgstar(const std::vector<int>& vec_radgam, const MCParticle& p)
867 {
868  double egstar = -1.;
869  ROOT::Math::PxPyPzEVector p4_tau = p.get4Vector();
870  B2DEBUG(19, "p4_tau: " << p4_tau << " " << p4_tau.P());
871  ROOT::Math::Boost boost_to_mother_rest_frame(p4_tau.BoostToCM());
872  for (auto i : vec_radgam) {
873  ROOT::Math::PxPyPzEVector p4_gamma = MCParticles[i]->get4Vector();
874  B2DEBUG(19, "p4_gamma: " << p4_gamma << " " << p4_gamma.P());
875  ROOT::Math::PxPyPzEVector p4_gamma_rest = boost_to_mother_rest_frame * p4_gamma;
876  B2DEBUG(19, "p4_gamma_rest: " << p4_gamma_rest << " " << p4_gamma_rest.P());
877  double energy_rest = p4_gamma_rest.E();
878  if (energy_rest > egstar) egstar = energy_rest;
879  }
880  B2DEBUG(19, "egstar: " << egstar);
881  return egstar;
882 }
int getPDGCode() const
PDG code.
Definition: Const.h:464
static const ParticleType pi0
neutral pion particle
Definition: Const.h:665
static const ChargedStable muon
muon particle
Definition: Const.h:651
static const ChargedStable pion
charged pion particle
Definition: Const.h:652
static const ParticleType Klong
K^0_L particle.
Definition: Const.h:669
static const ParticleType photon
photon particle
Definition: Const.h:664
static const ChargedStable electron
electron particle
Definition: Const.h:650
Replacement for TDatabasePDG that is filled from EvtGen's evt.pdl.
static EvtGenDatabasePDG * Instance()
Instance method that loads the EvtGen table.
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
@ c_IsPHOTOSPhoton
bit 8: Particle is an radiative photon from PHOTOS
Definition: MCParticle.h:63
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
std::vector< int > vec_numu
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_em
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_omega
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_k0s
Variable name of the vector where particles identified in the event are stored.
Int_t m_mprong
Prong of the decay channel of tau-.
std::vector< int > vec_b1p
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_f1
Variable name of the vector where particles identified in the event are stored.
int numOfTauPlus
Number of tau+ in the event.
Int_t m_pprong
Prong of the decay channel of tau+.
StoreObjPtr< EventMetaData > m_event_metadata
event number
void IdentifyTauPair()
Identifies if the event is a generated tau pair.
std::vector< int > vec_apro
Variable name of the vector where particles identified in the event are stored.
double getEgstar(const std::vector< int > &vec_radgam, const MCParticle &mc)
Energy of the radiative photon in tau rest frame.
std::vector< int > vec_pi0
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_alpha
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_radgam_taum
Variable name of the vector where particles identified in the event are stored.
StoreArray< MCParticle > MCParticles
StoreArray of MCParticles.
std::vector< int > vec_anue
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_nue
Variable name of the vector where particles identified in the event are stored.
virtual void initialize() override
Initializes the module.
std::vector< int > vec_a0p_980
Variable name of the vector where particles identified in the event are stored.
std::string m_file_plus
Alternative mapping for tau+.
std::vector< int > vec_a0m_1450
Variable name of the vector where particles identified in the event are stored.
virtual void event() override
Method is called for each event.
bool m_isEtaPizPizPizFromTauMinus
Flag for eta->pi0pi0pi0 decays from tau-.
double m_pegstar
Energy of radiative photon from tau+.
std::vector< int > vec_lmb_br
Variable name of the vector where particles identified in the event are stored.
Int_t m_mmode
ID of the decay channel of tau-.
void AnalyzeTauPairEvent()
Analyze a generated tau pair event.
bool m_isOmegaPimPipFromTauMinus
Flag for omega->pi-pi+ decays from tau-.
int getRecursiveMotherCharge(const MCParticle *mc)
Identifies particles coming from tau decays.
std::vector< int > vec_phi
Variable name of the vector where particles identified in the event are stored.
static constexpr int Neutrinos[3]
PDG codes of neutrinos in final state particles in generation: {nu_e, nu_mu, mu_tau}.
int m_taum_no
number of tau- unclassified events
std::string m_tauminusdecaymode
Variable name for the decay mode of the tau-.
std::vector< int > vec_a1p
Variable name of the vector where particles identified in the event are stored.
bool m_isOmegaPimPipFromTauPlus
Flag for omega->pi-pi+ decays from tau+.
bool tauPair
Boolean variable used to identify tau event.
int TauolaBelle2DecayMode(const std::string &s, int chg)
Classifies the decays of the event and assigns a decay mode.
int idOfTauMinus
Index of the generated tau-.
std::vector< int > vec_lambda
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_anut
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_f0
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_mum
Variable name of the vector where particles identified in the event are stored.
Int_t m_pmode
ID of the decay channel of tau+.
static constexpr int OrderedList[46]
PDG codes of ORDERED particles.
int numOfTauMinus
Number of tau- in the event.
std::vector< int > vec_nut
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_kstar0_br
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_radgam_taup
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_a00_1450
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_kstar0
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_a0m_980
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_a00_980
Variable name of the vector where particles identified in the event are stored.
int getProngOfDecay(const MCParticle &mc)
Identifies the number of charged final state particles in the decay.
std::vector< int > vec_a1m
Variable name of the vector where particles identified in the event are stored.
int idOfTauPlus
Index of the generated tau+.
StoreObjPtr< TauPairDecay > m_tauDecay
pointer to tau pair decay objects
std::vector< int > vec_rhop
Variable name of the vector where particles identified in the event are stored.
std::string m_printmode
Parameter passed by the user to indicated the informationt to be printed.
std::vector< int > vec_pro
Variable name of the vector where particles identified in the event are stored.
bool m_isEtaPizPizPizFromTauPlus
Flag for eta->pi0pi0pi0 decays from tau+.
std::string m_tauplusdecaymode
Variable name for the decay mode of the tau+.
std::vector< int > vec_pim
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_mup
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_pip
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_kstarp
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_kstarm
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_etapr
Variable name of the vector where particles identified in the event are stored.
double m_megstar
Energy of radiative photon from tau-.
std::vector< int > vec_ep
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_k0l
Variable name of the vector where particles identified in the event are stored.
static constexpr int finalStatePDGs[5]
PDG codes accepted as charged final state particles in generation: {e, mu, pi, K, p}.
std::vector< int > vec_eta
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_km
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_anumu
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_dau_tauplus
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_rhom
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_gam
Variable name of the vector where particles identified in the event are stored.
std::string m_file_minus
Alternative mapping for tau-.
int m_taup_no
number of tau+ unclassified events
std::vector< int > vec_dau_tauminus
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_kp
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_b1m
Variable name of the vector where particles identified in the event are stored.
std::vector< int > vec_rho0
Variable name of the vector where particles identified in the event are stored.
std::map< std::string, int > mode_decay_minus
Mapping for tau- decays.
std::map< std::string, int > mode_decay_plus
Mapping for tau+ decays.
std::vector< int > vec_a0p_1450
Variable name of the vector where particles identified in the event are stored.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.