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