4 Validation of the Boost Vector calibration
9 from prompt
import ValidationSettings
16 import scipy.linalg
as la
18 import matplotlib.pyplot
as plt
23 from math
import sqrt, frexp, asin, hypot, atan2
25 from datetime
import datetime, timedelta
26 from ROOT.Belle2
import Unit
29 settings = ValidationSettings(name=
'BoostVector Calibrations',
31 download_files=[
'stdout'],
36 def getBVvalsErrs(bv, bve):
41 mag = np.linalg.norm(bv)
42 xzAngle = atan2(bv[0], bv[2])
43 yzAngle = atan2(bv[1], bv[2])
45 magUnc = np.linalg.norm(bv * bve) / mag
46 xzAngleUnc = 1. / (1 + (bv[0] / bv[2])**2) * hypot(bve[0] / bv[2], -bve[1] * bv[0] / bv[2]**2)
47 yzAngleUnc = 1. / (1 + (bv[1] / bv[2])**2) * hypot(bve[1] / bv[2], -bve[1] * bv[1] / bv[2]**2)
49 tomrad = Unit.rad / Unit.mrad
50 return [1e3 * mag, tomrad * xzAngle, tomrad * yzAngle], [1e3 * magUnc, tomrad * xzAngleUnc, tomrad * yzAngleUnc]
54 def getBVvalues(path):
56 with open(path +
'/database.txt')
as fDB:
62 fN = ll[0].replace(
'/',
'_') +
'_rev_' + ll[1] +
'.root'
65 runDict[fN] = (int(r[0]), int(r[1]))
69 fList = glob(path +
'/*.root')
71 bName = os.path.basename(fName)
72 runExp = runDict[bName]
74 f = ROOT.TFile.Open(fName)
75 bvAll = f.Get(
"CollisionBoostVector")
76 assert(bvAll.ClassName() ==
"Belle2::EventDependency")
78 evNums = bvAll.getEventNumbers()
80 for i
in range(len(evNums) + 1):
81 bvObj = bvAll.getObjectByIndex(i)
83 bvV = bvObj.getBoost()
84 bv = [bvV(i)
for i
in range(3)]
85 bveV = bvObj.getBoostCovariance()
86 bve = [sqrt(bveV(i, i))
for i
in range(3)]
88 tStart = int(frexp(bveV(0, 1))[0] * 2**53) % 2**32 / 3600.
89 tEnd = int(frexp(bveV(0, 2))[0] * 2**53) % 2**32 / 3600.
91 bvV, bvE = getBVvalsErrs(bv, bve)
93 arr.append((runExp, tStart, tEnd, bvV, bvE))
96 arr = sorted(arr, key=
lambda x: x[1])
103 def printToFile(arr):
105 with open(
'bvData.csv',
'w')
as outFile:
106 outFile.write(
'exp run tStart tEnd mag xzAngle yzAngle magUnc xzAngleUnc yzAngleUnc \n')
128 def plotVar(arr, limits, vName, getterV, getterE=None):
137 for i, el
in enumerate(arr):
139 s = datetime.utcfromtimestamp((s + 9) * 3600)
140 e = datetime.utcfromtimestamp((e + 9) * 3600)
143 Vals.append(getterV(el))
144 Vals.append(getterV(el))
146 if getterE
is not None:
147 Errs.append(getterE(el))
148 Errs.append(getterE(el))
151 if i >= len(arr) - 1:
154 dt = (arr[i + 1][1] - arr[i][2]) * 3600
161 gS = datetime.utcfromtimestamp((arr[i][2] + 9) * 3600)
162 gE = datetime.utcfromtimestamp((arr[i + 1][1] + 9) * 3600)
164 tVals.append(gS + (gE - gS) / 2)
166 if getterE
is not None:
170 tGapVals.append(gS - timedelta(seconds=1))
173 tGapVals.append(gE + timedelta(seconds=1))
175 GapVals.append(np.nan)
176 GapVals.append(getterV(arr[i]))
177 GapVals.append(getterV(arr[i + 1]))
178 GapVals.append(np.nan)
180 plt.plot(tVals, Vals, linewidth=2, color=
'C0')
181 plt.plot(tGapVals, GapVals, linewidth=2, color=
'C0', alpha=0.35)
183 Vals = np.array(Vals)
184 Errs = np.array(Errs)
186 if getterE
is not None:
187 plt.fill_between(tVals, Vals - Errs, Vals + Errs, alpha=0.2)
191 plt.ylabel(vName +
' [mrad]')
193 plt.ylabel(vName +
r' $[10^{-3}]$')
195 loc =
'plots/allData'
196 if limits
is not None:
197 plt.xlim(datetime.strptime(limits[0],
'%Y-%m-%d'), datetime.strptime(limits[1],
'%Y-%m-%d'))
198 loc =
'plots/' + limits[0] +
'to' + limits[1]
201 os.makedirs(loc, exist_ok=
True)
203 plt.savefig(loc +
'/' + vName +
'.png')
207 def plotPullSpectrum(arr, vName, getterV, getterE):
209 from itertools
import groupby
210 vals = np.array([k
for k, g
in groupby([getterV(v)
for v
in arr])])
211 errs = np.array([k
for k, g
in groupby([getterE(v)
for v
in arr])])
212 assert(len(vals) == len(errs))
214 diffs = (vals[1:] - vals[:-1]) / np.hypot(errs[1:], errs[:-1])
217 n1, n2 = scipy.stats.norm.cdf([-1, 1])
219 q1 = np.quantile(diffs, n1)
220 q2 = np.quantile(diffs, n2)
222 plt.hist(diffs, bins=np.linspace(-10, 10, 20), label=f
'q1={round(q1,1)}, q2={round(q2,1)}')
226 loc =
'plots/allData'
227 plt.savefig(loc +
'/' + vName +
'.png')
231 def run_validation(job_path, input_data_path, requested_iov, expert_config):
237 if expert_config !=
'':
238 expert_config = json.loads(expert_config)
241 if expert_config
is not None and 'plotsRanges' in expert_config:
242 allLimits += expert_config[
'plotsRanges']
245 dbFile = glob(f
'{job_path}/**/database.txt', recursive=
True)
246 dbFile = [db
for db
in dbFile
if 'algorithm_output' not in db]
247 assert(len(dbFile) == 1)
249 inputDir = dbFile[:dbFile.rfind(
'/')]
251 arr = getBVvalues(inputDir)
256 plt.figure(figsize=(18, 9))
259 for limits
in allLimits:
260 plotVar(arr, limits,
'boostMag',
lambda e: e[3][0],
lambda e: e[4][0])
261 plotVar(arr, limits,
'xzBoostAngle',
lambda e: e[3][1],
lambda e: e[4][1])
262 plotVar(arr, limits,
'yzBoostAngle',
lambda e: e[3][2],
lambda e: e[4][2])
264 plotPullSpectrum(arr,
'boostMagPulls',
lambda e: e[3][0],
lambda e: e[4][0])
265 plotPullSpectrum(arr,
'xzBoostAnglePulls',
lambda e: e[3][1],
lambda e: e[4][1])
266 plotPullSpectrum(arr,
'yzBoostAnglePulls',
lambda e: e[3][2],
lambda e: e[4][2])
269 if __name__ ==
"__main__":
270 run_validation(*sys.argv[1:])