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