Belle II Software development
laserResolutionTools.py
1#!/usr/bin/env python3
2
3
10
11# ------------------------------------------------------------------------
12# Tools to fit the laser timing distribution and plot the results.
13# This code is intended for studying the TOP time resolution
14# ------------------------------------------------------------------------
15
16
17import basf2 as b2
18from ROOT import TF1, TFile, TH1F, TSpectrum, TTree
19from array import array
20
21
22def fitLaserResolution(
23 mcCorrectionsFile='/group/belle2/group/detector/TOP/calibration/MCreferences/t0MC.root',
24 dataFile='',
25 outputFile='laserResolutionResults.root',
26 pdfType='cb',
27 maxPeaks=2,
28 saveFits=False,
29 includeBackscatter=True,
30 useSinglePDF=True,
31 useMCPeaks=True):
32 """
33 Function that implements the fit of the laser time distribution correcting for the propagation time in the prism.
34 The inputs to the fitter are hit time distributions per channel, in the form of TH2F.
35
36 Two files containing the containing the hit timing VS channels distribution must be provided:
37
38 * The first file is used to estimate the light propagation correction (aka MC correction),
39 the number of peaks and the separation bewteen these peaks.
40 Since the correction is the same for all the slots, the corresponding TH2F can have only 512 bins on the x-axis.
41 A default file is available, where the hit time is taken from
42 the TOPSimHits, and the laser jitter has been set to zero in the simulation.
43 * The second file contains the distribution obtained from the data do be used to estimate the resolution.
44 In this case the histrogram must have
45 (512 x 16) bins on the x-axis, to store the time distribution for each channel of the detector.
46
47 Parameters:
48 mcCorrectionsFile (str): File with the TH2F containing the TOPSImHits time distribution.
49 Used to calculate the MC corrections
50 dataFile (str): File with the TH2F containing the TOPDigit time distribution on which the resolutions
51 must be evaluated
52 outputFile (str): rootFile containing the outupt trees and plots
53 pdfType (str): PDF used in the data fit: cb for a CrystalBall, gaus for a Gaussian or
54 gausExpo for an exponentially modified Gaussian
55 maxPeaks (int): maximum number of peaks that can be used in the data fit. Note that the
56 actual value is decided channel-by-channel
57 according to the MC simulation, this parameter is only a maximum cap.
58 In the current implementation only 1 or 2 peaks are supported, therefore maxPeaks can only go up to 2
59 saveFits (bool): set to True to save the histrogram and the fit for eavey single channel
60 includeBackscatter (bool): set to True to add an extra peak in the fit to account for the
61 MCP backscattering
62 useMCPeaks (bool): ste to True to fix the light path time difference from the MC. Set to False
63 to let this parameter floating in the fit
64 Returns:
65 void
66 """
67
68 if maxPeaks > 2 or maxPeaks < 1:
69 b2.B2FATAL('Usupported value for the maximum number for peaks (maxPeaks = ' +
70 str(maxPeaks) + '). Please set maxPeak o either 1 or 2.')
71 if pdfType != 'cb' and pdfType != 'gaus' and pdfType != 'gausExpo':
72 b2.B2FATAL(
73 'Unknown PDF type ' +
74 pdfType +
75 ". The possible options are cb for the Crystal Ball,"
76 "gaus for the Gaussian and gausExpo for exponentially modified Gaussian")
77
78 # First loops over the MC file to get the time propagation corrections
79 # Only the two highest peaks are stored
80
81 # List with the position fo the MC peaks (2 per channel). This is where the
82 # MC peak positions are stored to be used later to correct the data
83 mcPeaks = [[-1. for second in range(2)] for first in range(512)]
84
85 # Opens the file containg the MC distribution and loads it
86 tFileMC = TFile(mcCorrectionsFile)
87 histoMC = tFileMC.Get('LaserTimingVSChannelOneSlot')
88
89 # Loop over the channels of a slot (i.e the bins on the x axis of histoMC)
90 for kCh in range(512):
91 # Gets a one-channel wide slice and adjusts the range
92 timeProjectionMC = histoMC.ProjectionY('projectionMC', kCh + 1, kCh + 1)
93 timeProjectionMC.GetXaxis().SetRangeUser(0., 1.)
94 # Initializes TSpectrum
95 spectrum = TSpectrum()
96 # By default dentifies a peak only if it is 1-sigma apart from another peak
97 # and has an aplitud of at least 10% of the largest peak.
98 numPeaks = spectrum.Search(timeProjectionMC, 1., 'nobackground', 0.1)
99 # This is a bit ugl way to store the peak locations and amplitudes
100 # in a list. At this stage the maxima are no granted to be sorted
101 peaksX_ = spectrum.GetPositionX()
102 peaksY_ = spectrum.GetPositionY()
103 peaksX = [peaksX_[i] for i in range(numPeaks)]
104 peaksY = [peaksY_[j] for j in range(numPeaks)]
105
106 # Sorts the peaks starting form the largest one and stores the first
107 # two in the mcPeaks matrix
108 for iMax in range(numPeaks):
109 if iMax < 2:
110 maxPosition = int(peaksY.index(max(peaksY)))
111 peaksY[maxPosition] = -1. # get rid of the maximum
112 mcPeaks[kCh][iMax] = peaksX[maxPosition]
113
114 tFileMC.Close()
115
116 # End of the MC corrections part
117
118 # Opens the file with the data and loads the timing histogram
119 tFileData = TFile(dataFile)
120 histoData = tFileData.Get('LaserTimingVSChannel')
121
122 # Prepares the output file and tree
123 # tFileOut = TFile(outputFile, "RECREATE")
124 outTree = TTree("tree", "tree")
125
126 # Slot ID (1-based)
127 slotID = array('i', [0])
128 # Hardware channle number (0-based)
129 hwChannel = array('i', [0])
130 # Number of peaks used in the fit
131 nPeaks = array('i', [0])
132 # Degrees of freedom of the fit
133 ndf = array('f', [0])
134 # Chi2 of the fit
135 chi2 = array('f', [0.])
136 # Sigma of the Gaussian core
137 sigma = array('f', [0.])
138 # Statistical error on sigma
139 errSigma = array('f', [0.])
140 # Time of the primary peak (maximum of the fit fuction)
141 peakTime = array('f', [0.])
142 # Statistical error on manPeak
143 errPeakTime = array('f', [0.])
144
145 # Time of the spurious peak
146 extraTime = array('f', [0.])
147 # Statistical error on extraTime
148 errExtraTime = array('f', [0.])
149
150 # scale factor for Sigma of the Gaussian core
151 sigmaExtra = array('f', [0.])
152 # Statistical error on sigma scale factor
153 errSigmaExtra = array('f', [0.])
154
155 # Alpha parameter of the CB functions
156 alpha = array('f', [0.])
157 # Statistical error on alpha
158 errAlpha = array('f', [0.])
159 # n parameter of the CB functions
160 n = array('f', [0.])
161 # statistical error on n
162 errN = array('f', [0.])
163 # lambda parameter of the gauss exponiential
164 lam = array('f', [0.])
165 # Statistical error on lam
166 errLam = array('f', [0.])
167 # Normalization of the primary peak
168 norm1 = array('f', [0.])
169 # Statistical error on norm1
170 errNorm1 = array('f', [0.])
171 # Normalization of the secondary peak
172 norm2 = array('f', [0.])
173 # Statistical error on norm2
174 errNorm2 = array('f', [0.])
175
176 # Normalization of the spurious peak
177 normExtra = array('f', [0.])
178 # Statistical error on normExtra
179 errNormExtra = array('f', [0.])
180
181 # Separation between primary and secondary peak from the MC
182 deltaMC = array('f', [0.])
183 # Laser time corrected for the propagation time in the prism
184 correctedTime = array('f', [0.])
185 # Time of the late peak in the MC
186 latePeak = array('f', [0.])
187 # Time of the earlier peak in the MC
188 earlyPeak = array('f', [0.])
189
190 # Sets the tree branches
191 outTree.Branch('slotID', slotID, 'slotID/I')
192 outTree.Branch('hwChannel', hwChannel, 'hwChannel/I')
193 outTree.Branch('ndf', ndf, 'ndf/F')
194 outTree.Branch('chi2', chi2, 'chi2/F')
195 outTree.Branch('nPeaks', nPeaks, 'nPeaks/I')
196 outTree.Branch('sigma', sigma, 'sigma/F')
197 outTree.Branch('errSigma', errSigma, 'errSigma/F')
198 outTree.Branch('peakTime', peakTime, 'peakTime/F')
199 outTree.Branch('errPeakTime', errPeakTime, 'errPeakTime/F')
200 outTree.Branch('extraTime', extraTime, 'extraTime/F')
201 outTree.Branch('errExtraTime', errExtraTime, 'errExtraTime/F')
202 outTree.Branch('alpha', alpha, 'alpha/F')
203 outTree.Branch('errAlpha', errAlpha, 'errAlpha/F')
204 outTree.Branch('n', n, 'n/F')
205 outTree.Branch('errN', errN, 'errN/F')
206 outTree.Branch('lam', lam, 'lam/F')
207 outTree.Branch('errLam', errLam, 'errLam/F')
208 outTree.Branch('norm1', norm1, 'norm1/F')
209 outTree.Branch('errNorm1', errNorm1, 'errNorm1/F')
210 outTree.Branch('norm2', norm2, 'norm2/F')
211 outTree.Branch('errNorm2', errNorm2, 'errNorm2/F')
212 outTree.Branch('normExtra', normExtra, 'normExtra/F')
213 outTree.Branch('errNormExtra', errNormExtra, 'errNormExtra/F')
214 outTree.Branch('sigmaExtra', sigmaExtra, 'sigmaExtra/F')
215 outTree.Branch('errSigmaExtra', errSigmaExtra, 'errSigmaExtra/F')
216 outTree.Branch('deltaMC', deltaMC, 'deltaMC/F')
217 outTree.Branch('correctedTime', correctedTime, 'correctedTime/F')
218 outTree.Branch('latePeak', latePeak, 'latePeak/F')
219 outTree.Branch('earlyPeak', earlyPeak, 'earlyPeak/F')
220
221 # Main loop_: takes the histogram, slices it and fits each slide according to the number of peaks found in the MC and the
222 # pdf chosen by te user
223 for iSlot in range(0, 16):
224 print('Fitting slot ' + str(iSlot))
225 for k in range(0, 512):
226 timeProjection = histoData.ProjectionY('projection_' + str(iSlot + 1) + '_' +
227 str(k), k + iSlot * 512 + 1, k + iSlot * 512 + 1)
228 maximum = timeProjection.GetXaxis().GetBinCenter(timeProjection.GetMaximumBin())
229 if timeProjection.Integral() < 10:
230 continue
231 timeProjection.GetXaxis().SetRangeUser(maximum - 1., maximum + 2.)
232
233 slotID[0] = iSlot + 1
234 hwChannel[0] = k
235
236 # Saves the MC information in the tree variables
237 if(mcPeaks[k][1] > 0):
238 # By convention the first component of the PDF represents the later peak,
239 # which in the MC appears to be also the main one. However this may change with
240 # different MC simulations, therefore we have to check which one is
241 # the first peak and which one is the second peak
242 if mcPeaks[k][1] > mcPeaks[k][0]:
243 earlyPeak[0] = mcPeaks[k][0]
244 latePeak[0] = mcPeaks[k][1]
245 else:
246 earlyPeak[0] = mcPeaks[k][1]
247 latePeak[0] = mcPeaks[k][0]
248 deltaMC[0] = earlyPeak[0] - latePeak[0]
249 nPeaks[0] = 2
250 else:
251 nPeaks[0] = 1
252 deltaMC[0] = 0.
253 latePeak[0] = mcPeaks[k][0]
254 earlyPeak[0] = 0.
255
256 # fit with the CB
257 if pdfType == 'cb':
258 cb = TF1(
259 "cb",
260 "[0]*ROOT:: Math: : crystalball_function(x, [2], [3], [4], [5]) + "
261 "[1]*[0]*ROOT::Math::crystalball_function(x, [2], [3], [4], [5]+[6]) + "
262 "[7]*[0]*ROOT:: Math::crystalball_function(x, [2], [3], [9]*[4], [5]+[8]) ",
263 maximum -
264 1.,
265 maximum +
266 2.)
267 # main peak
268 cb.SetParameter(0, 10.) # norm 1
269 cb.SetParameter(2, -1.) # alpha
270 cb.SetParLimits(2, -30., -0.01) # alpha
271 cb.SetParameter(3, 3.) # n
272 cb.SetParLimits(3, 0.01, 6.) # n must be on the right side
273 cb.SetParameter(4, 0.05) # sigma
274 cb.SetParLimits(4, 0.03, 0.200) # range for sigma
275 cb.SetParameter(5, maximum) # maximum of the latest peak
276 cb.SetParLimits(5, maximum - 0.1, maximum + 0.1) # maximum of the latest peak
277 # backscatter peak
278 cb.SetParameter(7, 0.01) # yield of the spurious peak
279 cb.SetParLimits(7, 0., .1) # yield of the spurious peak
280 cb.SetParameter(8, 1.) # delay of the spurious peak (~ 1 ns)
281 cb.SetParLimits(8, 0.2, 2.) # delay of the spurious peak (~ 1 ns)
282 cb.SetParameter(9, 1.5) # scale factro for sigma of the spurious peak (~2)
283 cb.SetParLimits(9, 1.1, 3.) # scale factro for sigma of the spurious peak (~2)
284 if not includeBackscatter:
285 cb.FixParameter(7, 0.) # yield of the spurious peak
286 cb.FixParameter(8, 1.) # delay of the spurious peak (~ 1 ns)
287 cb.FixParameter(9, 1.5) # scale factro for sigma of the spurious peak (~2)
288
289 if(mcPeaks[k][1] > 0 and not useSinglePDF):
290 cb.SetParameter(1, 0.3) # norm 2
291 cb.SetParLimits(1, 0., 100.) # norm 1
292 if useMCPeaks:
293 cb.FixParameter(6, deltaMC[0])
294 else:
295 cb.SetParameter(6, deltaMC[0])
296 cb.SetParLimits(6, deltaMC[0] - 0.2, -0.001)
297 else:
298 cb.FixParameter(1, 0.)
299 cb.FixParameter(6, 0.)
300
301 cb.SetNpx(1000)
302 timeProjection.Fit('cb', 'RQS')
303 timeProjection.Fit('cb', 'RQS')
304 result = timeProjection.Fit('cb', 'RQS')
305
306 # Dumps the fit results into the tree variables
307 chi2[0] = result.Chi2()
308 ndf[0] = result.Ndf()
309 alpha[0] = cb.GetParameter(2)
310 errAlpha[0] = cb.GetParError(2)
311 n[0] = cb.GetParameter(3)
312 errN[0] = cb.GetParError(3)
313 lam[0] = 0.
314 errLam[0] = 0.
315 peakTime[0] = cb.GetParameter(5)
316 errPeakTime[0] = cb.GetParError(5)
317 sigma[0] = cb.GetParameter(4)
318 errSigma[0] = cb.GetParError(4)
319 norm1[0] = cb.GetParameter(0)
320 errNorm1[0] = cb.GetParError(0)
321 norm2[0] = cb.GetParameter(1)
322 errNorm2[0] = cb.GetParError(1)
323 normExtra[0] = cb.GetParameter(7)
324 errNormExtra[0] = cb.GetParError(7)
325 extraTime[0] = cb.GetParameter(8)
326 errExtraTime[0] = cb.GetParError(8)
327 sigmaExtra[0] = cb.GetParameter(9)
328 errSigmaExtra[0] = cb.GetParError(9)
329
330 # models each peak as an exponentially-modified gaussian
331 if pdfType == 'gausExpo':
332
333 gausExpo = TF1(
334 "gausExpo",
335 "[0]*(([4]/2.)*TMath::Exp(([4]/2.)*(2*[2] + [4]*[3]*[3]- 2.*x)))*"
336 "ROOT::Math::erfc(([2] + [4]*[3]*[3] - x)/(TMath::Sqrt(2.)*[3])) + "
337 "[1]*[0]*(([4]/2.)*TMath::Exp(([4]/2.)*(2*([2]+[5])+[4]*[3]*[3]-2.*x)))*"
338 "ROOT::Math::erfc((([2]+[5]) + [4]*[3]*[3] - x)/(TMath::Sqrt(2.)*[3])) +"
339 "[6]*[0]*(([4]/2.)*TMath::Exp(([4]/2.)*(2*([2]+[7])+[4]*[8]*[3]*[8]*[3]-2.*x)))*"
340 "ROOT::Math::erfc((([2]+[7]) + [4]*[8]*[3]*[8]*[3] - x)/(TMath::Sqrt(2.)*[8]*[3]))",
341 maximum -
342 1.,
343 maximum +
344 2.)
345
346 # main peak
347 gausExpo.SetParameter(0, 1000.) # norm 1
348 gausExpo.SetParameter(2, maximum) # maximum of the latest peak
349 gausExpo.SetParLimits(2, maximum - 0.1, maximum + 0.1) # maximum of the latest peak
350 gausExpo.SetParameter(3, 0.05) # sigma
351 gausExpo.SetParLimits(3, 0.03, 0.200) # range for sigma
352 gausExpo.SetParameter(4, 1.2) # lambda
353 # backscatter peak
354 gausExpo.SetParameter(6, 0.01) # norm extra
355 gausExpo.SetParLimits(6, 0., 0.1) # norm extra
356 gausExpo.SetParameter(7, 1.) # delay of the spurious peak (~ 1 ns)
357 gausExpo.SetParLimits(7, 0.2, 2.) # delay of the spurious peak (~ 1 ns)
358 gausExpo.SetParameter(8, 1.5) # scale factro for sigma of the spurious peak (~2)
359 gausExpo.SetParLimits(8, 1.1, 3.) # scale factro for sigma of the spurious peak (~2)
360 if not includeBackscatter:
361 gausExpo.FixParameter(6, 0.) # yield of the spurious peak
362 gausExpo.FixParameter(7, 1.) # delay of the spurious peak (~ 1 ns)
363 gausExpo.FixParameter(8, 1.5) # scale factor for sigma of the spurious peak (~2)
364
365 if(mcPeaks[k][1] > 0 and not useSinglePDF):
366 gausExpo.SetParameter(1, 0.3) # norm 2
367 gausExpo.SetParLimits(1, 0., 100.) # norm 1
368 if useMCPeaks:
369 gausExpo.FixParameter(5, deltaMC[0])
370 else:
371 gausExpo.SetParameter(5, deltaMC[0])
372 gausExpo.SetParLimits(5, deltaMC[0] - 0.2, -0.001)
373 else:
374 gausExpo.FixParameter(1, 0.)
375 gausExpo.FixParameter(5, 0.)
376
377 # Perform the fit
378 gausExpo.SetNpx(1000)
379 timeProjection.Fit('gausExpo', 'RQS')
380 timeProjection.Fit('gausExpo', 'RQS')
381 result = timeProjection.Fit('gausExpo', 'RQS')
382
383 # save the results
384 chi2[0] = result.Chi2()
385 ndf[0] = result.Ndf()
386 alpha[0] = 0.
387 errAlpha[0] = 0.
388 n[0] = 0.
389 errN[0] = 0.
390 lam[0] = gausExpo.GetParameter(4)
391 errLam[0] = gausExpo.GetParError(4)
392 peakTime[0] = gausExpo.GetParameter(2)
393 errPeakTime[0] = gausExpo.GetParError(2)
394 sigma[0] = gausExpo.GetParameter(3)
395 errSigma[0] = gausExpo.GetParError(3)
396 norm1[0] = gausExpo.GetParameter(0)
397 errNorm1[0] = gausExpo.GetParError(0)
398 norm2[0] = gausExpo.GetParameter(1)
399 errNorm2[0] = gausExpo.GetParError(1)
400 normExtra[0] = gausExpo.GetParameter(6)
401 errNormExtra[0] = gausExpo.GetParError(6)
402 extraTime[0] = gausExpo.GetParameter(7)
403 errExtraTime[0] = gausExpo.GetParError(7)
404 sigmaExtra[0] = gausExpo.GetParameter(8)
405 errSigmaExtra[0] = gausExpo.GetParError(8)
406
407 # fit using a simple gaussian
408 if pdfType == 'gaus':
409 gaussian = TF1(
410 "gaussian",
411 "[0]*TMath::Gaus([2], [3], kTRUE)) + "
412 "[0]*[1]*TMath::Gaus([2]+[4], [3], kTRUE)) +"
413 "[0]*[5]*TMath::Gaus([2]+[6], [3]*[7], kTRUE))",
414 maximum -
415 1.,
416 maximum +
417 2.)
418 # main peak
419 gaussian.SetParameter(0, 10.) # norm 1
420 gaussian.SetParameter(2, maximum) # maximum of the latest peak
421 gaussian.SetParLimits(2, maximum - 0.1, maximum + 0.1) # maximum of the latest peak
422 gaussian.SetParameter(3, 0.05) # sigma
423 gaussian.SetParLimits(3, 0.03, 0.200) # range for sigma
424 # backscatter peak
425 gaussian.SetParameter(5, 0.01) # yield of the spurious peak
426 gaussian.SetParLimits(5, 0., .1) # yield of the spurious peak
427 gaussian.SetParameter(6, 1.) # delay of the spurious peak (~ 1 ns)
428 gaussian.SetParLimits(6, 0.2, 2.) # delay of the spurious peak (~ 1 ns)
429 gaussian.SetParameter(7, 1.5) # scale factro for sigma of the spurious peak (~2)
430 gaussian.SetParLimits(7, 1.1, 3.) # scale factro for sigma of the spurious peak (~2)
431 if not includeBackscatter:
432 gaussian.FixParameter(5, 0.) # yield of the spurious peak
433 gaussian.FixParameter(6, 1.) # delay of the spurious peak (~ 1 ns)
434 gaussian.FixParameter(7, 1.5) # scale factro for sigma of the spurious peak (~2)
435
436 if(mcPeaks[k][1] > 0 and not useSinglePDF):
437 gaussian.SetParameter(1, 0.3) # norm 2
438 gaussian.SetParLimits(1, 0., 100.) # norm 1
439 if useMCPeaks:
440 gaussian.FixParameter(4, deltaMC[0])
441 else:
442 gaussian.SetParameter(4, deltaMC[0])
443 gaussian.SetParLimits(4, deltaMC[0] - 0.2, -0.001)
444 else:
445 gaussian.FixParameter(1, 0.)
446 gaussian.FixParameter(4, 0.)
447
448 gaussian.SetNpx(1000)
449 timeProjection.Fit('gaussian', 'RQS')
450 timeProjection.Fit('gaussian', 'RQS')
451 result = timeProjection.Fit('gaussian', 'RQS')
452
453 # Dumps the fit results into the tree variables
454 chi2[0] = result.Chi2()
455 ndf[0] = result.Ndf()
456 alpha[0] = 0.
457 errAlpha[0] = 0.
458 n[0] = 0.
459 errN[0] = 0.
460 lam[0] = 0.
461 errLam[0] = 0.
462 peakTime[0] = gaussian.GetParameter(2)
463 errPeakTime[0] = gaussian.GetParError(2)
464 sigma[0] = gaussian.GetParameter(3)
465 errSigma[0] = gaussian.GetParError(3)
466 norm1[0] = gaussian.GetParameter(0)
467 errNorm1[0] = gaussian.GetParError(0)
468 norm2[0] = gaussian.GetParameter(1)
469 errNorm2[0] = gaussian.GetParError(1)
470 normExtra[0] = gaussian.GetParameter(5)
471 errNormExtra[0] = gaussian.GetParError(5)
472 extraTime[0] = gaussian.GetParameter(6)
473 errExtraTime[0] = gaussian.GetParError(6)
474 sigmaExtra[0] = gaussian.GetParameter(7)
475 errSigmaExtra[0] = gaussian.GetParError(7)
476
477 # calculate the MC-corrected time sobtracting the timing of the main peak in the MC
478 correctedTime[0] = peakTime[0] - mcPeaks[k][0]
479
480 outTree.Fill()
481
482 if saveFits:
483 timeProjection.Write()
484
485 histoData.Write()
486 outTree.Write()
487
488
489def plotLaserResolution(fitResultsFile='laserResolutionResults.root'):
490 """
491 Function that creates some standard plots from the tree containg the flaset fit results
492 """
493
494 # Opens the file with the data and loads the timing histogram
495 tFileData = TFile(fitResultsFile)
496 treeData = tFileData.Get('tree')
497 histoData = tFileData.Get('LaserTimingVSChannel')
498
499 # Findes the average value of correctedTime to optimize the hisotgram axis ranges
500 h_test = TH1F("h_test", "a test histogram to determine the histogram boundaries", 1000, 0., 100.)
501 treeData.Draw("correctedTime>>h_test")
502 meanCorrTime = h_test.GetMean()
503
504 # laser peak time in each slot, after the MC correction (10 ps binnig)
505 h_localT0Resolution = [TH1F("h_localT0Resolution_slot" + str(iSlot + 1),
506 "Laser peak position after the MC correction in slot " + str(iSlot + 1),
507 400,
508 meanCorrTime - 2.,
509 meanCorrTime + 2.) for iSlot in range(16)]
510 # laser peak resolution in the whole detector (10 ps binnig)
511 h_singleChannelResolution = TH1F("h_singleChannelResolution", "Resolution of the laser peak.", 40, 0., 0.4)
512
513 # laser peak resolution as function of the channel (10 ps binnig)
514 h_singleChannelResolutionVSChannel = TH1F(
515 "singleChannelResolutionVSChannel",
516 "Resolution of the laser peak VS channel number",
517 512 * 16,
518 0,
519 512 * 16)
520
521 # laser peak position as function of the channel (10 ps binnig)
522 h_localT0ResolutionVSChannel = TH1F(
523 "localT0ResolutionVSChannel",
524 "Resolution of the laser peak VS channel number",
525 512 * 16,
526 0,
527 512 * 16)
528
529 # Distribution of the late peak
530 h_latePeakVSChannel = TH1F("latePeakVSChannel", "Late Peak position", 512 * 16, 0, 512 * 16)
531 # Distribution of the early peak
532 h_earlyPeakVSChannel = TH1F("earlyPeakVSChannel", "Early Peak position", 512 * 16, 0, 512 * 16)
533
534 for entry in treeData:
535 globalChannel = entry.hwChannel + entry.slotID * 512
536
537 h_localT0Resolution[entry.slotID - 1].Fill(entry.correctedTime)
538 h_singleChannelResolution.Fill(entry.sigma)
539
540 h_singleChannelResolutionVSChannel.SetBinContent(globalChannel + 1, entry.sigma)
541 h_singleChannelResolutionVSChannel.SetBinError(globalChannel + 1, entry.errSigma)
542
543 h_localT0ResolutionVSChannel.SetBinContent(globalChannel + 1, entry.correctedTime)
544 h_localT0ResolutionVSChannel.SetBinError(globalChannel + 1, entry.errPeakTime)
545
546 h_latePeakVSChannel.SetBinContent(globalChannel + 1, entry.latePeak)
547 if entry.earlyPeak > 0:
548 h_earlyPeakVSChannel.SetBinContent(globalChannel + 1, entry.earlyPeak)
549
550 # loops over the MC distributions for shift the according to the time offset of each slot
551 for iSlot in range(16):
552 laserTime = histoData.GetBinContent(iSlot * 512 + 1) # channle 0 of the slot
553 mcTime = h_latePeakVSChannel.GetBinContent(iSlot * 512 + 1) # channle 0 of the slot
554 timeShift = laserTime - mcTime
555 for iBin in range(512):
556 lateTime = h_latePeakVSChannel.GetBinContent(iBin + iSlot * 512 + 1) + timeShift
557 earlyTime = h_earlyPeakVSChannel.GetBinContent(iBin + iSlot * 512 + 1) + timeShift
558 h_latePeakVSChannel.SetBinContent(iBin + iSlot * 512 + 1, lateTime)
559 h_earlyPeakVSChannel.SetBinContent(iBin + iSlot * 512 + 1, earlyTime)
560
561 # Prepares the output file and tree
562 tFileOut = TFile('plots.root', "RECREATE")
563
564 histoData.Write()
565 h_latePeakVSChannel.Write()
566 h_earlyPeakVSChannel.Write()
567 h_singleChannelResolution.Write()
568 h_singleChannelResolutionVSChannel.Write()
569 h_localT0ResolutionVSChannel.Write()
570
571 for i in range(16):
572 h_localT0Resolution[i].Write()
573
574 tFileOut.Close()