Belle II Software development
decfiles_branching_fractions.py
1#!/usr/bin/env python
2
3
10
11# Compare the length of decay description measured in number of lines
12# (excluding comments and empty lines) as well as the sum of the decay
13# mode branching fractions.
14
15import re
16import basf2
17# make Belle2 namespace available
18from ROOT import Belle2 # noqa
19from ROOT.Belle2 import EvtGenDatabasePDG
20from terminal_utils import ANSIColors as ac
21
22database = EvtGenDatabasePDG.Instance()
23
24f = open(basf2.find_file('decfiles/dec/DECAY_BELLE2.DEC'))
25decfile_lines = f.readlines()
26f.close()
27
28re_decay = re.compile('Decay *([^ ]+).*\n')
29re_enddecay = re.compile('Enddecay *')
30
31in_decay = False
32# save the decay mode lines belonging to a certain particle as dictionary
33# to do some checks on these.
34decays = {}
35particle = ''
36for i in range(len(decfile_lines)):
37 if in_decay:
38 match = re_enddecay.match(decfile_lines[i])
39 if match is not None:
40 in_decay = False
41 else:
42 if (decfile_lines[i] != '\n'):
43 if (decfile_lines[i].lstrip()[0] != '#'):
44 decays[particle].append(decfile_lines[i])
45 else:
46 match = re_decay.match(decfile_lines[i])
47 if match is not None:
48 particle = match.group(1)
49 decays[particle] = []
50 in_decay = True
51
52# determine the number of defined decay modes for each defined particle
53# and compare them to the corresponding anti-particle
54
55
56def get_decay_length(particle_name):
57 if particle_name in decays:
58 return len(decays[particle_name])
59 return -1
60
61
62for particle in database.ParticleList():
63 code = particle.PdgCode()
64 name = particle.GetName()
65 if (code > 0):
66 antiparticle = database.GetParticle(-code)
67 if antiparticle:
68 antiname = antiparticle.GetName()
69 length = get_decay_length(name)
70 antilength = get_decay_length(antiname)
71 if (length > 0 and antilength > 0 and length != antilength):
72 print('Inconsistent length of decay description '
73 f'for {name} ({length}) and {antiname} ({antilength}).')
74 exit(1)
75
76
77# Now get the sum of branching fractions for each particle
78def get_branching_fraction(particle_name):
79 if particle_name in decays:
80 bfsum = 0.
81 for decmode in decays[particle_name]:
82 bfsum += float(decmode.split()[0])
83 return bfsum
84 return -1
85
86
87for particle in database.ParticleList():
88 code = particle.PdgCode()
89 name = particle.GetName()
90 if (code > 0):
91 antiparticle = database.GetParticle(-code)
92 if antiparticle:
93 antiname = antiparticle.GetName()
94 bfsum = get_branching_fraction(name)
95 antibfsum = get_branching_fraction(antiname)
96 if (bfsum > 0 and antibfsum > 0 and bfsum != antibfsum):
97 print('Inconsistent sum of decay branching fractions '
98 f'for {name} ({bfsum}) and {antiname} ({antibfsum}).\n'
99 f'Did you remember to modify both {name} and {antiname} branching fractions? '
100 f'Check it also by running "{ac.color("red")}b2dec-compare-BFs{ac.reset()}".')
101 exit(1)
102 # This should be done for each particle, not only B mesons, but the
103 # other particle's decays have not yet been fixed
104 if ((abs(code) == 511 or abs(code) == 521) and bfsum > 0 and abs(1.0 - bfsum) > 1e-7):
105 print('Sum of decay mode branching fractions '
106 f'for {name} is not compatible with 1 ({bfsum}).\n'
107 f'Did you remember to run "{ac.color("red")}b2dec-correct-pythiaBFs{ac.reset()}"?')
108 exit(1)
109 # This should be done for each particle, not only B mesons, but the
110 # other particle's decays have not yet been fixed
111 if ((abs(code) == 511 or abs(code) == 521) and antibfsum > 0 and abs(1.0 - antibfsum) > 1e-7):
112 print('Sum of decay mode branching fractions '
113 f'for {antiname} is not compatible with 1 ({antibfsum}).\n'
114 f'Did you remember to run "{ac.color("red")}b2dec-correct-pythiaBFs{ac.reset()}"?')
115 exit(1)