Belle II Software development
vxdcdc_alignment.py
1#!/usr/bin/env python3
2
3
10
11from glob import glob
12from pathlib import Path
13import argparse
14
15from subprocess import run, CalledProcessError
16from shutil import copy2
17
18import matplotlib
19import matplotlib.pyplot as plt
20
21from prompt import ValidationSettings
22
23import alignment_validation.dimuon as dimuonval
24import alignment_validation.cosmics as cosmicval
25
26import ROOT as r
27r.PyConfig.IgnoreCommandLineOptions = True
28r.gROOT.SetBatch()
29
30matplotlib.use('Agg')
31plt.style.use("belle2")
32
33
34settings = ValidationSettings(name="Full VXD and CDC Alignment",
35 description=__doc__,
36 download_files=[],
37 expert_config=None)
38
39
40def run_validation(job_path, input_data_path=None, **kwargs):
41 '''job_path will be replaced with path/to/calibration_results
42 input_data_path will be replaced with path/to/data_path used for calibration
43 e.g. /group/belle2/dataprod/Data/PromptSkim/'''
44
45 collector_output_dir_cosmic = Path(job_path) / 'VXDCDCalignment_validation/0/collector_output/cosmic/'
46 collector_output_dir_mumu = Path(job_path) / 'VXDCDCalignment_validation/0/collector_output/mumu/'
47
48 output_dir = Path(kwargs.get('output_dir', 'VXDCDCAlignmentValidation_output'))
49 # create output directory if it does not exist
50 output_dir.mkdir(parents=True, exist_ok=True)
51
52 pattern_cosmic = str(collector_output_dir_cosmic) + "/*/cosmic_ana.root"
53 pattern_mumu = str(collector_output_dir_mumu) + "/*/dimuon_ana.root"
54
55 def hadd_and_get_merged_file(filenames_pattern, input_type):
56 root_files = glob(filenames_pattern)
57 merged_file = output_dir / f"{input_type}.root"
58
59 if len(root_files) > 1:
60 try:
61 run(
62 ["hadd", "-f", merged_file, *root_files],
63 capture_output=True,
64 text=True,
65 )
66 except CalledProcessError as e:
67 print(f"hadd failed with exit code {e.returncode}")
68 print(e.stdout)
69 print(e.stderr)
70
71 elif len(root_files) == 1:
72 copy2(root_files[0], merged_file)
73 else:
74 raise FileNotFoundError(f"No root files found for pattern: {filenames_pattern}")
75
76 return str(merged_file)
77
78 cosmic_file = hadd_and_get_merged_file(pattern_cosmic, "cosmics")
79 mumu_file = hadd_and_get_merged_file(pattern_mumu, "dimuon")
80
81 print(f"Merged ntuples saved in {cosmic_file} and {mumu_file}")
82 print("Running validation...")
83
84 cosmicval.run_validation([cosmic_file], output_dir=str(output_dir / "cosmics/"))
85 dimuonval.run_validation([mumu_file], output_dir=str(output_dir / "dimuon/"))
86
87 # Now merge std histograms stored in ColectorOutput.root
88 histo_pattern_cosmic = str(collector_output_dir_cosmic) + "/*/CollectorOutput.root"
89 histo_pattern_mumu = str(collector_output_dir_mumu) + "/*/CollectorOutput.root"
90
91 histo_cosmic = hadd_and_get_merged_file(histo_pattern_cosmic, "cosmic_CollectorOutput")
92 histo_mumu = hadd_and_get_merged_file(histo_pattern_mumu, "dimuon_CollectorOutput")
93
94 print(f"Merged CollectorOutput histograms saved in {histo_cosmic} and {histo_mumu}")
95
96 print("Alignment validation completed.")
97
98
99if __name__ == '__main__':
100 parser = argparse.ArgumentParser(description=__doc__,
101 formatter_class=argparse.RawTextHelpFormatter)
102
103 # b2val-prompt-run wants to pass to the script also input_data_path
104 # and requested_iov. As they are not required by this validation I just accept
105 # them together with calibration_results_dir and then ignore them
106 parser.add_argument('calibration_results_dir',
107 help='The directory that contains the collector outputs',
108 nargs='+')
109
110 parser.add_argument('-o', '--output_dir',
111 help='The directory where all the output will be saved',
112 default='VXDCDCAlignmentValidation_output')
113 args = parser.parse_args()
114
115 run_validation(args.calibration_results_dir[0], output_dir=args.output_dir)