4 Validation of the Beam Spot 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
24 from itertools
import groupby
26 from datetime
import datetime, timedelta
27 from ROOT.Belle2
import Unit
30 settings = ValidationSettings(name=
'BeamSpot Calibrations',
32 download_files=[
'stdout'],
37 def getEigenPars(covM):
38 sxx, syy, szz, sxy, sxz, syz = covM
40 mat = np.array([[sxx, sxy, sxz],
45 eigVals = result[0].real
49 idx = eigVals.argsort()[::-1]
50 eigVals = eigVals[idx]
51 eigVecs = eigVecs[:, idx]
53 assert(eigVals[0] > 1e-4)
54 assert(eigVals[1] > 1e-4)
55 assert(eigVals[2] > 1e-4)
57 sxEig = sqrt((eigVals[1]))
58 syEig = sqrt((eigVals[2]))
59 szEig = sqrt((eigVals[0]))
72 angleXZ = Unit.rad / Unit.mrad * asin(eigVecs[0][0] / sqrt(1 - eigVecs[1][0]**2))
73 angleYZ = Unit.rad / Unit.mrad * asin(eigVecs[1][0])
74 angleXY = Unit.rad / Unit.mrad * asin(eigVecs[1][1] / sqrt(1 - eigVecs[1][0]**2))
76 return [sxEig, syEig, szEig, angleXZ, angleYZ, angleXY]
80 def getBSvalues(path):
82 with open(path +
'/database.txt')
as fDB:
88 fN = ll[0].replace(
'/',
'_') +
'_rev_' + ll[1] +
'.root'
91 runDict[fN] = (int(r[0]), int(r[1]))
95 fList = glob(path +
'/*.root')
97 bName = os.path.basename(fName)
98 runExp = runDict[bName]
100 f = ROOT.TFile.Open(fName)
101 bsAll = f.Get(
"BeamSpot")
102 assert(bsAll.ClassName() ==
"Belle2::EventDependency")
104 evNums = bsAll.getEventNumbers()
106 for i
in range(len(evNums) + 1):
107 bs = bsAll.getObjectByIndex(i)
108 ipR = bs.getIPPosition()
109 ip = [ipR(i) * Unit.cm / Unit.um
for i
in range(3)]
110 ipeR = bs.getIPPositionCovMatrix()
111 ipe = [sqrt(ipeR(i, i)) * Unit.cm / Unit.um
for i
in range(3)]
112 covR = bs.getSizeCovMatrix()
113 covM = (covR(0, 0), covR(1, 1), covR(2, 2), covR(0, 1), covR(0, 2), covR(1, 2))
114 covM = [x * (Unit.cm / Unit.um)**2
for x
in covM]
116 tStart = ipeR(0, 1) * 1e20
117 tEnd = ipeR(0, 2) * 1e20
118 tStart = int(frexp(ipeR(0, 1))[0] * 2**53) % 2**32 / 3600.
119 tEnd = int(frexp(ipeR(0, 2))[0] * 2**53) % 2**32 / 3600.
121 eigM = getEigenPars(covM)
122 arr.append((runExp, tStart, tEnd, ip, ipe, covM, eigM))
125 arr = sorted(arr, key=
lambda x: x[1])
132 def printToFile(arr):
134 with open(
'bsData.csv',
'w')
as outFile:
135 outFile.write(
'exp run tStart tEnd xIP yIP zIP xeIP yeIP zeIP sXX sYY sZZ sXY sXZ '
136 +
'sYZ xSizeEig ySizeEig zSizeEig xzAngle yzAngle xyAngle\n')
172 def plotVar(arr, limits, vName, getterV, getterE=None):
181 for i, el
in enumerate(arr):
183 s = datetime.utcfromtimestamp((s + 9) * 3600)
184 e = datetime.utcfromtimestamp((e + 9) * 3600)
187 Vals.append(getterV(el))
188 Vals.append(getterV(el))
190 if getterE
is not None:
191 Errs.append(getterE(el))
192 Errs.append(getterE(el))
195 if i >= len(arr) - 1:
198 dt = (arr[i + 1][1] - arr[i][2]) * 3600
205 gS = datetime.utcfromtimestamp((arr[i][2] + 9) * 3600)
206 gE = datetime.utcfromtimestamp((arr[i + 1][1] + 9) * 3600)
208 tVals.append(gS + (gE - gS) / 2)
210 if getterE
is not None:
214 tGapVals.append(gS - timedelta(seconds=1))
217 tGapVals.append(gE + timedelta(seconds=1))
219 GapVals.append(np.nan)
220 GapVals.append(getterV(arr[i]))
221 GapVals.append(getterV(arr[i + 1]))
222 GapVals.append(np.nan)
224 plt.plot(tVals, Vals, linewidth=2, color=
'C0')
225 plt.plot(tGapVals, GapVals, linewidth=2, color=
'C0', alpha=0.35)
227 Vals = np.array(Vals)
228 Errs = np.array(Errs)
230 if getterE
is not None:
231 plt.fill_between(tVals, Vals - Errs, Vals + Errs, alpha=0.2)
235 plt.ylabel(vName +
' [mrad]')
237 plt.ylabel(vName +
' [um]')
239 loc =
'plots/allData'
240 if limits
is not None:
241 plt.xlim(datetime.strptime(limits[0],
'%Y-%m-%d'), datetime.strptime(limits[1],
'%Y-%m-%d'))
242 loc =
'plots/' + limits[0] +
'to' + limits[1]
245 os.makedirs(loc, exist_ok=
True)
247 plt.savefig(loc +
'/' + vName +
'.png')
251 def plotPullSpectrum(arr, vName, getterV, getterE):
253 valsOrg = np.array([getterV(v)
for v
in arr])
254 errsOrg = np.array([getterE(v)
for v
in arr])
257 indx = np.array([list(g)[0][0]
for k, g
in groupby(zip(np.arange(len(valsOrg)), valsOrg),
lambda x: x[1])])
261 diffs = (vals[1:] - vals[:-1]) / np.hypot(errs[1:], errs[:-1])
264 n1, n2 = scipy.stats.norm.cdf([-1, 1])
266 q1 = np.quantile(diffs, n1)
267 q2 = np.quantile(diffs, n2)
269 plt.hist(diffs, bins=np.linspace(-20, 20, 80), label=f
'q1={round(q1,1)}, q2={round(q2,1)}')
273 loc =
'plots/allData'
274 plt.savefig(loc +
'/' + vName +
'.png')
278 def run_validation(job_path, input_data_path, requested_iov, expert_config):
284 if expert_config !=
'':
285 expert_config = json.loads(expert_config)
288 if expert_config
is not None and 'plotsRanges' in expert_config:
289 allLimits += expert_config[
'plotsRanges']
292 dbFile = glob(f
'{job_path}/**/database.txt', recursive=
True)
293 dbFile = [db
for db
in dbFile
if 'algorithm_output' not in db]
294 assert(len(dbFile) == 1)
296 inputDir = dbFile[:dbFile.rfind(
'/')]
298 arr = getBSvalues(inputDir)
303 plt.figure(figsize=(18, 9))
306 for limits
in allLimits:
307 plotVar(arr, limits,
'xIP',
lambda e: e[3][0],
lambda e: e[4][0])
308 plotVar(arr, limits,
'yIP',
lambda e: e[3][1],
lambda e: e[4][1])
309 plotVar(arr, limits,
'zIP',
lambda e: e[3][2],
lambda e: e[4][2])
311 plotVar(arr, limits,
'xSpotSize',
lambda e: sqrt(e[5][0]))
312 plotVar(arr, limits,
'ySpotSize',
lambda e: sqrt(e[5][1]))
313 plotVar(arr, limits,
'zSpotSize',
lambda e: sqrt(e[5][2]))
315 plotVar(arr, limits,
'xSpotSizeEig',
lambda e: e[6][0])
316 plotVar(arr, limits,
'ySpotSizeEig',
lambda e: e[6][1])
317 plotVar(arr, limits,
'zSpotSizeEig',
lambda e: e[6][2])
319 plotVar(arr, limits,
'xzSpotAngle',
lambda e: e[6][3])
320 plotVar(arr, limits,
'yzSpotAngle',
lambda e: e[6][4])
321 plotVar(arr, limits,
'xySpotAngle',
lambda e: e[6][5])
323 plotPullSpectrum(arr,
'xIPpulls',
lambda e: e[3][0],
lambda e: e[4][0])
324 plotPullSpectrum(arr,
'yIPpulls',
lambda e: e[3][1],
lambda e: e[4][1])
325 plotPullSpectrum(arr,
'zIPpulls',
lambda e: e[3][2],
lambda e: e[4][2])
328 if __name__ ==
"__main__":
329 run_validation(*sys.argv[1:])