Belle II Software development
b2biiConversion.py
1#!/usr/bin/env python3
2
3
10
11import basf2 as b2
12import b2bii
13from modularAnalysis import setAnalysisConfigParams
14import os
15import re
16import requests
17from ctypes import cdll
18
19
20def 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
39def 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
176def 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 >>> parse_process_url("http://bweb3.cc.kek.jp/mdst.php?ex=65&rs=1&re=30&skm=ypipi")
198 []
199
200 If the URL cannot be found an error is raised and an empty list is returned.
201 Also for other http errors or non existing urls
202
203 >>> parse_process_url("http://httpbin.org/status/404")
204 []
205 >>> parse_process_url("http://httpbin.org/status/500")
206 []
207 >>> parse_process_url("http://nosuchurl")
208 []
209 """
210
211 if isinstance(url, list) or isinstance(url, tuple):
212 return url
213
214 if not url.startswith("http://") and not url.startswith("https://"):
215 if os.path.exists(url):
216 return [url]
217 else:
218 b2.B2ERROR(
219 f"Could not parse url '{url}': no such file or directory")
220 return []
221
222 # regular expression to find process_event lines in html response
223 process_event = re.compile(br"^\s*process_event\s+(.*)\s+0$", re.MULTILINE)
224 # get the url
225 try:
226 request = requests.get(url)
227 request.raise_for_status()
228 return [e.decode("ASCII")
229 for e in process_event.findall(request.content)]
230 except (requests.ConnectionError, requests.HTTPError) as e:
231 b2.B2ERROR(
232 f"Failed to connect to '{url}': {str(e)}")
233
234 return []
235
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