Belle II Software  release-08-01-10
klm_time_constants.py
1 
8 
9 '''
10 Validation of KLM time constants 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 from ROOT import TH2F, TCanvas, TFile, gStyle
22 import os
23 import json
24 
25 
26 settings = ValidationSettings(name='KLM time constants',
27  description=__doc__,
28  download_files=['stdout'],
29  expert_config={
30  "chunk_size": 100
31  })
32 
33 
34 def run_validation(job_path, input_data_path, requested_iov, expert_config):
35  '''
36  Run the validation.
37  Note:
38  - job_path will be replaced with path/to/calibration_results
39  - input_data_path will be replaced with path/to/data_path used for calibration, e.g. /group/belle2/dataprod/Data/PromptSkim/
40  '''
41 
42  # Grab the expert configurations.
43  expert_config = json.loads(expert_config)
44  chunk_size = expert_config['chunk_size']
45 
46  # Ignore the ROOT command line options.
47  ROOT.PyConfig.IgnoreCommandLineOptions = True # noqa
48  # Run ROOT in batch mode.
49  ROOT.gROOT.SetBatch(True)
50  # Set the Belle II style.
51  ROOT.gROOT.SetStyle("BELLE2")
52  # And unset the stat box.
53  ROOT.gStyle.SetOptStat(0)
54 
55  # Path to the database.txt file.
56  database_file = os.path.join(f'{job_path}', 'KLMTime', 'outputdb', 'database.txt')
57 
58  # Check the list of runs from the file database.txt.
59  exp_run_dict = {}
60  previous_exp = -666
61  with open(database_file) as f:
62  for line in f:
63  fields = line.split(' ')
64  if (fields[0] == 'dbstore/KLMTimeConstants'):
65  iov = fields[2].split(',')
66  exp = int(iov[0])
67  run = int(iov[1])
68  if (exp != previous_exp):
69  exp_run_dict[exp] = [run]
70  previous_exp = exp
71  else:
72  exp_run_dict[exp].append(run)
73 
74  # Tweak the IoV range if the first run is 0.
75  # This is needed for display purposes.
76  for exp, run_list in exp_run_dict.items():
77  run_list.sort()
78  if len(run_list) > 1:
79  if run_list[0] == 0 and run_list[1] > 5:
80  run_list[0] = run_list[1] - 5
81 
82  # Run the KLMCalibrationChecker class.
83  for exp, run_list in exp_run_dict.items():
84  for run in run_list:
85  checker = KLMCalibrationChecker()
86  checker.setExperimentRun(exp, run)
87  checker.setTestingPayload(database_file)
88  basf2.B2INFO(f'Creating time constants results tree for experiment {exp}, run {run}.')
89  checker.setTimeConstantsResultsFile(f'time_constants_exp{exp}_run{run}.root')
90  checker.checkTimeConstants()
91 
92  # Run the validation.
93  for exp, run_list in exp_run_dict.items():
94  # For each experiment, merge the files in chunks of some runs.
95  chunks = math.ceil(len(run_list) / chunk_size)
96  for chunk in range(chunks):
97  file_name = f'time_constants_exp{exp}_chunk{chunk}.root'
98  run_files = [
99  f'time_constants_exp{exp}_run{run}.root' for run in run_list[chunk * chunk_size:(chunk + 1) * chunk_size]]
100  subprocess.run(['hadd', '-f', file_name] + run_files, check=True)
101  input_file = ROOT.TFile(f'{file_name}')
102  gStyle.SetOptStat(1111111)
103  gStyle.SetOptFit(1111)
104 
105  barrel_RPCPhi = TH2F("barrel_RPCPhi",
106  "time constants for Barrel RPC phi readout", 100, 30000, 65000, 100, 0.004, 0.015)
107  barrel_RPCZ = TH2F("barrel_RPCZ",
108  "time constants for Barrel RPC Z readout", 100, 30000, 65000, 100, 0.0, 0.0025)
109  barrel_scintillator = TH2F("barrel_scintillator",
110  "time constants for Barrel scintillator", 100, 30000, 65000, 100, 0.075, 0.09)
111  endcap_scintillator = TH2F("endcap_scintillator",
112  "time constants for endcap scintillator", 100, 0, 16000, 100, 0.069, 0.075)
113 
114  tree = input_file.Get("constants")
115  assert isinstance(tree, ROOT.TTree) == 1
116  myC = TCanvas("myC")
117 
118  tree.Draw("delayRPCPhi:channelNumber>>barrel_RPCPhi", "subdetector==1 & layer>=3", "colz")
119  barrel_RPCPhi.GetXaxis().SetTitle("Channel number")
120  barrel_RPCPhi.GetYaxis().SetTitle("Time Delay constants")
121  myC.Print("barrel_RPCPhi.png")
122 
123  tree.Draw("delayRPCZ:channelNumber>>barrel_RPCZ", "subdetector==1 & layer>=3", "colz")
124  barrel_RPCZ.GetXaxis().SetTitle("Channel number")
125  barrel_RPCZ.GetYaxis().SetTitle("Time Delay constants")
126  myC.Print("barrel_RPCZ.png")
127 
128  tree.Draw("delayBKLM:channelNumber>>barrel_scintillator", "subdetector==1 & layer<3", "colz")
129  barrel_scintillator.GetXaxis().SetTitle("Channel number")
130  barrel_scintillator.GetYaxis().SetTitle("Time Delay constants")
131  myC.Print("barrel_scintillator.png")
132 
133  tree.Draw("delayEKLM:channelNumber>>endcap_scintillator", "subdetector==2", "colz")
134  endcap_scintillator.GetXaxis().SetTitle("Channel number")
135  endcap_scintillator.GetYaxis().SetTitle("Time Delay constants")
136  myC.Print("endcap_scintillator.png")
137 
138  fout = TFile("KLMTimeConstants.root", "recreate")
139  barrel_RPCPhi.Write()
140  barrel_scintillator.Write()
141  endcap_scintillator.Write()
142  input_file.Close()
143  fout.Close()
144 
145  # Let's delete the files for single IoVs.
146  for run_file in run_files:
147  try:
148  os.remove(run_file)
149  except OSError as e:
150  basf2.B2ERROR(f'The file {run_file} can not be removed: {e.strerror}')
151 
152 
153 if __name__ == "__main__":
154  run_validation(*sys.argv[1:])