19from ROOT
import Belle2
20from rundb
import RunDB
26def getCollidingPatternFromFiles(herFilePath, lerFilePath):
28 Take HER and LER filling pattern
from file
and perform AND operation to take only colliding buckets.
30 The format
is the one given by the accelerator people. The first column
is the number of the bunch,
31 the second
is 1.0000
or .0000 depending on whether the bunch
is filled
or not. The third column
is extra.
34 herFile = open(herFilePath)
35 herLines = herFile.readlines()
37 lerFile = open(lerFilePath)
38 lerLines = lerFile.readlines()
42 for lineHer, lineLer
in zip(herLines, lerLines):
43 if(lineHer[0] ==
"#"):
46 if(lineHer.split()[1] ==
'1.0000' and lineLer.split()[1] ==
'1.0000'):
54def getCollidingPattern(herFPHex, lerFPHex):
55 """Take LER and HER hexadecimal fill pattern, convert to binary and perform AND operation to take only colliding buckets"""
57 herFPBin = bin(int(herFPHex, 16))
58 herFPBin = herFPBin.replace(
'0b',
'')
60 lerFPBin = bin(int(lerFPHex, 16))
61 lerFPBin = lerFPBin.replace(
'0b',
'')
63 return [int(h) & int(l)
for h, l
in zip(herFPBin, lerFPBin)]
66def fill(fillPattern, firstExp, firstRun, lastExp, lastRun):
67 """Create a payload fill pattern for the given run range"""
69 if fillPattern
is None:
75 for num, bucket
in enumerate(fillPattern):
77 bunches.setBucket(num)
83 db.storeData(
"BunchStructure", bunches, iov)
86 basf2.B2INFO(f
"Filling new payload. iov: {firstExp} {firstRun} {lastExp} {lastRun}")
88 basf2.B2INFO(f
"Filling new payload with default filling pattern. iov:{firstExp} {firstRun} {lastExp} {lastRun}\n")
95if __name__ ==
"__main__":
97 parser = argparse.ArgumentParser(description=
'Create bunch structure payload taking information from the RunDB')
98 parser.add_argument(
'minExp', metavar=
'minExp', type=int,
99 help=
'first experiment. Use only this argument to produce filling pattern for experiment 0 or 1003')
100 parser.add_argument(
'minRun', metavar=
'minRun', type=int, nargs=
'?',
102 parser.add_argument(
'maxExp', metavar=
'maxExp', type=int, nargs=
'?',
103 help=
'last experiment')
104 parser.add_argument(
'maxRun', metavar=
'maxRun', type=int, nargs=
'?',
109 metavar=
'<exp> <run>',
115 help=
'Change run and experiment of the filling pattern to be used for early phase 3 \
116 run-independent MC (exp 1003). (default: %(default)s)')
119 '--patternFromFiles',
120 dest=
'patternFromFiles',
121 metavar=
'<herFile> <lerFile>',
124 help=
'Use external files to create filling pattern. The format is the one given by accelerator group')
131 help=
"Don't fill the gaps between physic iovs with default filling pattern")
133 args = parser.parse_args()
135 if(args.minExp == 0):
138 if(args.patternFromFiles):
139 basf2.B2INFO(
"Using external files")
140 pattern = getCollidingPatternFromFiles(args.patternFromFiles[0], args.patternFromFiles[1])
141 fill(pattern, 0, 0, 0, -1)
145 for b
in range(0, 5120, 2):
148 if((b % 300 == 0) & (b != 0)):
151 bunches.setBucket(b + extraStep)
156 db.storeData(
"BunchStructure", bunches, iov)
158 elif(args.minExp == 1003):
160 if(args.patternFromFiles):
161 basf2.B2INFO(
"Using external files")
162 pattern = getCollidingPatternFromFiles(args.patternFromFiles[0], args.patternFromFiles[1])
165 username = input(
"Enter your DESY username:")
166 rundb = RunDB(username=username)
168 basf2.B2INFO(f
"Use exp {args.exprun1003[0]} and run {args.exprun1003[1]} for early phase 3 run-independent MC")
170 runInfo = rundb.get_run_info(
171 min_experiment=args.exprun1003[0],
172 max_experiment=args.exprun1003[0],
173 min_run=args.exprun1003[1],
174 max_run=args.exprun1003[1],
180 pattern = getCollidingPattern(it[
'her'][
'fill_pattern'], it[
'ler'][
'fill_pattern'])
182 fill(pattern, 1003, 0, 1003, -1)
184 elif(args.patternFromFiles):
185 basf2.B2INFO(
"Using external files")
186 pattern = getCollidingPatternFromFiles(args.patternFromFiles[0], args.patternFromFiles[1])
187 fill(pattern, args.minExp, args.minRun, args.maxExp, args.maxRun)
190 username = input(
"Enter your DESY username: ")
191 rundb = RunDB(username=username)
198 runInfo = rundb.get_run_info(
199 min_experiment=minexp,
200 max_experiment=maxexp,
207 current_pattern =
None
208 current_start =
None,
None
211 current_end = minexp, minrun
216 lastEnd = minexp, minrun
221 exprun = it[
'experiment'], it[
'run']
223 if(it[
'her'][
'fill_pattern'] ==
"" or it[
'ler'][
'fill_pattern'] ==
""):
224 basf2.B2WARNING(f
"Filling pattern for Exp {exprun[0]} Run {exprun[1]} is empty. \
225 Previous filling pattern will be used instead.")
228 pattern = getCollidingPattern(it[
'her'][
'fill_pattern'], it[
'ler'][
'fill_pattern'])
231 if pattern != current_pattern:
233 if(args.dontFillGaps
is False and current_start[0]
is not None
234 and current_start[1] != lastEnd[1] + 1
and current_start[1] != lastEnd[1]):
235 fill(
"", lastEnd[0], lastEnd[1] + 1, current_start[0], current_start[1] - 1)
238 fill(current_pattern, *current_start, *current_end)
240 if current_pattern
is not None:
241 basf2.B2INFO(f
"Corresponding to {lumi/1000.:.2f} pb-1\n")
243 lumiDic[
''.join(str(i)
for i
in current_pattern)][
"iovs"].append([*current_start, *current_end])
246 keyFP =
''.join(str(i)
for i
in pattern)
248 if(keyFP
in lumiDic):
249 lumiDic[keyFP][
"lumi"] += it[
'statistics'][
'lumi_recorded']
253 lumiDic[keyFP][
"lumi"] = it[
'statistics'][
'lumi_recorded']
254 lumiDic[keyFP][
"lerBunches"] = it[
'ler'][
'number_of_bunches']
255 lumiDic[keyFP][
"herBunches"] = it[
'her'][
'number_of_bunches']
256 lumiDic[keyFP][
"iovs"] = []
258 lumi = it[
'statistics'][
'lumi_recorded']
261 lastEnd = current_end
264 current_pattern = pattern
265 current_start = exprun
271 lumi += it[
'statistics'][
'lumi_recorded']
272 lumiDic[
''.join(str(i)
for i
in current_pattern)][
"lumi"] += it[
'statistics'][
'lumi_recorded']
275 if(args.dontFillGaps
is False and current_start[0]
is not None and current_start[1] != lastEnd[1] + 1):
276 fill(
"", lastEnd[0], lastEnd[1] + 1, current_start[0], current_start[1] - 1)
278 fill(current_pattern, *current_start, *current_end)
279 basf2.B2INFO(f
"Corresponding to {lumi/1000.:.2f} pb-1\n")
280 lumiDic[
''.join(str(i)
for i
in current_pattern)][
"iovs"].append([*current_start, *current_end])
282 if(args.dontFillGaps
is False and current_end[1] != maxrun):
283 fill(
"", current_end[0], current_end[1] + 1, maxexp, maxrun)
286 fill(
"", maxexp, maxrun + 1, -1, -1)
289 basf2.B2INFO(
"Summary:\n")
291 for k, v
in collections.OrderedDict(sorted(lumiDic.items(), key=
lambda t: t[1][
"lumi"], reverse=
True)).items():
293 basf2.B2INFO(f
"{i} Filling pattern")
294 basf2.B2INFO(f
" lumi {v['lumi']/1000.:.2f} pb-1")
295 basf2.B2INFO(f
" HER/LER number of bunches {int(lumiDic[keyFP]['herBunches'])}/{int(lumiDic[keyFP]['lerBunches'])}")
296 for iov
in v[
"iovs"]:
297 basf2.B2INFO(f
" iov {iov[0]} {iov[1]} - {iov[2]} {iov[3]}")
Class to store the fill pattern of colliding bunches.
A class that describes the interval of experiments/runs for which an object in the database is valid.
static Database & Instance()
Instance of a singleton Database.