Belle II Software  release-08-01-10
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_phokhara_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, eventType='eetautau')
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-', eventType='mumumumu')
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, eventType='mumutautau')
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, eventType='tautautautau')
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-', eventType='eepipi')
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-', eventType='eeKK')
43  rename_module_in_path(path, 'TrepsInput', 'TREPS_eeKK')
44  elif event_code is EventCode.eepp:
45  add_treps_generator(path, 'e+e-ppbar', eventType='eeppbar')
46  rename_module_in_path(path, 'TrepsInput', 'TREPS_eepp')
47  elif event_code is EventCode.pipiISR:
48  add_phokhara_generator(path, 'pi+pi-', eventType='pipiISR')
49  elif event_code is EventCode.pipipi0ISR:
50  add_phokhara_generator(path, 'pi+pi-pi0', eventType='pipipi0ISR')
51  elif event_code is EventCode.pipipipiISR:
52  add_phokhara_generator(path, 'pi+pi-pi+pi-', eventType='pipipipiISR')
53  elif event_code is EventCode.pipipi0pi0ISR:
54  add_phokhara_generator(path, 'pi+pi-pi0pi0', eventType='pipipi0pi0ISR')
55  elif event_code is EventCode.pipietaISR:
56  add_phokhara_generator(path, 'pi+pi-eta', eventType='pipietaISR')
57  elif event_code is EventCode.KKISR:
58  add_phokhara_generator(path, 'K+K-', eventType='KKISR')
59  elif event_code is EventCode.K0K0barISR:
60  add_phokhara_generator(path, 'K0K0bar', eventType='K0K0barISR')
61  elif event_code is EventCode.ppbarISR:
62  add_phokhara_generator(path, 'ppbar', eventType='ppbarISR')
63 
64 
65 def get_event_ranges(events, event_codes=None):
66  """
67  Get event range for channels to be generated. The number of events of each channel is determined by:
68  channel cross-section / total cross-section of all channels assigned to the same basf2 job.
69 
70  Parameters:
71  events (int): Total number of events
72  event_codes (Iterable): tuple or list of EventCode.
73  Return:
74  a dictionary with EvenCode as the key and tuple of event range as value.
75  """
76  total_cross_section = sum(EventCode_CrossSection[e] for e in event_codes)
77  lower_range_delimiter = 0
78  return_dict = {}
79  for e in event_codes:
80  weight = EventCode_CrossSection[e] / total_cross_section
81  # Check if this is the last event code: in case, close the range and return.
82  if e == event_codes[len(event_codes) - 1]:
83  return_dict[e] = (lower_range_delimiter, events + 1)
84  return return_dict
85  events_in_range = round(events * weight)
86  return_dict[e] = (lower_range_delimiter, lower_range_delimiter + events_in_range)
87  lower_range_delimiter += events_in_range
88 
89 
90 def rename_module_in_path(path, module_type, new_module_name):
91  """
92  Helper function to rename a module named with its type.
93  Parameters:
94  path (basf2.Path): path where a module to be renamed
95  module_type (str): default module name which is also module.type()
96  new_module_name (str): new module name
97  """
98  for module in path.modules():
99  if module.type() == module_type:
100  module.set_name(new_module_name)
101 
102 
104  """
105  Module to set ``eventExtraInfo(EventCode)`` according to event range
106  of each channel.
107 
108  Parameters:
109  event_codes (Iterable): tuple or list of EventCode.
110  """
111 
112  def __init__(self, event_codes):
113  """
114  Initialize the class
115  Parameters:
116  event_codes (Iterable): tuple or list of EventCode.
117  """
118  import ROOT # noqa
119  super(EventRangePathSplitter, self).__init__()
120 
121  self.event_codesevent_codes = event_codes
122 
123  self.event_extra_infoevent_extra_info = ROOT.Belle2.PyStoreObj('EventExtraInfo')
124 
125  self.event_rangesevent_ranges = None
126 
127  self.event_numberevent_number = -1
128 
129  def initialize(self):
130  """
131  Initialize module before any events are processed
132  """
133  import ROOT # noqa
134  self.event_rangesevent_ranges = get_event_ranges(ROOT.Belle2.Environment.Instance().getNumberOfEvents(), self.event_codesevent_codes)
135  self.event_extra_infoevent_extra_info.registerInDataStore()
136 
137  def beginRun(self):
138  """Begin run method of the module"""
139  self.event_numberevent_number = -1
140 
141  def event(self):
142  """Event method of the module"""
143  self.event_numberevent_number += 1
144  if not self.event_extra_infoevent_extra_info.isValid():
145  self.event_extra_infoevent_extra_info.create()
146  elif self.event_extra_infoevent_extra_info.hasExtraInfo('EventCode'):
147  B2FATAL('The EventExtraInfo object has already an EventCode field registered.')
148  for event_code, event_range in self.event_rangesevent_ranges.items():
149  if (event_range[0] <= self.event_numberevent_number < event_range[1]):
150  self.event_extra_infoevent_extra_info.setExtraInfo('EventCode', event_code.value)
151  self.return_value(event_code.value)
152  return
153  # This should never happen.
154  self.return_value(0)
155 
156 
157 class ExtraInfoPathSplitter(Module):
158  """
159  Helper module to return True if the value from ``eventExtraInfo(EventCode)``
160  is included in the event_codes parameter.
161 
162  Parameters:
163  event_codes (Iterable): tuple or list of EventCode.
164  """
165 
166  def __init__(self, event_codes):
167  """
168  Initialize the class
169  Parameters:
170  event_codes (Iterable): tuple or list of EventCode.
171  """
172  import ROOT # noqa
173  super(ExtraInfoPathSplitter, self).__init__()
174 
175  self.event_codesevent_codes = [e.value for e in event_codes]
176 
177  self.event_extra_infoevent_extra_info = ROOT.Belle2.PyStoreObj('EventExtraInfo')
178 
179  def initialize(self):
180  """
181  Initialize module before any events are processed
182  """
183  self.event_extra_infoevent_extra_info.isRequired()
184 
185  def event(self):
186  """Event method of the module"""
187  if not self.event_extra_infoevent_extra_info.hasExtraInfo('EventCode'):
188  B2FATAL('The EventExtraInfo object has no EventCode field registered.')
189  if self.event_extra_infoevent_extra_info.getExtraInfo('EventCode') in self.event_codesevent_codes:
190  self.return_value(1)
191  else:
192  self.return_value(0)
event_ranges
Dictionary to get number of events for each event code.
Definition: utils.py:125
event_extra_info
PyStoreObj off EventExtraInfo.
Definition: utils.py:123
event_extra_info
PyStoreObj for EventExtraInfo to save event codes.
Definition: utils.py:177