Belle II Software  release-06-01-15
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 for i in range(len(decfile_lines)):
35  if in_decay:
36  match = re_enddecay.match(decfile_lines[i])
37  if match is not None:
38  in_decay = False
39  else:
40  if(decfile_lines[i] != '\n'):
41  if(decfile_lines[i].lstrip()[0] != '#'):
42  decays[particle].append(decfile_lines[i])
43  else:
44  match = re_decay.match(decfile_lines[i])
45  if match is not None:
46  particle = match.group(1)
47  decays[particle] = []
48  in_decay = True
49 
50 # determine the number of defined decay modes for each defined particle
51 # and compare them to the corresponding anti-particle
52 
53 
54 def get_decay_length(particle_name):
55  if particle_name in decays:
56  return len(decays[particle_name])
57  return -1
58 
59 
60 for particle in database.ParticleList():
61  code = particle.PdgCode()
62  name = particle.GetName()
63  if (code > 0):
64  antiparticle = database.GetParticle(-code)
65  if antiparticle:
66  antiname = antiparticle.GetName()
67  length = get_decay_length(name)
68  antilength = get_decay_length(antiname)
69  if (length > 0 and antilength > 0 and length != antilength):
70  print('Inconsistent length of decay description '
71  f'for {name} ({length}) and {antiname} ({antilength}).')
72  exit(1)
73 
74 
75 # Now get the sum of branching fractions for each particle
76 def get_branching_fraction(particle_name):
77  if particle_name in decays:
78  bfsum = 0.
79  for decmode in decays[particle_name]:
80  bfsum += float(decmode.split()[0])
81  return bfsum
82  return -1
83 
84 
85 for particle in database.ParticleList():
86  code = particle.PdgCode()
87  name = particle.GetName()
88  if (code > 0):
89  antiparticle = database.GetParticle(-code)
90  if antiparticle:
91  antiname = antiparticle.GetName()
92  bfsum = get_branching_fraction(name)
93  antibfsum = get_branching_fraction(antiname)
94  if (bfsum > 0 and antibfsum > 0 and bfsum != antibfsum):
95  print('Inconsistent sum of decay branching fractions '
96  f'for {name} ({bfsum}) and {antiname} ({antibfsum}).\n'
97  f'Did you remember to modify both {name} and {antiname} branching fractions? '
98  f'Check it also by running "{ac.color("red")}b2dec-compare-BFs{ac.reset()}".')
99  exit(1)
100  # This should be done for each particle, not only B mesons, but the
101  # other particle's decays have not yet been fixed
102  if((abs(code) == 511 or abs(code) == 521) and bfsum > 0 and abs(1.0 - bfsum) > 1e-7):
103  print('Sum of decay mode branching fractions '
104  f'for {name} is not compatible with 1 ({bfsum}).\n'
105  f'Did you remember to run "{ac.color("red")}b2dec-correct-pythiaBFs{ac.reset()}"?')
106  exit(1)
107  # This should be done for each particle, not only B mesons, but the
108  # other particle's decays have not yet been fixed
109  if((abs(code) == 511 or abs(code) == 521) and antibfsum > 0 and abs(1.0 - antibfsum) > 1e-7):
110  print('Sum of decay mode branching fractions '
111  f'for {antiname} is not compatible with 1 ({antibfsum}).\n'
112  f'Did you remember to run "{ac.color("red")}b2dec-correct-pythiaBFs{ac.reset()}"?')
113  exit(1)