Belle II Software development
CoGCalibration_utils.py
1# !/usr/bin/env python
2
3
10
11#
12# evaluates the CoG corrections, create a localDB
13# with the corrections and a root file to check
14# the corrections
15#
16# usage: basf2 SVDCoGTimeCalibratinWithErrorImporter localDB filename
17# localDB = name of the local DB folder
18# filename = single root file, or file with the list of reconstructed files
19#
20# this script can be launched with launch_calibration_cog.sh in the
21# B2SVD project, svd_CoGHitTime_calibration repository
22#
23
24
25import basf2 as b2
26from ROOT import Belle2, TFile, TFitResultPtr, TH1F, TH2D, TH2F
27from ROOT import TF1, gDirectory, gROOT
28import math
29from ROOT.Belle2 import SVDCoGCalibrationFunction
30
31
32svd_recoDigits = "SVDRecoDigitsFromTracks"
33cdc_Time0 = "EventT0"
34svd_Clusters = "SVDClustersFromTracks"
35
36gROOT.SetBatch(True)
37
38# mode = True
39
40
42 """
43 Python class used for evaluating the CoG corrections, create a localDB,
44 creating a localDB with the corrections and a root file to check the corrections
45 """
46
48 """
49 Function that allows to set if apply the CDC latency correction
50
51 parameters:
52 mode (bool):
53 - if True -> not apply correction
54 - if False -> apply correction
55 """
56
58 print("Not Correct for CDC latency: " + str(mode) + " " + str(self.notApplyCDCLatencyCorrection))
59
60 def fillLists(self, mode_byte_object, svdClusters_rel_RecoTracks_cl):
61 """
62 Function that fill the lists needed for the CoG corrections
63
64 parameters:
65 mode_byte_object (modeByte): modeByte that contains the information about the TB
66 svdClusters_rel_RecoTracks_cl (SVDCluster): cluster related to tracks
67 """
68
69 timeCluster = svdClusters_rel_RecoTracks_cl.getClsTime()
70 snrCluster = svdClusters_rel_RecoTracks_cl.getSNR()
71 layerCluster = svdClusters_rel_RecoTracks_cl.getSensorID().getLayerNumber()
72 layerIndex = layerCluster - 3
73 sensorCluster = svdClusters_rel_RecoTracks_cl.getSensorID().getSensorNumber()
74 sensorIndex = sensorCluster - 1
75 ladderCluster = svdClusters_rel_RecoTracks_cl.getSensorID().getLadderNumber()
76 ladderIndex = ladderCluster - 1
77 sideCluster = svdClusters_rel_RecoTracks_cl.isUCluster()
78 if sideCluster:
79 sideIndex = 1
80 else:
81 sideIndex = 0
82
83 hasTimezero = self.cdcEventT0.hasEventT0()
84 # print("Time: " + str(hasTimezero))
85 if hasTimezero:
86 TBClusters = mode_byte_object.getTriggerBin()
87 TBIndex = ord(TBClusters)
88 tZero = self.cdcEventT0.getEventT0()
89 # tZero_err = self.cdcEventT0.getEventT0Uncertainty()
90 # tZero_err = 5.1
91 tZeroSync = tZero - 4000./509 * (3 - TBIndex)
92 et0 = self.EventT0Hist
93 et0.Fill(tZeroSync)
94 # print(str(tZero_err))
95
96 resHist = self.resList[layerIndex][ladderIndex][sensorIndex][sideIndex][TBIndex]
97 resHist.Fill(timeCluster - tZeroSync)
98 spHist = self.spList[layerIndex][ladderIndex][sensorIndex][sideIndex][TBIndex]
99 # spHist.Fill(timeCluster, 1.3*timeCluster - 50 + random.gauss(0,10))
100 spHist.Fill(timeCluster, tZeroSync)
101 cogHist = self.cogList[layerIndex][ladderIndex][sensorIndex][sideIndex][TBIndex]
102 cogHist.Fill(timeCluster)
103 cdcHist = self.cdcList[layerIndex][ladderIndex][sensorIndex][sideIndex][TBIndex]
104 cdcHist.Fill(tZeroSync)
105 snrHist = self.snrList[layerIndex][ladderIndex][sensorIndex][sideIndex][TBIndex]
106 snrHist.Fill(snrCluster)
107
108 self.nList[layerIndex][ladderIndex][sensorIndex][sideIndex][TBIndex] += 1
109 self.sumCOGList[layerIndex][ladderIndex][sensorIndex][sideIndex][TBIndex] += timeCluster
110
111
112 self.NTOT = self.NTOT + 1
113
114 def set_localdb(self, localDB):
115 """
116 Function that allows to set the localDB
117
118 parameters:
119 localDB (str): Name of the localDB used
120 """
121
122 self.localdb = localDB
123
124 def initialize(self):
125 """
126 Initialize object (histograms, lists, ...) used by the class
127 """
128
129
130 self.outputFileName = "CoGCorrectionMonitor_" + self.localdb + ".root"
131
132
134 self.resList = []
135
136 self.spList = []
137
138 self.cogList = []
139
140 self.cdcList = []
141
142 self.snrList = []
143
144 self.nList = []
145
146 self.sumCOGList = []
147
149
150 self.Evt = 0
151 for layer in geoCache.getLayers(Belle2.VXD.SensorInfoBase.SVD):
152 layerList0 = []
153 layerList1 = []
154 layerList2 = []
155 layerList3 = []
156 layerList4 = []
157 layerList5 = []
158 layerList6 = []
159 layerList7 = []
160 layerList8 = []
161 self.resList.append(layerList0)
162 self.spList.append(layerList1)
163 self.cogList.append(layerList2)
164 self.cdcList.append(layerList3)
165 self.snrList.append(layerList4)
166 self.nList.append(layerList8)
167 self.sumCOGList.append(layerList7)
168 # layerNumber = layer.getLayerNumber()
169 for ladder in geoCache.getLadders(layer):
170 ladderList0 = []
171 ladderList1 = []
172 ladderList2 = []
173 ladderList3 = []
174 ladderList4 = []
175 ladderList5 = []
176 ladderList6 = []
177 ladderList7 = []
178 ladderList8 = []
179 layerList0.append(ladderList0)
180 layerList1.append(ladderList1)
181 layerList2.append(ladderList2)
182 layerList3.append(ladderList3)
183 layerList4.append(ladderList4)
184 layerList5.append(ladderList5)
185 layerList6.append(ladderList6)
186 layerList7.append(ladderList7)
187 layerList8.append(ladderList8)
188 # ladderNumber = ladder.getLadderNumber()
189 for sensor in geoCache.getSensors(ladder):
190 sensorList0 = []
191 sensorList1 = []
192 sensorList2 = []
193 sensorList3 = []
194 sensorList4 = []
195 sensorList5 = []
196 sensorList6 = []
197 sensorList7 = []
198 sensorList8 = []
199 ladderList0.append(sensorList0)
200 ladderList1.append(sensorList1)
201 ladderList2.append(sensorList2)
202 ladderList3.append(sensorList3)
203 ladderList4.append(sensorList4)
204 ladderList5.append(sensorList5)
205 ladderList6.append(sensorList6)
206 ladderList7.append(sensorList7)
207 ladderList8.append(sensorList8)
208 # sensorNumber = sensor.getSensorNumber()
209 for side in range(2):
210 sideList0 = []
211 sideList1 = []
212 sideList2 = []
213 sideList3 = []
214 sideList4 = []
215 sideList5 = []
216 sideList6 = []
217 sideList7 = []
218 sideList8 = []
219 sensorList0.append(sideList0)
220 sensorList1.append(sideList1)
221 sensorList2.append(sideList2)
222 sensorList3.append(sideList3)
223 sensorList4.append(sideList4)
224 sensorList5.append(sideList5)
225 sensorList6.append(sideList6)
226 sensorList7.append(sideList7)
227 sensorList8.append(sideList8)
228
229 for i in geoCache.getLayers(Belle2.VXD.SensorInfoBase.SVD):
230 layerN = i.getLayerNumber()
231 li = layerN - 3
232 for j in geoCache.getLadders(i):
233 ladderN = j.getLadderNumber()
234 ldi = ladderN - 1
235 for k in geoCache.getSensors(j):
236 sensorN = k.getSensorNumber()
237 si = sensorN - 1
238 for s in range(2):
239 for t in range(4):
240 self.resList[li][ldi][si][s].append(
241 TH1F("res" + "_" + str(k) + "." + str(s) + "." + str(t), " ", 200, -100, 100))
242 self.spList[li][ldi][si][s].append(
243 TH2D("sp" + "_" + str(k) + "." + str(s) + "." + str(t), " ", 300, -150, 150, 300, -150, 150))
244 self.cogList[li][ldi][si][s].append(
245 TH1F("cog" + "_" + str(k) + "." + str(s) + "." + str(t), " ", 200, -100, 100))
246 self.cdcList[li][ldi][si][s].append(
247 TH1F("cdc" + "_" + str(k) + "." + str(s) + "." + str(t), " ", 200, -100, 100))
248 self.snrList[li][ldi][si][s].append(
249 TH1F("snr" + "_" + str(k) + "." + str(s) + "." + str(t), " ", 100, 0, 100))
250 self.nList[li][ldi][si][s].append(0)
251 self.sumCOGList[li][ldi][si][s].append(0)
252
253 self.EventT0Hist = TH1F("EventT0", " ", 200, -100, 100)
254
255 self.AlphaUTB = TH2F("alphaVsTB_U", " ", 400, 0.5, 2, 4, 0, 4)
256 self.AlphaUTB.GetXaxis().SetTitle("alpha")
257 self.AlphaUTB.GetYaxis().SetTitle("trigger bin")
258
259 self.AlphaVTB = TH2F("alphaVsTB_V", " ", 400, 0.5, 2, 4, 0, 4)
260 self.AlphaVTB.GetXaxis().SetTitle("alpha")
261 self.AlphaVTB.GetYaxis().SetTitle("trigger bin")
262
263 self.BetaUTB = TH2F("betaVsTB_U", " ", 200, -100, 100, 4, 0, 4)
264 self.BetaUTB.GetXaxis().SetTitle("beta (ns)")
265 self.BetaUTB.GetYaxis().SetTitle("trigger bin")
266
267 self.BetaVTB = TH2F("betaVsTB_V", " ", 200, -100, 100, 4, 0, 4)
268 self.BetaVTB.GetXaxis().SetTitle("beta (ns)")
269 self.BetaVTB.GetYaxis().SetTitle("trigger bin")
270
271
272 self.MeanHistVTB = TH2F("meanHistVsTB_V", " ", 100, -10, 10, 4, 0, 4)
273 self.MeanHistVTB.GetXaxis().SetTitle("distribution mean (ns)")
274 self.MeanHistVTB.GetYaxis().SetTitle("trigger bin")
275
276 self.MeanHistUTB = TH2F("meanHistVsTB_U", " ", 100, -10, 10, 4, 0, 4)
277 self.MeanHistUTB.GetXaxis().SetTitle("distribution mean (ns)")
278 self.MeanHistUTB.GetYaxis().SetTitle("trigger bin")
279
280 self.RMSHistVTB = TH2F("rmsHistVsTB_V", " ", 100, 0, 10, 4, 0, 4)
281 self.RMSHistVTB.GetXaxis().SetTitle("distribution RMS (ns)")
282 self.RMSHistVTB.GetYaxis().SetTitle("trigger bin")
283
284 self.RMSHistUTB = TH2F("rmsHistVsTB_U", " ", 100, 0, 10, 4, 0, 4)
285 self.RMSHistUTB.GetXaxis().SetTitle("distribution RMS (ns)")
286 self.RMSHistUTB.GetYaxis().SetTitle("trigger bin")
287
288 self.MeanFitVTB = TH2F("meanFitVsTB_V", " ", 100, -10, 10, 4, 0, 4)
289 self.MeanFitVTB.GetXaxis().SetTitle("fit mean (ns)")
290 self.MeanFitVTB.GetYaxis().SetTitle("trigger bin")
291
292 self.MeanFitUTB = TH2F("meanFitVsTB_U", " ", 100, -10, 10, 4, 0, 4)
293 self.MeanFitUTB.GetXaxis().SetTitle("fit mean (ns)")
294 self.MeanFitUTB.GetYaxis().SetTitle("trigger bin")
295
296 self.RMSFitUTB = TH2F("rmsFitVsTB_U", " ", 100, 0, 10, 4, 0, 4)
297 self.RMSFitUTB.GetXaxis().SetTitle("fit sigma (ns)")
298 self.RMSFitUTB.GetYaxis().SetTitle("trigger bin")
299
300 self.RMSFitVTB = TH2F("rmsFitVsTB_V", " ", 100, 0, 10, 4, 0, 4)
301 self.RMSFitVTB.GetXaxis().SetTitle("fit sigma (ns)")
302 self.RMSFitVTB.GetYaxis().SetTitle("trigger bin")
303
304
305 self.gaus = TF1("gaus", 'gaus(0)', -150, 100)
306
307 self.NTOT = 0
308
309 def event(self):
310 """
311 Function that allows to cicle on the events
312 """
313 svd_evt_info = Belle2.PyStoreObj('SVDEventInfo')
314 mode_byte = svd_evt_info.getModeByte()
315 # timeClusterU = 0
316 # timeClusterV = 0
317 # sideIndex = 0
318 # TBIndexU = 0
319 # TBIndexV = 0
320
321 self.Evt = self.Evt + 1
322
323
325 svdCluster_list = Belle2.PyStoreArray(svd_Clusters)
326 # svdRecoDigit_list = Belle2.PyStoreArray(svd_recoDigits)
327
328 for svdCluster in svdCluster_list:
329 # svdRecoDigit = svdCluster.getRelatedTo(svd_recoDigits)
330 self.fillLists(mode_byte, svdCluster)
331
332 def terminate(self):
333 """
334 Terminates te class and produces the output rootfile
335 """
336
337 tfile = TFile(self.outputFileName, 'recreate')
339
341
342 timeCal = SVDCoGCalibrationFunction()
343 # Bias and Scale
344 tbBias = [-50, -50, -50, -50]
345 tbScale = [1, 1, 1, 1]
346 tbBias_err = [1, 1, 1, 1]
347 tbScale_err = [1, 1, 1, 1]
348 # tbCovScaleBias = [1, 1, 1, 1]
349
350 TCOGMEAN = 0
351 T0MEAN = 0
352
353 '''
355 for layer in geoCache.getLayers(Belle2.VXD.SensorInfoBase.SVD):
356 layerNumber = layer.getLayerNumber()
357 li = layerNumber - 3
358 for ladder in geoCache.getLadders(layer):
359 ladderNumber = ladder.getLadderNumber()
360 ldi = ladderNumber - 1
361 for sensor in geoCache.getSensors(ladder):
362 sensorNumber = sensor.getSensorNumber()
363 si = sensorNumber - 1
364 for side in range(2):
365 for tb in range(4):
366 n = self.nList[li][ldi][si][side][tb]
367 NTOT += n
368 '''
370 gDirectory.mkdir("plots")
371 gDirectory.cd("plots")
372 for layer in geoCache.getLayers(Belle2.VXD.SensorInfoBase.SVD):
373 layerNumber = layer.getLayerNumber()
374 li = layerNumber - 3
375 gDirectory.mkdir("layer" + str(layer))
376 gDirectory.cd("layer" + str(layer))
377 for ladder in geoCache.getLadders(layer):
378 ladderNumber = ladder.getLadderNumber()
379 ldi = ladderNumber - 1
380 for sensor in geoCache.getSensors(ladder):
381 sensorNumber = sensor.getSensorNumber()
382 si = sensorNumber - 1
383 for side in range(2):
384 for tb in range(4):
385 # Resolution distribution Histograms with Gaussian Fit
386 res = self.resList[li][ldi][si][side][tb]
387 fitResult = int(TFitResultPtr(res.Fit(self.gaus, "R")))
388
389 if res.GetEntries() > 5:
390 if side == 1:
391 self.MeanHistUTB.Fill(res.GetMean(), tb)
392 self.RMSHistUTB.Fill(res.GetRMS(), tb)
393 if fitResult > -1:
394 self.MeanFitUTB.Fill(self.gaus.GetParameter(1), tb)
395 self.RMSFitUTB.Fill(self.gaus.GetParameter(2), tb)
396 else:
397 self.MeanHistVTB.Fill(res.GetMean(), tb)
398 self.RMSHistVTB.Fill(res.GetRMS(), tb)
399 if fitResult > -1:
400 self.MeanFitVTB.Fill(self.gaus.GetParameter(1), tb)
401 self.RMSFitVTB.Fill(self.gaus.GetParameter(2), tb)
402
403 res.Write()
404 # COG Distribution Histograms
405 cog = self.cogList[li][ldi][si][side][tb]
406 cog.Write()
407 # CDC EventT0 Distribution Histograms
408 cdc = self.cdcList[li][ldi][si][side][tb]
409 cdc.Write()
410 # SNR Distribution Histograms
411 snr = self.snrList[li][ldi][si][side][tb]
412 # snrMean = snr.GetMean()
413 snr.Write()
414 # ScatterPlot Histograms with Linear Fit
415 sp = self.spList[li][ldi][si][side][tb]
416 # covscalebias = sp.GetCovariance()
417 pfxsp = sp.ProfileX()
418 sp.Write()
419 pfxsp.Write()
420
421 if sp.GetRMS() != 0:
422 m = sp.GetCovariance() / pow(sp.GetRMS(1), 2)
423 # m = sp.GetCovariance()/cog.GetRMS()
424 m_err = 2 / pow(sp.GetRMS(), 3) * sp.GetRMSError() * sp.GetCovariance()
425 q = sp.GetMean(2) - m * sp.GetMean(1)
426 q_err = math.sqrt(pow(sp.GetMeanError(2), 2) +
427 pow(m * sp.GetMeanError(1), 2) + pow(m_err * sp.GetMean(1), 2))
428 else:
429 m = 1
430 m_err = 0
431 q = 0
432 q_err = 0
433
434 if side == 1:
435 self.AlphaUTB.Fill(m, tb)
436 self.BetaUTB.Fill(q, tb)
437 else:
438 self.AlphaVTB.Fill(m, tb)
439 self.BetaVTB.Fill(q, tb)
440
441 n = self.nList[li][ldi][si][side][tb]
442
443 tbBias[tb] = q
444 tbScale[tb] = m
445 tbBias_err[tb] = q_err
446 tbScale_err[tb] = m_err
447 TCOGMEAN += n * (m * self.sumCOGList[li][ldi][si][side][tb] / n + q) / self.NTOT
448
449 T0MEAN = self.EventT0Hist.GetMean()
450 '''
451 print(
452 "Mean of the CoG corrected distribution: " +
453 str(TCOGMEAN) +
454 " Mean of the T0 distribution: " +
455 str(T0MEAN))
456 '''
458 tbBias[0] = tbBias[0] - T0MEAN
459 tbBias[1] = tbBias[1] - T0MEAN
460 tbBias[2] = tbBias[2] - T0MEAN
461 tbBias[3] = tbBias[3] - T0MEAN
462
463 timeCal.set_bias(tbBias[0], tbBias[1], tbBias[2], tbBias[3])
464 timeCal.set_scale(tbScale[0], tbScale[1], tbScale[2], tbScale[3])
465 print("setting CoG calibration for " + str(layerNumber) + "." + str(ladderNumber) + "." + str(sensorNumber))
466 payload.set(layerNumber, ladderNumber, sensorNumber, bool(side), 1, timeCal)
467 gDirectory.cd("../")
468
469 gDirectory.cd("../")
470 self.AlphaUTB.Write()
471 self.AlphaVTB.Write()
472 self.BetaUTB.Write()
473 self.BetaVTB.Write()
474 self.MeanFitUTB.Write()
475 self.MeanFitVTB.Write()
476 self.RMSFitUTB.Write()
477 self.RMSFitVTB.Write()
478 self.MeanHistUTB.Write()
479 self.MeanHistVTB.Write()
480 self.RMSHistUTB.Write()
481 self.RMSHistVTB.Write()
482 self.EventT0Hist.Write()
483
484 Belle2.Database.Instance().storeData(Belle2.SVDCoGTimeCalibrations.name, payload, iov)
485
486 tfile.Close()
static IntervalOfValidity always()
Function that returns an interval of validity that is always valid, c.f.
A (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:72
a (simplified) python wrapper for StoreObjPtr.
Definition: PyStoreObj.h:67
base class for calibrations classes
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
MeanHistVTB
mean of the residuals distribution vs TB, for V side
notApplyCDCLatencyCorrection
parameter that allows to apply or not the CDC latency correction
RMSFitUTB
RMS of the residuals distribution vs TB, for U side (from gaussian fit)
resList
lists used to create the histograms for each TB : residuals
RMSFitVTB
RMS of the residuals distribution vs TB, for V side (from gaussian fit)
MeanFitUTB
mean of the residuals distribution vs TB, for U side (from gaussian fit)
def fillLists(self, mode_byte_object, svdClusters_rel_RecoTracks_cl)
MeanFitVTB
mean of the residuals distribution vs TB, for V side (from gaussian fit)
MeanHistUTB
mean of the residuals distribution vs TB, for U side
RMSHistVTB
RMS of the residuals distribution vs TB, for V side.
RMSHistUTB
RMS of the residuals distribution vs TB, for U side.
static Database & Instance()
Instance of a singleton Database.
Definition: Database.cc:42