Belle II Software development
klm_time_cabledelay.py
1
8
9'''
10Validation of KLM time cabledelay calibration.
11'''
12
13
14import basf2
15from prompt import ValidationSettings
16import ROOT
17from ROOT.Belle2 import KLMCalibrationChecker
18import sys
19import subprocess
20import math
21import os
22import json
23from ROOT import TH1F, TCanvas, TFile, gStyle
24
25
26settings = ValidationSettings(name='KLM time cabledelay',
27 description=__doc__,
28 download_files=['stdout'],
29 expert_config={
30 "chunk_size": 100,
31 "LowerTimeBoundaryRPC": -800.0,
32 "UpperTimeBoundaryRPC": -600.0,
33 "LowerTimeBoundaryScintilltorsBKLM": -4800.0,
34 "UpperTimeBoundaryScintilltorsBKLM": -4400.0,
35 "LowerTimeBoundaryScintilltorsEKLM": -4900.0,
36 "UpperTimeBoundaryScintilltorsEKLM": -4500.0,
37 })
38
39
40def run_validation(job_path, input_data_path, requested_iov, expert_config):
41 '''
42 Run the validation.
43 Note:
44 - job_path will be replaced with path/to/calibration_results
45 - input_data_path will be replaced with path/to/data_path used for calibration, e.g. /group/belle2/dataprod/Data/PromptSkim/
46 '''
47
48 # Grab the expert configurations.
49 expert_config = json.loads(expert_config)
50 print(expert_config)
51 chunk_size = expert_config['chunk_size']
52 LowerTimeBoundaryRPC = expert_config['LowerTimeBoundaryRPC']
53 UpperTimeBoundaryRPC = expert_config['UpperTimeBoundaryRPC']
54 LowerTimeBoundaryScintilltorsBKLM = expert_config['LowerTimeBoundaryScintilltorsBKLM']
55 UpperTimeBoundaryScintilltorsBKLM = expert_config['UpperTimeBoundaryScintilltorsBKLM']
56 LowerTimeBoundaryScintilltorsEKLM = expert_config['LowerTimeBoundaryScintilltorsEKLM']
57 UpperTimeBoundaryScintilltorsEKLM = expert_config['UpperTimeBoundaryScintilltorsEKLM']
58
59 # Ignore the ROOT command line options.
60 ROOT.PyConfig.IgnoreCommandLineOptions = True # noqa
61 # Run ROOT in batch mode.
62 ROOT.gROOT.SetBatch(True)
63 # Set the Belle II style.
64 ROOT.gROOT.SetStyle("BELLE2")
65 # And unset the stat box.
66 ROOT.gStyle.SetOptStat(0)
67
68 # Path to the database.txt file.
69 database_file = os.path.join(f'{job_path}', 'KLMTime', 'outputdb', 'database.txt')
70
71 # Check the list of runs from the file database.txt.
72 exp_run_dict = {}
73 previous_exp = -666
74 with open(database_file) as f:
75 for line in f:
76 fields = line.split(' ')
77 if (fields[0] == 'dbstore/KLMTimeCableDelay'):
78 iov = fields[2].split(',')
79 exp = int(iov[0])
80 run = int(iov[1])
81 if (exp != previous_exp):
82 exp_run_dict[exp] = [run]
83 previous_exp = exp
84 else:
85 exp_run_dict[exp].append(run)
86
87 # Tweak the IoV range if the first run is 0.
88 # This is needed for display purposes.
89 for exp, run_list in exp_run_dict.items():
90 run_list.sort()
91 if len(run_list) > 1:
92 if run_list[0] == 0 and run_list[1] > 5:
93 run_list[0] = run_list[1] - 5
94
95 # Run the KLMCalibrationChecker class.
96 for exp, run_list in exp_run_dict.items():
97 for run in run_list:
98 checker = KLMCalibrationChecker()
99 checker.setExperimentRun(exp, run)
100 checker.setTestingPayload(database_file)
101 basf2.B2INFO(f'Creating time cable delay results tree for experiment {exp}, run {run}.')
102 checker.setTimeCableDelayResultsFile(f'time_cabledelay_exp{exp}_run{run}.root')
103 checker.checkTimeCableDelay()
104
105 # Run the validation.
106 for exp, run_list in exp_run_dict.items():
107 # For each experiment, merge the files in chunks of some runs.
108 chunks = math.ceil(len(run_list) / chunk_size)
109 for chunk in range(chunks):
110 file_name = f'time_cabledelay_exp{exp}_chunk{chunk}.root'
111 run_files = [
112 f'time_cabledelay_exp{exp}_run{run}.root' for run in run_list[chunk * chunk_size:(chunk + 1) * chunk_size]]
113 subprocess.run(['hadd', '-f', file_name] + run_files, check=True)
114 input_file = ROOT.TFile(f'{file_name}')
115
116 gStyle.SetOptStat(1111111)
117 gStyle.SetOptFit(1111)
118 barrel_RPC = TH1F("barrel_RPC", "time cable delay for Barrel RPC", 100, LowerTimeBoundaryRPC, UpperTimeBoundaryRPC)
119 barrel_scintillator = TH1F("barrel_scintillator", "time cable delay for Barrel scintillator",
120 100, LowerTimeBoundaryScintilltorsBKLM, UpperTimeBoundaryScintilltorsBKLM)
121 endcap_scintillator = TH1F("endcap_scintillator", "time cable delay for endcap scintillator",
122 100, LowerTimeBoundaryScintilltorsEKLM, UpperTimeBoundaryScintilltorsEKLM)
123
124 tree = input_file.Get("cabledelay")
125 assert isinstance(tree, ROOT.TTree) == 1
126 myC = TCanvas("myC")
127
128 tree.Draw("timeDelay>>barrel_RPC", "subdetector==1 & layer>=3")
129 barrel_RPC.Fit("gaus")
130 barrel_RPC.GetXaxis().SetTitle("T_{cable} (ns)")
131 barrel_RPC.GetYaxis().SetTitle("Entries")
132 myC.Print("barrel_RPC.png")
133
134 tree.Draw("timeDelay>>barrel_scintillator", "subdetector==1 & layer<3")
135 barrel_scintillator.Fit("gaus")
136 barrel_scintillator.GetXaxis().SetTitle("T_{cable} (ns)")
137 barrel_scintillator.GetYaxis().SetTitle("Entries")
138 myC.Print("barrel_scintillator.png")
139
140 tree.Draw("timeDelay>>endcap_scintillator", "subdetector==2")
141 endcap_scintillator.Fit("gaus")
142 endcap_scintillator.GetXaxis().SetTitle("T_{cable} (ns)")
143 endcap_scintillator.GetYaxis().SetTitle("Entries")
144 myC.Print("endcap_scintillator.png")
145
146 # Write out histograms
147 fout = TFile("KLMTimeCableDelay.root", "recreate")
148 barrel_RPC.Write()
149 barrel_scintillator.Write()
150 endcap_scintillator.Write()
151 input_file.Close()
152 fout.Close()
153
154 # Let's delete the files for single IoVs.
155 for run_file in run_files:
156 try:
157 os.remove(run_file)
158 except OSError as e:
159 basf2.B2ERROR(f'The file {run_file} can not be removed: {e.strerror}')
160
161
162if __name__ == "__main__":
163 run_validation(*sys.argv[1:])