Belle II Software  release-08-00-05
utils.py
1 
8 from .constants import EventCode, EventCode_CrossSection, EventCodes
9 
10 from basf2 import B2FATAL, Module
11 from generators import add_aafh_generator, add_koralw_generator, add_treps_generator
12 
13 
14 def add_low_multiplicity_generator(path, event_code):
15  """
16  Add dedicated generator based on EventCode.
17  Module name is also changed to avoid conflicts
18 
19  Parameters:
20  path (basf2.Path): path where generators should be added
21  event_code (EventCode): EventCode integer to identify a channel
22  """
23 
24  if event_code not in EventCodes:
25  B2FATAL(f'The event code {event_code} is unknown.')
26  if event_code is EventCode.eetautau:
27  add_aafh_generator(path, 'e+e-tau+tau-', enableTauDecays=False)
28  rename_module_in_path(path, 'AafhInput', 'AAFH_eetautau')
29  elif event_code is EventCode.mumumumu:
30  add_aafh_generator(path, 'mu+mu-mu+mu-')
31  rename_module_in_path(path, 'AafhInput', 'AAFH_mumumumu')
32  elif event_code is EventCode.mumutautau:
33  add_aafh_generator(path, 'mu+mu-tau+tau-', enableTauDecays=False)
34  rename_module_in_path(path, 'AafhInput', 'AAFH_mumutautau')
35  elif event_code is EventCode.tautautautau:
36  add_koralw_generator(path, 'tau+tau-tau+tau-', enableTauDecays=False)
37  rename_module_in_path(path, 'KoralWInput', 'KoralW_tautautautau')
38  elif event_code is EventCode.eepipi:
39  add_treps_generator(path, 'e+e-pi+pi-')
40  rename_module_in_path(path, 'TrepsInput', 'TREPS_eepipi')
41  elif event_code is EventCode.eeKK:
42  add_treps_generator(path, 'e+e-K+K-')
43  rename_module_in_path(path, 'TrepsInput', 'TREPS_eeKK')
44  elif event_code is EventCode.eepp:
45  add_treps_generator(path, 'e+e-ppbar')
46  rename_module_in_path(path, 'TrepsInput', 'TREPS_eepp')
47  elif event_code is EventCode.pipiISR:
48  m = path.add_module('PhokharaInput', FinalState=1, LO=0, NLO=1, QED=0, MinInvMassHadrons=0.)
49  m.set_name('PHOKHARA_pipiISR')
50  elif event_code is EventCode.pipipi0ISR:
51  m = path.add_module('PhokharaInput', FinalState=8, LO=0, NLO=1, QED=0, MinInvMassHadrons=0.)
52  m.set_name('PHOKHARA_pipipi0ISR')
53  elif event_code is EventCode.pipipipiISR:
54  m = path.add_module('PhokharaInput', FinalState=3, LO=0, NLO=1, QED=0, MinInvMassHadrons=0.)
55  m.set_name('PHOKHARA_pipipipiISR')
56  elif event_code is EventCode.pipipi0pi0ISR:
57  m = path.add_module('PhokharaInput', FinalState=2, LO=0, NLO=1, QED=0, MinInvMassHadrons=0.)
58  m.set_name('PHOKHARA_pipipi0pi0ISR')
59  elif event_code is EventCode.etapipiISR:
60  m = path.add_module('PhokharaInput', FinalState=10, LO=0, NLO=1, QED=0, MinInvMassHadrons=0.)
61  m.set_name('PHOKHARA_etapipiISR')
62  elif event_code is EventCode.KKISR:
63  m = path.add_module('PhokharaInput', FinalState=6, LO=0, NLO=1, QED=0, MinInvMassHadrons=0.)
64  m.set_name('PHOKHARA_KKISR')
65  elif event_code is EventCode.K0K0barISR:
66  m = path.add_module('PhokharaInput', FinalState=7, LO=0, NLO=1, QED=0, MinInvMassHadrons=0.)
67  m.set_name('PHOKHARA_K0K0barISR')
68  elif event_code is EventCode.ppbarISR:
69  m = path.add_module('PhokharaInput', FinalState=4, LO=0, NLO=1, QED=0, MinInvMassHadrons=0.)
70  m.set_name('PHOKHARA_ppbarISR')
71 
72 
73 def get_event_ranges(events, event_codes=None):
74  """
75  Get event range for channels to be generated. The number of events of each channel is determined by:
76  channel cross-section / total cross-section of all channels assigned to the same basf2 job.
77 
78  Parameters:
79  events (int): Total number of events
80  event_codes (Iterable): tuple or list of EventCode.
81  Return:
82  a dictionary with EvenCode as the key and tuple of event range as value.
83  """
84  total_cross_section = sum(EventCode_CrossSection[e] for e in event_codes)
85  lower_range_delimiter = 0
86  return_dict = {}
87  for e in event_codes:
88  weight = EventCode_CrossSection[e] / total_cross_section
89  # Check if this is the last event code: in case, close the range and return.
90  if e == event_codes[len(event_codes) - 1]:
91  return_dict[e] = (lower_range_delimiter, events + 1)
92  return return_dict
93  events_in_range = round(events * weight)
94  return_dict[e] = (lower_range_delimiter, lower_range_delimiter + events_in_range)
95  lower_range_delimiter += events_in_range
96 
97 
98 def rename_module_in_path(path, module_type, new_module_name):
99  """
100  Helper function to rename a module named with its type.
101  Parameters:
102  path (basf2.Path): path where a module to be renamed
103  module_type (str): default module name which is also module.type()
104  new_module_name (str): new module name
105  """
106  for module in path.modules():
107  if module.type() == module_type:
108  module.set_name(new_module_name)
109 
110 
112  """
113  Module to set ``eventExtraInfo(EventCode)`` according to event range
114  of each channel.
115 
116  Parameters:
117  event_codes (Iterable): tuple or list of EventCode.
118  """
119 
120  def __init__(self, event_codes):
121  """
122  Initialize the class
123  Parameters:
124  event_codes (Iterable): tuple or list of EventCode.
125  """
126  import ROOT # noqa
127  super(EventRangePathSplitter, self).__init__()
128 
129  self.event_codesevent_codes = event_codes
130 
131  self.event_extra_infoevent_extra_info = ROOT.Belle2.PyStoreObj('EventExtraInfo')
132 
133  self.event_rangesevent_ranges = None
134 
135  self.event_numberevent_number = -1
136 
137  def initialize(self):
138  """
139  Initialize module before any events are processed
140  """
141  import ROOT # noqa
142  self.event_rangesevent_ranges = get_event_ranges(ROOT.Belle2.Environment.Instance().getNumberOfEvents(), self.event_codesevent_codes)
143  self.event_extra_infoevent_extra_info.registerInDataStore()
144 
145  def beginRun(self):
146  """Begin run method of the module"""
147  self.event_numberevent_number = -1
148 
149  def event(self):
150  """Event method of the module"""
151  self.event_numberevent_number += 1
152  if not self.event_extra_infoevent_extra_info.isValid():
153  self.event_extra_infoevent_extra_info.create()
154  elif self.event_extra_infoevent_extra_info.hasExtraInfo('EventCode'):
155  B2FATAL('The EventExtraInfo object has already an EventCode field registered.')
156  for event_code, event_range in self.event_rangesevent_ranges.items():
157  if (event_range[0] <= self.event_numberevent_number < event_range[1]):
158  self.event_extra_infoevent_extra_info.setExtraInfo('EventCode', event_code.value)
159  self.return_value(event_code.value)
160  return
161  # This should never happen.
162  self.return_value(0)
163 
164 
165 class ExtraInfoPathSplitter(Module):
166  """
167  Helper module to return True if the value from ``eventExtraInfo(EventCode)``
168  is included in the event_codes parameter.
169 
170  Parameters:
171  event_codes (Iterable): tuple or list of EventCode.
172  """
173 
174  def __init__(self, event_codes):
175  """
176  Initialize the class
177  Parameters:
178  event_codes (Iterable): tuple or list of EventCode.
179  """
180  import ROOT # noqa
181  super(ExtraInfoPathSplitter, self).__init__()
182 
183  self.event_codesevent_codes = [e.value for e in event_codes]
184 
185  self.event_extra_infoevent_extra_info = ROOT.Belle2.PyStoreObj('EventExtraInfo')
186 
187  def initialize(self):
188  """
189  Initialize module before any events are processed
190  """
191  self.event_extra_infoevent_extra_info.isRequired()
192 
193  def event(self):
194  """Event method of the module"""
195  if not self.event_extra_infoevent_extra_info.hasExtraInfo('EventCode'):
196  B2FATAL('The EventExtraInfo object has no EventCode field registered.')
197  if self.event_extra_infoevent_extra_info.getExtraInfo('EventCode') in self.event_codesevent_codes:
198  self.return_value(1)
199  else:
200  self.return_value(0)
event_ranges
Dictionary to get number of events for each event code.
Definition: utils.py:133
event_extra_info
PyStoreObj off EventExtraInfo.
Definition: utils.py:131
event_extra_info
PyStoreObj for EventExtraInfo to save event codes.
Definition: utils.py:185