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