Belle II Software  release-05-01-25
decfiles_branching_fractions.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 # Compare the length of decay description measured in number of lines
5 # (excluding comments and empty lines) as well as the sum of the decay
6 # mode branching fractions.
7 # Authors: Kirill Chilikin, Stephan Duell
8 
9 import re
10 
11 from ROOT import Belle2
12 from ROOT.Belle2 import EvtGenDatabasePDG
13 
14 database = EvtGenDatabasePDG.Instance()
15 
16 f = open(Belle2.FileSystem.findFile('decfiles/dec/DECAY_BELLE2.DEC'))
17 decfile_lines = f.readlines()
18 f.close()
19 
20 re_decay = re.compile('Decay *([^ ]+).*\n')
21 re_enddecay = re.compile('Enddecay *')
22 
23 in_decay = False
24 decays = {} # save the decay mode lines belonging to a certain particle as dictionary to do some checks on these.
25 for i in range(len(decfile_lines)):
26  if in_decay:
27  match = re_enddecay.match(decfile_lines[i])
28  if match is not None:
29  in_decay = False
30  else:
31  if(decfile_lines[i] != '\n'):
32  if(decfile_lines[i].lstrip()[0] != '#'):
33  decays[particle].append(decfile_lines[i])
34  else:
35  match = re_decay.match(decfile_lines[i])
36  if match is not None:
37  particle = match.group(1)
38  decays[particle] = []
39  in_decay = True
40 
41 # determine the number of defined decay modes for each defined particle and compare them to the corresponding anti-particle
42 
43 
44 def get_decay_length(particle_name):
45  if particle_name in decays:
46  return len(decays[particle_name])
47  return -1
48 
49 for particle in database.ParticleList():
50  code = particle.PdgCode()
51  name = particle.GetName()
52  if (code > 0):
53  antiparticle = database.GetParticle(-code)
54  if antiparticle:
55  antiname = antiparticle.GetName()
56  length = get_decay_length(name)
57  antilength = get_decay_length(antiname)
58  if (length > 0 and antilength > 0 and length != antilength):
59  print(f'Inconsistent length of decay description '
60  f'for {name} ({length}) and {antiname} ({antilength}).')
61  exit(1)
62 
63 
64 # Now get the sum of branching fractions for each particle
65 def get_branching_fraction(particle_name):
66  if particle_name in decays:
67  bfsum = 0.
68  for decmode in decays[particle_name]:
69  bfsum += float(decmode.split()[0])
70  return bfsum
71  return -1
72 
73 for particle in database.ParticleList():
74  code = particle.PdgCode()
75  name = particle.GetName()
76  if (code > 0):
77  antiparticle = database.GetParticle(-code)
78  if antiparticle:
79  antiname = antiparticle.GetName()
80  bfsum = get_branching_fraction(name)
81  antibfsum = get_branching_fraction(antiname)
82  if (bfsum > 0 and antibfsum > 0 and bfsum != antibfsum):
83  print(f'Inconsistent sum of decay branching fractions '
84  f'for {name} ({bfsum}) and {antiname} ({antibfsum}).')
85  exit(1)
86  # This should be done for each particle, not only B mesons, but the other particle's decays have not yet been fixed
87  if((abs(code) == 511 or abs(code) == 521) and bfsum > 0 and abs(1.0-bfsum) > 1e-7):
88  print(f'Sum of decay mode branching fractions '
89  f'for {name} is not compatible with 1 ({bfsum}).')
90  exit(1)
91  # This should be done for each particle, not only B mesons, but the other particle's decays have not yet been fixed
92  if((abs(code) == 511 or abs(code) == 521) and antibfsum > 0 and abs(1.0-antibfsum) > 1e-7):
93  print(f'Sum of decay mode branching fractions '
94  f'for {antiname} is not compatible with 1 ({antibfsum}).')
95  exit(1)
Belle2::FileSystem::findFile
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
Definition: FileSystem.cc:147