Belle II Software development
top.py
1#!/usr/bin/env python3
2
3
10
11'''
12Validation plots for TOP calibration.
13'''
14
15from prompt import ValidationSettings
16from ROOT import TFile, TH1F, TGraph, TCanvas, TLegend, gROOT, gStyle, PyConfig
17from basf2 import B2ERROR
18import sys
19import glob
20
21
22settings = ValidationSettings(name='TOP post-tracking calibration',
23 description=__doc__,
24 download_files=[],
25 expert_config=None)
26
27
28def run_validation(job_path, input_data_path, requested_iov, expert_config):
29 '''
30 Makes validation plots
31 :job_path: path to top posttracking calibration output
32 :input_data_path: required argument but not used
33 :requested_iov: required argument but not used
34 :expert_config: required argument but not used
35 '''
36
37 # input/output file names
38
39 inputFileName = job_path + '/TOP_validation/0/algorithm_output/TOPCalValidation.root'
40 outputFileName = 'TOPValidation.pdf'
41
42 # configuration
43
44 PyConfig.IgnoreCommandLineOptions = True
45 gROOT.SetBatch(True)
46 gROOT.ForceStyle()
47 gStyle.SetOptStat(0)
48 gStyle.SetOptFit(1)
49 gStyle.SetHistMinimumZero(True)
50 gStyle.SetLabelSize(0.05, "X")
51 gStyle.SetLabelSize(0.05, "Y")
52 gStyle.SetTitleSize(0.06, "X")
53 gStyle.SetTitleSize(0.06, "Y")
54 gStyle.SetTitleOffset(0.7, "X")
55 gStyle.SetTitleOffset(0.8, "Y")
56 gStyle.SetGridColor(11)
57
58 # open input file and create the canvas
59
60 file_in = TFile.Open(inputFileName)
61 if (not file_in):
62 B2ERROR(inputFileName + ": file not found")
63 return
64 canvas = TCanvas("c1", "c1", 1000, 750)
65
66 # prepare and fit histograms for channel T0
67
68 channelT0s = []
69 residuals = []
70 residuals_all = TH1F("residuals_all", "ChannelT0 residuals; residuals [ns]", 200, -1.0, 1.0)
71 h_rms = TH1F("h_rms", "Width of residuals (rms); slot; r.m.s [ps]", 16, 0.5, 16.5)
72 h_core = TH1F("h_core", "Core width of residuals; slot; sigma [ps]", 16, 0.5, 16.5)
73 h_out = TH1F("h_out", "Outlayers (more than 3 sigma); slot; fraction [%]", 16, 0.5, 16.5)
74 for slot in range(1, 17):
75 name = "slot" + f'{slot:02d}'
76 h = file_in.Get("channelT0_" + name)
77 channelT0s.append(h)
78 r = TH1F("residuals_" + name, "ChannelT0, " + name + "; residuals [ns]", 200, -1.0, 1.0)
79 residuals.append(r)
80 if not h:
81 continue
82 for i in range(1, h.GetNbinsX() + 1):
83 if h.GetBinError(i) > 0:
84 r.Fill(h.GetBinContent(i))
85 residuals_all.Fill(h.GetBinContent(i))
86 r.Fit("gaus", "Q")
87 residuals_all.Fit("gaus", "Q")
88 h_rms.SetBinContent(slot, r.GetRMS() * 1000)
89 fun = r.GetFunction("gaus")
90 if not fun:
91 continue
92 fun.SetLineWidth(1)
93 h_core.SetBinContent(slot, fun.GetParameter(2) * 1000)
94 mean = fun.GetParameter(1)
95 wid = fun.GetParameter(2)
96 n_all = 0
97 n_in = 0
98 for i in range(1, h.GetNbinsX() + 1):
99 if h.GetBinError(i) == 0:
100 continue
101 n_all += 1
102 if abs(h.GetBinContent(i) - mean) < 3 * wid:
103 n_in += 1
104 if n_all > 0:
105 h_out.SetBinContent(slot, (1 - n_in / n_all) * 100)
106 residuals_all.Fit("gaus", "Q")
107
108 # open pdf file
109
110 canvas.Print(outputFileName + "[")
111
112 # make plots of channelT0 residuals vs. channel
113
114 canvas.Clear()
115 canvas.Divide(4, 4)
116 graphs = []
117 for i, h in enumerate(channelT0s):
118 canvas.cd(i + 1)
119 if h:
120 h.SetMinimum(-1.0)
121 h.SetMaximum(1.0)
122 h.Draw()
123 g_over = TGraph()
124 g_under = TGraph()
125 for ibin in range(1, h.GetNbinsX() + 1):
126 if h.GetBinContent(ibin) > 1.0:
127 g_over.SetPoint(g_over.GetN(), h.GetBinCenter(ibin), 0.95)
128 elif h.GetBinContent(ibin) < -1.0:
129 g_under.SetPoint(g_under.GetN(), h.GetBinCenter(ibin), -0.95)
130 if g_over.GetN() > 0:
131 g_over.SetMarkerStyle(22)
132 g_over.SetMarkerColor(2)
133 g_over.Draw("P")
134 graphs.append(g_over)
135 if g_under.GetN() > 0:
136 g_under.SetMarkerStyle(23)
137 g_under.SetMarkerColor(2)
138 g_under.Draw("P")
139 graphs.append(g_under)
140 canvas.Print(outputFileName)
141
142 # make plots of channelT0 residual distributions
143
144 canvas.Clear()
145 canvas.Divide(4, 4)
146 gStyle.SetOptFit(0)
147 gStyle.SetOptStat("oue")
148 W = gStyle.GetStatW()
149 H = gStyle.GetStatH()
150 gStyle.SetStatW(0.4)
151 gStyle.SetStatH(0.3)
152 for i, h in enumerate(residuals):
153 canvas.cd(i + 1)
154 h.Draw()
155 canvas.Print(outputFileName)
156 gStyle.SetStatW(W)
157 gStyle.SetStatH(H)
158
159 # make summary plots for channelT0
160
161 canvas.Clear()
162 canvas.Divide(2, 2)
163 gStyle.SetOptFit(111)
164 gStyle.SetOptStat(0)
165 histos = [residuals_all, h_rms, h_core, h_out]
166 for i, h in enumerate(histos):
167 canvas.cd(i + 1)
168 h.Draw()
169 canvas.Print(outputFileName)
170
171 # prepare commonT0 histogram
172
173 commonT0 = file_in.Get("commonT0")
174 if commonT0:
175 commonT0.Scale(1000)
176 commonT0.SetYTitle(commonT0.GetYaxis().GetTitle().replace('[ns]', '[ps]'))
177 commonT0.SetMinimum(-100)
178 commonT0.SetMaximum(100)
179 commonT0.Fit("pol0", "Q")
180
181 # make plots for commonT0
182
183 canvas.Clear()
184 canvas.Divide(1, 2)
185 canvas.GetPad(2).SetGrid()
186 gStyle.SetHistMinimumZero(False)
187 histos = [commonT0, file_in.Get("runIndex")]
188 for i, h in enumerate(histos):
189 canvas.cd(i + 1)
190 if h:
191 h.SetMarkerStyle(20)
192 h.SetMarkerSize(0.7)
193 h.Draw()
194 canvas.Print(outputFileName)
195 gStyle.SetHistMinimumZero(True)
196
197 # make plots for moduleT0
198
199 canvas.Clear()
200 canvas.Divide(4, 4)
201 histos = []
202 for slot in range(1, 17):
203 canvas.cd(slot)
204 h = file_in.Get("moduleT0_slot" + f'{slot:02d}')
205 if h:
206 h.Scale(1000)
207 h.SetYTitle(h.GetYaxis().GetTitle().replace('[ns]', '[ps]'))
208 h.SetMinimum(-100)
209 h.SetMaximum(100)
210 h.Fit("pol0", "Q")
211 histos.append(h)
212 canvas.Print(outputFileName)
213
214 # prepare moduleT0 summary histograms
215
216 h_offset = TH1F("h_offset", "ModuleT0: fitted offset; slot; p0 [ps]", 16, 0.5, 16.5)
217 h_chi = TH1F("h_chi", "ModuleT0: chi2/ndf; slot; #chi^{2}/ndf", 16, 0.5, 16.5)
218 h_res = TH1F("h_res", "ModuleT0: residuals; residual - p0 [ps]", 200, -100, 100)
219 h_pul = TH1F("h_pul", "ModuleT0: pulls; (residual - p0) / error", 200, -10, 10)
220 for i, h in enumerate(histos):
221 if not h:
222 continue
223 fun = h.GetFunction("pol0")
224 if not fun:
225 continue
226 p0 = fun.GetParameter(0)
227 err = fun.GetParError(0)
228 h_offset.SetBinContent(i + 1, p0)
229 h_offset.SetBinError(i + 1, err)
230 h_chi.SetBinContent(i + 1, fun.GetChisquare() / max(fun.GetNDF(), 1))
231 for ibin in range(1, h.GetNbinsX() + 1):
232 err = h.GetBinError(ibin)
233 if err > 0:
234 h_res.Fill(h.GetBinContent(ibin) - p0)
235 h_pul.Fill((h.GetBinContent(ibin) - p0) / err)
236
237 # plot moduleT0 summary histograms
238
239 canvas.Clear()
240 canvas.Divide(2, 2)
241 histos = [h_offset, h_chi, h_res, h_pul]
242 h_offset.SetStats(False)
243 h_chi.SetStats(False)
244 gStyle.SetOptStat("rme")
245 for i, h in enumerate(histos):
246 canvas.cd(i + 1)
247 h.Draw()
248 canvas.Print(outputFileName)
249 gStyle.SetOptStat(0)
250
251 # plot fractions of active and active-and-calibrated channels
252
253 canvas.Clear()
254 canvas.Divide(4, 4)
255 legends = []
256 for slot in range(1, 17):
257 canvas.cd(slot)
258 name = "slot" + f'{slot:02d}'
259 histos = [file_in.Get("numActive_" + name), file_in.Get("numActiveCalibrated_" + name)]
260 legend = TLegend(0.1, 0.1, 0.7, 0.3)
261 legends.append(legend)
262 opt = ''
263 for i, h in enumerate(histos):
264 if h:
265 h.SetMinimum(0.0)
266 h.SetMaximum(1.05)
267 text = h.GetTitle().split(',')[0]
268 if text == "Active":
269 text += " channels"
270 h.SetTitle(name)
271 h.SetLineColor(i+1)
272 h.Draw(opt)
273 opt = 'same'
274 legend.AddEntry(h, text)
275 if legend.GetNRows() > 0:
276 legend.Draw("same")
277 canvas.Print(outputFileName)
278
279 # plot fractions of time base and channelT0 calibrated channels
280
281 canvas.Clear()
282 canvas.Divide(4, 4)
283 legends = []
284 for slot in range(1, 17):
285 canvas.cd(slot)
286 name = "slot" + f'{slot:02d}'
287 histos = [file_in.Get("numTBCalibrated_" + name), file_in.Get("numT0Calibrated_" + name)]
288 legend = TLegend(0.1, 0.1, 0.7, 0.3)
289 legends.append(legend)
290 opt = ''
291 for i, h in enumerate(histos):
292 if h:
293 h.SetMinimum(0.0)
294 h.SetMaximum(1.05)
295 text = h.GetTitle().split(',')[0]
296 h.SetTitle(name)
297 h.SetLineColor(i+1)
298 h.Draw(opt)
299 opt = 'same'
300 legend.AddEntry(h, text)
301 if legend.GetNRows() > 0:
302 legend.Draw("same")
303 canvas.Print(outputFileName)
304
305 # plot threshold efficiencies
306
307 canvas.Clear()
308 canvas.Divide(4, 4)
309 legends = []
310 for slot in range(1, 17):
311 canvas.cd(slot)
312 name = "slot" + f'{slot:02d}'
313 h = file_in.Get("thrEffi_slot" + f'{slot:02d}')
314 legend = TLegend(0.1, 0.1, 0.7, 0.3)
315 legends.append(legend)
316 if h:
317 h.SetMinimum(0.0)
318 h.SetMaximum(1.0)
319 text = h.GetTitle().split(',')[0]
320 h.SetTitle(name)
321 h.Draw()
322 legend.AddEntry(h, text)
323 legend.Draw("same")
324 canvas.Print(outputFileName)
325
326 # plot BS13d asic shifts
327
328 canvas.Clear()
329 canvas.Divide(2, 2)
330 for cb in range(4):
331 canvas.cd(cb + 1)
332 canvas.GetPad(cb + 1).SetGrid()
333 h = file_in.Get("asicShifts_" + str(cb))
334 if h:
335 h.SetMinimum(-50.0)
336 h.SetMaximum(50.0)
337 h.Draw()
338 canvas.Print(outputFileName)
339
340 # plot offsets
341
342 canvas.Clear()
343 canvas.Divide(2, 2)
344 gStyle.SetOptStat("e")
345 gStyle.SetStatY(0.99)
346
347 offsets = [file_in.Get("svdOffset"), file_in.Get("cdcOffset")]
348 sigmas = [file_in.Get("svdSigma"), file_in.Get("cdcSigma")]
349 components = ['SVD', 'CDC']
350 colors = [4, 2]
351
352 canvas.cd(1)
353 hmin = 0
354 hmax = 0
355 for h in offsets:
356 if h:
357 hmin = min(hmin, h.GetMinimum())
358 hmax = max(hmax, h.GetMaximum())
359 hmin = round(hmin, 0) - 1
360 hmax = round(hmax, 0) + 1
361 for i, h in enumerate(offsets):
362 if h:
363 h.SetMinimum(hmin)
364 h.SetMaximum(hmax)
365 h.SetMarkerStyle(24)
366 h.SetMarkerColor(colors[i])
367 h.SetLineColor(colors[i])
368 first = True
369 legend1 = TLegend()
370 for i, h in enumerate(offsets):
371 if not h or not sigmas[i] or sigmas[i].Integral() == 0:
372 continue
373 if first:
374 h.Draw()
375 first = False
376 else:
377 h.Draw("same")
378 legend1.AddEntry(h, components[i])
379 legend1.Draw("same")
380
381 canvas.cd(2)
382 hmax = 0
383 for h in sigmas:
384 if h:
385 hmax = max(hmax, h.GetMaximum())
386 for i, h in enumerate(sigmas):
387 if h:
388 h.SetMinimum(0)
389 h.SetMaximum(hmax * 1.1)
390 h.SetMarkerStyle(24)
391 h.SetMarkerColor(colors[i])
392 h.SetLineColor(colors[i])
393 first = True
394 legend2 = TLegend()
395 for i, h in enumerate(sigmas):
396 if not h or h.Integral() == 0:
397 continue
398 if first:
399 h.Draw()
400 first = False
401 else:
402 h.Draw("same")
403 legend2.AddEntry(h, components[i])
404 legend2.Draw("same")
405
406 fillPatt = [file_in.Get("fillPatternOffset"), file_in.Get("fillPatternFract")]
407 for i, h in enumerate(fillPatt):
408 canvas.cd(3 + i)
409 if h:
410 if i == 1:
411 for k in range(h.GetNbinsX()):
412 h.SetBinError(k + 1, h.GetBinContent(k + 1) / 1000)
413 h.Draw()
414
415 canvas.Print(outputFileName)
416 gStyle.SetOptStat(0)
417
418 # plot RQE
419
420 gStyle.SetOptStat("rmei")
421 canvas.Clear()
422 canvas.Divide(2, 2)
423
424 rqe_path = job_path + '/TOP_photonYields/0/algorithm_output/photonYields-*.root'
425 rqeFileNames = glob.glob(rqe_path)
426 if len(rqeFileNames) == 0:
427 B2ERROR(rqe_path + ": no such files")
428 rqeFiles = []
429 rqeHistos = []
430 for fileName in sorted(rqeFileNames):
431 rqeFile = TFile.Open(fileName)
432 if not rqeFile:
433 B2ERROR(rqeFile + ": can't be open")
434 continue
435 rqeFiles.append(rqeFile)
436 histos = [rqeFile.Get("RQE"), rqeFile.Get("RQEerr")]
437 expNo = fileName.split('/')[-1].split('-')[1]
438 for h in histos:
439 if h:
440 h.SetTitle(expNo)
441 rqeHistos += histos
442 if len(rqeHistos) == 4:
443 for i, h in enumerate(rqeHistos):
444 canvas.cd(1 + i)
445 if h:
446 h.Draw()
447 canvas.Print(outputFileName)
448 rqeHistos = []
449 canvas.Clear()
450 canvas.Divide(2, 2)
451
452 if len(rqeHistos) > 0:
453 for i, h in enumerate(rqeHistos):
454 canvas.cd(1 + i)
455 if h:
456 h.Draw()
457 canvas.Print(outputFileName)
458 gStyle.SetOptStat(0)
459
460 # close pdf file
461
462 canvas.Print(outputFileName + "]")
463
464 # plot photon hits, use png format to shorten file size
465
466 canvas.Clear()
467 canvas.Divide(4, 4)
468 for slot in range(1, 17):
469 canvas.cd(slot)
470 h = file_in.Get("hits_slot" + f'{slot:02d}')
471 if h:
472 h.Draw("colz")
473 canvas.SaveAs(outputFileName.replace('.pdf', 'Hits.png'))
474
475
476if __name__ == "__main__":
477 run_validation(*sys.argv[1:])