Belle II Software  release-06-02-00
decayHash.py
1 #!/usr/bin/env python3
2 
3 
10 
11 import re
12 import struct
13 import pdg
14 import basf2
15 
16 import pybasf2
17 # inspect is also used by LogPythonInterface. Do not remove
18 import numpy as np
19 import ROOT
20 from ROOT import Belle2
21 
22 logging = pybasf2.LogPythonInterface()
23 
24 ROOT.gSystem.Load("libanalysis.so")
25 ROOT.gSystem.Load("libanalysis_utility.so")
26 
27 
28 def _bitwiseConversion(value, i='f', o='i'):
29  """
30  Bitwise conversion between to python types
31  This is equivalently to
32  union {
33  Type_i i;
34  Type_o o;
35  } conversion;
36  conversion.i = input;
37  return conversion.o
38  @param i input data type (e.g. f for float)
39  @param o output data type (e.g. i for integer)
40  """
41  s = struct.pack('>' + i, value)
42  return struct.unpack('>' + o, s)[0]
43 
44 
45 def _decayHashFloatToInt(decayHash, decayHashExtended):
46  """
47  Convert decayHash and decayHashExtended 32 bit floats to an 64 bit integer
48  """
49  decayHashInt = _bitwiseConversion(np.float32(decayHash))
50  decayHashExtendedInt = _bitwiseConversion(np.float32(decayHashExtended))
51  decayHashFullInt = decayHashInt << 32
52  decayHashFullInt += decayHashExtendedInt
53  return decayHashFullInt
54 
55 
57  """
58  DecayHashMap using the C++ implementation of DecayTree and DecayNode
59  """
60 
61  def __init__(self, rootfile, removeRadiativeGammaFlag=False):
62  """Constructor"""
63  import root_numpy
64  ntuple = root_numpy.root2array(rootfile)
65  # self._removeGammaFlag = removeRadiativeGammaFlag
66 
67  self._string_string = {}
68 
69  self._forest_forest = {}
70  for decayHash, decayHashExtended, decayString in ntuple:
71  decayInt = Belle2.DecayForest.decayHashFloatToInt(decayHash, decayHashExtended)
72  if decayInt in self._string_string:
73  continue
74  self._string_string[decayInt] = decayString
75  self._forest_forest[decayInt] = Belle2.DecayForest(decayString, True, removeRadiativeGammaFlag)
76 
77  def get_string(self, decayHash, decayHashExtended):
78  """
79  Return DecayString given the decayHash and decayHashExtended
80  @param decayHash output of extraInfo(decayHash)
81  @param decayHashExtended output of extraInfo(decayHashExtended)
82  """
83  return self._string_string[Belle2.DecayForest.decayHashFloatToInt(decayHash, decayHashExtended)]
84 
85  def get_original_decay(self, decayHash, decayHashExtended):
86  """
87  Return original (MC) DecayTree given the decayHash and decayHashExtended
88  @param decayHash output of extraInfo(decayHash)
89  @param decayHashExtended output of extraInfo(decayHashExtended)
90  """
91  return self._forest_forest[Belle2.DecayForest.decayHashFloatToInt(decayHash, decayHashExtended)].getOriginalTree()
92 
93  def get_reconstructed_decay(self, decayHash, decayHashExtended):
94  """
95  Return reconstructed DecayTree given the decayHash and decayHashExtended
96  @param decayHash output of extraInfo(decayHash)
97  @param decayHashExtended output of extraInfo(decayHashExtended)
98  """
99  return self._forest_forest[Belle2.DecayForest.decayHashFloatToInt(decayHash, decayHashExtended)].getReconstructedTree()
100 
101  def print_hash(self, decayHash, decayHashExtended):
102  """
103  Print the DecayString in a fancy way given the decayHash and decayHashExtended
104  @param decayHash output of extraInfo(decayHash)
105  @param decayHashExtended output of extraInfo(decayHashExtended)
106  """
107  entry = self.get_stringget_string(decayHash, decayHashExtended)
108  entries = entry.split('|')
109  all_particles = re.findall(r"(-?[0-9]+)", entries[0])
110 
111  if len(all_particles) != len(entries) - 1:
112  print(entry)
113  raise RuntimeError("Bad format of decay string: " +
114  str(len(all_particles)) + " " + str(len(entries)) + " " + str(entries))
115 
116  table = []
117  table.append(["Decay ", prettify_pdg_codes(entries[0])])
118  for particle, mc_decay_string in zip(all_particles, entries[1:]):
119  table.append([prettify_pdg_codes(particle), prettify_pdg_codes(mc_decay_string)])
120 
121  basf2.pretty_print_table(table, column_widths=[6, '*'])
122 
123 
124 def _pdg_to_name(x):
125  """
126  Convert PDG code to a name
127  @param a pdg code
128  """
129  selected = False
130  if x[0] == '^':
131  selected = True
132  x = x[1:]
133 
134  pdg_code = int(x)
135  pdg_string = str(pdg_code)
136  try:
137  pdg_string = pdg.to_name(pdg_code)
138  except BaseException:
139  pass
140 
141  if selected:
142  if pybasf2.LogPythonInterface.terminal_supports_colors():
143  return '\x1b[31m' + pdg_string + '\x1b[0m'
144  else:
145  return '^' + pdg_string
146  return pdg_string
147 
148 
149 def prettify_pdg_codes(text):
150  """
151  Prettifiy a string containing PDG codes by replacing PDG codes
152  with their corresponding names.
153  @param text the text
154  """
155  text = re.sub(r"(\^?-?[0-9]+)", lambda x: _pdg_to_name(x.group(0)), text)
156  text = text.replace('gamma', 'g').replace('--> ', '').replace('anti-', 'a-')
157  text = text.replace('Upsilon', 'Y').replace(') ', ')').replace(' (', '(')
158  return text
Contains several DecayTree objects, which belong all to the same candidate.
Definition: DecayForest.h:24
static int decayHashFloatToInt(float decayHash, float decayHashExtended)
Convert DecayHashes outputted by ParticleMCDecayString module to an integer.
Definition: DecayForest.cc:43
_forest
Dict Int -> Reconstructed DecayTree.
Definition: decayHash.py:69
_string
Dict Int -> DecayStrings.
Definition: decayHash.py:67
def get_original_decay(self, decayHash, decayHashExtended)
Definition: decayHash.py:85
def get_reconstructed_decay(self, decayHash, decayHashExtended)
Definition: decayHash.py:93
def __init__(self, rootfile, removeRadiativeGammaFlag=False)
Definition: decayHash.py:61
def get_string(self, decayHash, decayHashExtended)
Definition: decayHash.py:77
def print_hash(self, decayHash, decayHashExtended)
Definition: decayHash.py:101
def to_name(pdg)
Definition: pdg.py:86