Belle II Software  release-08-01-10
b2biiConversion.py
1 #!/usr/bin/env python3
2 
3 
10 
11 import basf2 as b2
12 import b2bii
13 from modularAnalysis import setAnalysisConfigParams
14 import os
15 import re
16 import requests
17 from ctypes import cdll
18 
19 
20 def setupBelleDatabaseServer():
21  """
22  Sets the Belle DB server to the one recommended in /sw/belle/local/var/belle_postgres_server.
23 
24  If the user does not have the access rights to the above file, the can01 server is set by default.
25  """
26  belleDBServerFile = '/sw/belle/local/var/belle_postgres_server'
27  belleDBServer = 'can01'
28 
29  try:
30  with open(belleDBServerFile) as f:
31  belleDBServer = (f.read()).strip()
32  except OSError:
33  pass
34 
35  os.environ['PGUSER'] = 'g0db'
36  os.environ['BELLE_POSTGRES_SERVER'] = belleDBServer
37 
38 
39 def convertBelleMdstToBelleIIMdst(inputBelleMDSTFile, applySkim=True,
40  saveResultExtraInfo=False,
41  useBelleDBServer=None,
42  convertBeamParameters=True,
43  generatorLevelReconstruction=False,
44  generatorLevelMCMatching=False,
45  path=None, entrySequences=None,
46  matchType2E9oE25Threshold=-1.1,
47  enableNisKsFinder=True,
48  HadronA=True, HadronB=True,
49  enableRecTrg=False, enableEvtcls=True,
50  SmearTrack=2, enableLocalDB=True,
51  convertNbar=False):
52  """
53  Loads Belle MDST file and converts in each event the Belle MDST dataobjects to Belle II MDST
54  data objects and loads them to the StoreArray.
55 
56  Args:
57  inputBelleMDSTFile (str): Name of the file(s) to be loaded.
58  applySkim (bool): Apply skim conditions in B2BIIFixMdst.
59  saveResultExtraInfo (bool): Save B2BIIFixMdst module return value as EventExtraInfo.
60  useBelleDBServer (str): None to use the recommended BelleDB server.
61  convertBeamParameters (bool): Convert beam parameters or use information stored in Belle II database.
62  generatorLevelReconstruction (bool): Enables to bypass skims and corrections applied in B2BIIFixMdst.
63  generatorLevelMCMatching (bool): Enables to switch MCTruth matching to generator-level particles.
64  This is recommended for analyses with gammas in the final state.
65  path (basf2.Path): Path to add modules in.
66  entrySequences (list(str)): The number sequences (e.g. 23:42,101) defining
67  the entries which are processed for each inputFileName.
68  matchType2E9oE25Threshold (float): Clusters with a E9/E25 value above this threshold are classified as neutral
69  even if tracks are matched to their connected region (matchType == 2 in basf).
70  enableNisKsFinder (bool): Enables to convert nisKsFinder information.
71  HadronA (bool): Enables to switch on HadronA skim in B2BIIFixMdst module.
72  HadronB (bool): Enables to switch on HadronB skim in B2BIIFixMdst module.
73  enableRecTrg (bool): Enables to convert RecTrg_summary3 table.
74  enableEvtcls (bool): Enables to convert Evtcls and Evtcls_hadronic tables.
75  SmearTrack (float): Smear the MC tracks to match real data.
76  Apart from the recommended default value of 2 it can also be set to 1.
77  Details about the difference between those two options can be found
78  `here <https://belle.kek.jp/secured/wiki/doku.php?id=physics:charm:tracksmearing>`_.
79  Set to 0 to skip smearing (automatically set to 0 internally for real data).
80  enableLocalDB (bool): Enables to use local payloads.
81  convertNbar (bool): Enables conversion of anti-n0:mdst.
82  """
83 
84  # If we are on KEKCC make sure we load the correct NeuroBayes library
85  try:
86  cdll.LoadLibrary(
87  '/sw/belle/local/neurobayes/lib/libNeuroBayesCore_shared.so')
88  except BaseException:
89  pass
90 
91  if useBelleDBServer is None:
92  setupBelleDatabaseServer()
93  else:
94  os.environ['BELLE_POSTGRES_SERVER'] = useBelleDBServer
95 
96  b2.B2INFO('Belle DB server is set to: ' + os.environ['BELLE_POSTGRES_SERVER'])
97 
98  setAnalysisConfigParams({'mcMatchingVersion': 'Belle'}, path)
99 
101 
102  if enableLocalDB is True:
103  b2.conditions.metadata_providers = ["/sw/belle/b2bii/database/conditions/b2bii.sqlite"]
104  b2.conditions.payload_locations = ["/sw/belle/b2bii/database/conditions/"]
105  else:
106  b2.B2WARNING(
107  "B2BII is accessing the payloads from the conditions database.\n"
108  "The recommended procedure is to use the offline database and it is significantly\n"
109  "faster than using the global database.\n"
110  "If you need the payloads which are not included in the current offline database,\n"
111  "please contact b2bii librarian.")
112 
113  input = b2.register_module('B2BIIMdstInput')
114  if inputBelleMDSTFile is not None:
115  input.param('inputFileNames', parse_process_url(inputBelleMDSTFile))
116  if entrySequences is not None:
117  input.param('entrySequences', entrySequences)
118  # input.logging.set_log_level(LogLevel.DEBUG)
119  # input.logging.set_info(LogLevel.DEBUG, LogInfo.LEVEL | LogInfo.MESSAGE)
120  path.add_module(input)
121 
122  # we need magnetic field which is different than default.
123  # shamelessly copied from analysis/scripts/modularAnalysis.py:inputMdst
124  from ROOT import Belle2 # reduced scope of potentially-misbehaving import
125  from ROOT.Math import XYZVector
126  field = Belle2.MagneticField()
127  field.addComponent(
129  XYZVector(0, 0, 1.5 * Belle2.Unit.T)))
130  Belle2.DBStore.Instance().addConstantOverride("MagneticField", field, False)
131 
132  if (not generatorLevelReconstruction):
133  # Fix MSDT Module
134  fix = b2.register_module('B2BIIFixMdst')
135  # fix.logging.set_log_level(LogLevel.DEBUG)
136  # fix.logging.set_info(LogLevel.DEBUG, LogInfo.LEVEL | LogInfo.MESSAGE)
137  fix.param('SaveResultExtraInfo', saveResultExtraInfo)
138  # Hadron skim settings
139  fix.param('HadronA', HadronA)
140  fix.param('HadronB', HadronB)
141  fix.param('Smear_trk', SmearTrack)
142  if (HadronA is not True and HadronB is True):
143  b2.B2WARNING(
144  'The Hadron A skim is turned off.'
145  'However, its requirements are still applied since the HadronB(J) skim, which includes them, is turned on.')
146  path.add_module(fix)
147 
148  if(applySkim):
149  emptypath = b2.create_path()
150  # discard 'bad events' marked by fixmdst
151  fix.if_value('<=0', emptypath)
152  else:
153  b2.B2INFO('applySkim is set to be False.'
154  'No bad events marked by fixmdst will be discarded.'
155  'Corrections will still be applied.')
156  else:
157  b2.B2INFO('Perform generator level reconstruction, no corrections or skims in fix_mdst will be applied.')
158  # Convert MDST Module
159  convert = b2.register_module('B2BIIConvertMdst')
160  convert.param('convertBeamParameters', convertBeamParameters)
161  if (generatorLevelMCMatching):
162  convert.param('mcMatchingMode', 'GeneratorLevel')
163  convert.param("matchType2E9oE25Threshold", matchType2E9oE25Threshold)
164  convert.param("nisKsInfo", enableNisKsFinder)
165  convert.param("RecTrg", enableRecTrg)
166  convert.param("convertEvtcls", enableEvtcls)
167  convert.param("convertNbar", convertNbar)
168  # convert.logging.set_log_level(LogLevel.DEBUG)
169  # convert.logging.set_info(LogLevel.DEBUG, LogInfo.LEVEL | LogInfo.MESSAGE)
170  path.add_module(convert)
171  if convertNbar:
172  b2.conditions.append_globaltag('BellePID')
173  path.add_module('BelleNbarMVA', particleList='anti-n0:mdst', identifier='nbarMVA')
174 
175 
176 def parse_process_url(url):
177  """
178  Handle process_url style requests.
179  If url is a list just return it without looking at it. If the url starts
180  with http(s):// return the list of files provided by that url, otherwise
181  check if a file with the name given as url exists and return this as a list
182  with one item. If not such file exists return an empty list
183 
184  >>> parse_process_url(["foo", "bar"])
185  ['foo', 'bar']
186  >>> parse_process_url("/dev/null")
187  ['/dev/null']
188  >>> parse_process_url("missing_file.mdst")
189  []
190  >>> parse_process_url("http://bweb3.cc.kek.jp/mdst.php?ex=55&rs=1&re=5&skm=HadronBorJ&dt=on_resonance&bl=caseB") \
191  # doctest: +NORMALIZE_WHITESPACE
192  ['/group/belle/bdata_b/dstprod/dat/e000055/HadronBJ/0127/on_resonance/00/HadronBJ-e000055r000003-b20090127_0910.mdst',
193  '/group/belle/bdata_b/dstprod/dat/e000055/HadronBJ/0127/on_resonance/00/HadronBJ-e000055r000004-b20090127_0910.mdst',
194  '/group/belle/bdata_b/dstprod/dat/e000055/HadronBJ/0127/on_resonance/00/HadronBJ-e000055r000005-b20090127_0910.mdst']
195 
196  Some files are missing and thus marked with "### LOST ###", make sure we don't pick them up
197 
198  >>> parse_process_url("http://bweb3.cc.kek.jp/mdst.php?ex=65&rs=1&re=30&skm=ypipi")
199  []
200 
201  If the URL cannot be found an error is raised and an empty list is returned.
202  Also for other http errors or non existing urls
203 
204  >>> parse_process_url("http://httpbin.org/status/404")
205  []
206  >>> parse_process_url("http://httpbin.org/status/500")
207  []
208  >>> parse_process_url("http://nosuchurl")
209  []
210  """
211 
212  if isinstance(url, list) or isinstance(url, tuple):
213  return url
214 
215  if not url.startswith("http://") and not url.startswith("https://"):
216  if os.path.exists(url):
217  return [url]
218  else:
219  b2.B2ERROR(
220  "Could not parse url '{}': no such file or directory".format(url))
221  return []
222 
223  # regular expression to find process_event lines in html response
224  process_event = re.compile(br"^\s*process_event\s+(.*)\s+0$", re.MULTILINE)
225  # get the url
226  try:
227  request = requests.get(url)
228  request.raise_for_status()
229  return [e.decode("ASCII")
230  for e in process_event.findall(request.content)]
231  except (requests.ConnectionError, requests.HTTPError) as e:
232  b2.B2ERROR(
233  "Failed to connect to '{url}': {message}".format(
234  url=url, message=str(e)))
235 
236  return []
def setB2BII()
Definition: b2bii.py:21
Describe one component of the Geometry.
Magnetic field map.
Definition: MagneticField.h:32
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:28