Belle II Software  release-08-01-10
klm_time_cabledelay.py
1 
8 
9 '''
10 Validation of KLM time cabledelay calibration.
11 '''
12 
13 
14 import basf2
15 from prompt import ValidationSettings
16 import ROOT
17 from ROOT.Belle2 import KLMCalibrationChecker
18 import sys
19 import subprocess
20 import math
21 import os
22 import json
23 from ROOT import TH1F, TCanvas, TFile, gStyle
24 
25 
26 settings = 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 
40 def 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 
162 if __name__ == "__main__":
163  run_validation(*sys.argv[1:])