12 Validation of the Boost Vector calibration
17 from prompt
import ValidationSettings
24 import scipy.linalg
as la
26 import matplotlib.pyplot
as plt
31 from math
import sqrt, frexp, asin, hypot, atan2
33 from datetime
import datetime, timedelta
34 from ROOT.Belle2
import Unit
37 settings = ValidationSettings(name=
'BoostVector Calibrations',
39 download_files=[
'stdout'],
44 def getBVvalsErrs(bv, bve):
49 mag = np.linalg.norm(bv)
50 xzAngle = atan2(bv[0], bv[2])
51 yzAngle = atan2(bv[1], bv[2])
53 magUnc = np.linalg.norm(bv * bve) / mag
54 xzAngleUnc = 1. / (1 + (bv[0] / bv[2])**2) * hypot(bve[0] / bv[2], -bve[1] * bv[0] / bv[2]**2)
55 yzAngleUnc = 1. / (1 + (bv[1] / bv[2])**2) * hypot(bve[1] / bv[2], -bve[1] * bv[1] / bv[2]**2)
57 tomrad = Unit.rad / Unit.mrad
58 return [1e3 * mag, tomrad * xzAngle, tomrad * yzAngle], [1e3 * magUnc, tomrad * xzAngleUnc, tomrad * yzAngleUnc]
62 def getBVvalues(path):
64 with open(path +
'/database.txt')
as fDB:
70 fN = ll[0].replace(
'/',
'_') +
'_rev_' + ll[1] +
'.root'
73 runDict[fN] = (int(r[0]), int(r[1]))
77 fList = glob(path +
'/*.root')
79 bName = os.path.basename(fName)
80 runExp = runDict[bName]
82 f = ROOT.TFile.Open(fName)
83 bvAll = f.Get(
"CollisionBoostVector")
84 assert(bvAll.ClassName() ==
"Belle2::EventDependency")
86 evNums = bvAll.getEventNumbers()
88 for i
in range(len(evNums) + 1):
89 bvObj = bvAll.getObjectByIndex(i)
91 bvV = bvObj.getBoost()
92 bv = [bvV(i)
for i
in range(3)]
93 bveV = bvObj.getBoostCovariance()
94 bve = [sqrt(bveV(i, i))
for i
in range(3)]
96 tStart = int(frexp(bveV(0, 1))[0] * 2**53) % 2**32 / 3600.
97 tEnd = int(frexp(bveV(0, 2))[0] * 2**53) % 2**32 / 3600.
99 bvV, bvE = getBVvalsErrs(bv, bve)
101 arr.append((runExp, tStart, tEnd, bvV, bvE))
104 arr = sorted(arr, key=
lambda x: x[1])
111 def printToFile(arr):
113 with open(
'bvData.csv',
'w')
as outFile:
114 outFile.write(
'exp run tStart tEnd mag xzAngle yzAngle magUnc xzAngleUnc yzAngleUnc \n')
136 def plotVar(arr, limits, vName, getterV, getterE=None):
145 for i, el
in enumerate(arr):
147 s = datetime.utcfromtimestamp((s + 9) * 3600)
148 e = datetime.utcfromtimestamp((e + 9) * 3600)
151 Vals.append(getterV(el))
152 Vals.append(getterV(el))
154 if getterE
is not None:
155 Errs.append(getterE(el))
156 Errs.append(getterE(el))
159 if i >= len(arr) - 1:
162 dt = (arr[i + 1][1] - arr[i][2]) * 3600
169 gS = datetime.utcfromtimestamp((arr[i][2] + 9) * 3600)
170 gE = datetime.utcfromtimestamp((arr[i + 1][1] + 9) * 3600)
172 tVals.append(gS + (gE - gS) / 2)
174 if getterE
is not None:
178 tGapVals.append(gS - timedelta(seconds=1))
181 tGapVals.append(gE + timedelta(seconds=1))
183 GapVals.append(np.nan)
184 GapVals.append(getterV(arr[i]))
185 GapVals.append(getterV(arr[i + 1]))
186 GapVals.append(np.nan)
188 plt.plot(tVals, Vals, linewidth=2, color=
'C0')
189 plt.plot(tGapVals, GapVals, linewidth=2, color=
'C0', alpha=0.35)
191 Vals = np.array(Vals)
192 Errs = np.array(Errs)
194 if getterE
is not None:
195 plt.fill_between(tVals, Vals - Errs, Vals + Errs, alpha=0.2)
199 plt.ylabel(vName +
' [mrad]')
201 plt.ylabel(vName +
r' $[10^{-3}]$')
203 loc =
'plots/allData'
204 if limits
is not None:
205 plt.xlim(datetime.strptime(limits[0],
'%Y-%m-%d'), datetime.strptime(limits[1],
'%Y-%m-%d'))
206 loc =
'plots/' + limits[0] +
'to' + limits[1]
209 os.makedirs(loc, exist_ok=
True)
211 plt.savefig(loc +
'/' + vName +
'.png')
215 def plotPullSpectrum(arr, vName, getterV, getterE):
217 from itertools
import groupby
218 vals = np.array([k
for k, g
in groupby([getterV(v)
for v
in arr])])
219 errs = np.array([k
for k, g
in groupby([getterE(v)
for v
in arr])])
220 assert(len(vals) == len(errs))
222 diffs = (vals[1:] - vals[:-1]) / np.hypot(errs[1:], errs[:-1])
225 n1, n2 = scipy.stats.norm.cdf([-1, 1])
227 q1 = np.quantile(diffs, n1)
228 q2 = np.quantile(diffs, n2)
230 plt.hist(diffs, bins=np.linspace(-10, 10, 20), label=f
'q1={round(q1,1)}, q2={round(q2,1)}')
234 loc =
'plots/allData'
235 plt.savefig(loc +
'/' + vName +
'.png')
239 def run_validation(job_path, input_data_path, requested_iov, expert_config):
245 if expert_config !=
'':
246 expert_config = json.loads(expert_config)
249 if expert_config
is not None and 'plotsRanges' in expert_config:
250 allLimits += expert_config[
'plotsRanges']
253 dbFile = glob(f
'{job_path}/**/database.txt', recursive=
True)
254 dbFile = [db
for db
in dbFile
if 'algorithm_output' not in db]
255 assert(len(dbFile) == 1)
257 inputDir = dbFile[:dbFile.rfind(
'/')]
259 arr = getBVvalues(inputDir)
264 plt.figure(figsize=(18, 9))
267 for limits
in allLimits:
268 plotVar(arr, limits,
'boostMag',
lambda e: e[3][0],
lambda e: e[4][0])
269 plotVar(arr, limits,
'xzBoostAngle',
lambda e: e[3][1],
lambda e: e[4][1])
270 plotVar(arr, limits,
'yzBoostAngle',
lambda e: e[3][2],
lambda e: e[4][2])
272 plotPullSpectrum(arr,
'boostMagPulls',
lambda e: e[3][0],
lambda e: e[4][0])
273 plotPullSpectrum(arr,
'xzBoostAnglePulls',
lambda e: e[3][1],
lambda e: e[4][1])
274 plotPullSpectrum(arr,
'yzBoostAnglePulls',
lambda e: e[3][2],
lambda e: e[4][2])
277 if __name__ ==
"__main__":