10Validation of the Boost Vector calibration
14from prompt
import ValidationSettings
21import matplotlib.pyplot
as plt
25from math
import sqrt, frexp, hypot, atan2
27from datetime
import datetime, timedelta
28from ROOT.Belle2
import Unit
31settings = ValidationSettings(name=
'BoostVector Calibrations',
33 download_files=[
'stdout'],
38def getBVvalsErrs(bv, bve):
43 mag = np.linalg.norm(bv)
44 xzAngle = atan2(bv[0], bv[2])
45 yzAngle = atan2(bv[1], bv[2])
47 magUnc = np.linalg.norm(bv * bve) / mag
48 xzAngleUnc = 1. / (1 + (bv[0] / bv[2])**2) * hypot(bve[0] / bv[2], -bve[1] * bv[0] / bv[2]**2)
49 yzAngleUnc = 1. / (1 + (bv[1] / bv[2])**2) * hypot(bve[1] / bv[2], -bve[1] * bv[1] / bv[2]**2)
51 tomrad = Unit.rad / Unit.mrad
52 return [1e3 * mag, tomrad * xzAngle, tomrad * yzAngle], [1e3 * magUnc, tomrad * xzAngleUnc, tomrad * yzAngleUnc]
58 with open(path +
'/database.txt')
as fDB:
64 fN = ll[0].replace(
'/',
'_') +
'_rev_' + ll[1] +
'.root'
67 runDict[fN] = (int(r[0]), int(r[1]))
71 fList = glob(path +
'/*.root')
73 bName = os.path.basename(fName)
74 runExp = runDict[bName]
76 f = ROOT.TFile.Open(fName)
77 bvAll = f.Get(
"CollisionBoostVector")
78 assert(bvAll.ClassName() ==
"Belle2::EventDependency")
80 evNums = bvAll.getEventNumbers()
82 for i
in range(len(evNums) + 1):
83 bvObj = bvAll.getObjectByIndex(i)
85 bvV = bvObj.getBoost()
86 bv = [bvV(i)
for i
in range(3)]
87 bveV = bvObj.getBoostCovariance()
88 bve = [sqrt(bveV(i, i))
for i
in range(3)]
90 tStart = int(frexp(bveV(0, 1))[0] * 2**53) % 2**32 / 3600.
91 tEnd = int(frexp(bveV(0, 2))[0] * 2**53) % 2**32 / 3600.
93 bvV, bvE = getBVvalsErrs(bv, bve)
95 arr.append((runExp, tStart, tEnd, bvV, bvE))
98 arr = sorted(arr, key=
lambda x: x[1])
107 with open(
'bvData.csv',
'w')
as outFile:
108 outFile.write(
'exp run tStart tEnd mag xzAngle yzAngle magUnc xzAngleUnc yzAngleUnc \n')
130def plotVar(arr, limits, vName, getterV, getterE=None):
139 for i, el
in enumerate(arr):
141 s = datetime.utcfromtimestamp((s + 9) * 3600)
142 e = datetime.utcfromtimestamp((e + 9) * 3600)
145 Vals.append(getterV(el))
146 Vals.append(getterV(el))
148 if getterE
is not None:
149 Errs.append(getterE(el))
150 Errs.append(getterE(el))
153 if i >= len(arr) - 1:
156 dt = (arr[i + 1][1] - arr[i][2]) * 3600
163 gS = datetime.utcfromtimestamp((arr[i][2] + 9) * 3600)
164 gE = datetime.utcfromtimestamp((arr[i + 1][1] + 9) * 3600)
166 tVals.append(gS + (gE - gS) / 2)
168 if getterE
is not None:
172 tGapVals.append(gS - timedelta(seconds=1))
175 tGapVals.append(gE + timedelta(seconds=1))
177 GapVals.append(np.nan)
178 GapVals.append(getterV(arr[i]))
179 GapVals.append(getterV(arr[i + 1]))
180 GapVals.append(np.nan)
182 plt.plot(tVals, Vals, linewidth=2, color=
'C0')
183 plt.plot(tGapVals, GapVals, linewidth=2, color=
'C0', alpha=0.35)
185 Vals = np.array(Vals)
186 Errs = np.array(Errs)
188 if getterE
is not None:
189 plt.fill_between(tVals, Vals - Errs, Vals + Errs, alpha=0.2)
193 plt.ylabel(vName +
' [mrad]')
195 plt.ylabel(vName +
r' $[10^{-3}]$')
197 loc =
'plots/allData'
198 if limits
is not None:
199 plt.xlim(datetime.strptime(limits[0],
'%Y-%m-%d'), datetime.strptime(limits[1],
'%Y-%m-%d'))
200 loc =
'plots/' + limits[0] +
'to' + limits[1]
203 os.makedirs(loc, exist_ok=
True)
205 plt.savefig(loc +
'/' + vName +
'.png')
209def plotPullSpectrum(arr, vName, getterV, getterE):
211 from itertools
import groupby
212 vals = np.array([k
for k, g
in groupby([getterV(v)
for v
in arr])])
213 errs = np.array([k
for k, g
in groupby([getterE(v)
for v
in arr])])
214 assert(len(vals) == len(errs))
216 diffs = (vals[1:] - vals[:-1]) / np.hypot(errs[1:], errs[:-1])
219 n1, n2 = scipy.stats.norm.cdf([-1, 1])
221 q1 = np.quantile(diffs, n1)
222 q2 = np.quantile(diffs, n2)
224 plt.hist(diffs, bins=np.linspace(-10, 10, 20), label=f
'q1={round(q1,1)}, q2={round(q2,1)}')
228 loc =
'plots/allData'
229 plt.savefig(loc +
'/' + vName +
'.png')
233def run_validation(job_path, input_data_path, requested_iov, expert_config):
239 if expert_config !=
'':
240 expert_config = json.loads(expert_config)
243 if expert_config
is not None and 'plotsRanges' in expert_config:
244 allLimits += expert_config[
'plotsRanges']
247 dbFile = glob(f
'{job_path}/**/database.txt', recursive=
True)
248 dbFile = [db
for db
in dbFile
if 'algorithm_output' not in db]
249 assert(len(dbFile) == 1)
251 inputDir = dbFile[:dbFile.rfind(
'/')]
253 arr = getBVvalues(inputDir)
258 plt.figure(figsize=(18, 9))
261 for limits
in allLimits:
262 plotVar(arr, limits,
'boostMag',
lambda e: e[3][0],
lambda e: e[4][0])
263 plotVar(arr, limits,
'xzBoostAngle',
lambda e: e[3][1],
lambda e: e[4][1])
264 plotVar(arr, limits,
'yzBoostAngle',
lambda e: e[3][2],
lambda e: e[4][2])
266 plotPullSpectrum(arr,
'boostMagPulls',
lambda e: e[3][0],
lambda e: e[4][0])
267 plotPullSpectrum(arr,
'xzBoostAnglePulls',
lambda e: e[3][1],
lambda e: e[4][1])
268 plotPullSpectrum(arr,
'yzBoostAnglePulls',
lambda e: e[3][2],
lambda e: e[4][2])
271if __name__ ==
"__main__":