Belle II Software development
process_cosgain.py
1
8
9'''
10Implements cosgain correction
11'''
12
13import pandas as pd
14import matplotlib.pyplot as plt
15import matplotlib.ticker as ticker
16from ROOT.Belle2 import CDCDedxValidationAlgorithm
17from matplotlib.backends.backend_pdf import PdfPages
18
19
20def hist(y_min=None, y_max=None, x_min=None, x_max=None,
21 xlabel="", ylabel="", space=None, fx=1, fy=1,
22 fs1=20, fs2=8, font=18, rota=30, ax=None):
23 """
24 Configure histogram-style plot appearance.
25
26 If `ax` is None, applies to the current pyplot figure.
27 If `ax` is provided, applies to that axis (for subplots).
28 """
29 if ax is None:
30 fig, ax = plt.subplots(fx, fy, figsize=(fs1, fs2))
31 else:
32 fig = ax.get_figure()
33
34 if y_min is not None or y_max is not None:
35 ax.set_ylim(y_min, y_max)
36 if x_min is not None or x_max is not None:
37 ax.set_xlim(x_min, x_max)
38
39 ax.set_xlabel(xlabel, fontsize=font)
40 ax.set_ylabel(ylabel, fontsize=font)
41 ax.tick_params(axis='x', labelsize=font, rotation=rota)
42 ax.tick_params(axis='y', labelsize=font)
43
44 if space is not None:
45 ax.xaxis.set_major_locator(ticker.MultipleLocator(space))
46
47 ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.3f'))
48 ax.grid()
49
50 return fig, ax
51
52
53def parse_database(database_file, calib_key):
54 """Parse the database file and return exp -> [runs] mapping."""
55 exp_run_dict = {}
56 previous_exp = -666
57
58 with open(database_file) as f:
59 for line in f:
60 if line.startswith(calib_key):
61 try:
62 _, _, iov_str = line.strip().split(' ')
63 exp, run = map(int, iov_str.split(',')[:2])
64 if exp != previous_exp:
65 exp_run_dict[exp] = [run]
66 previous_exp = exp
67 else:
68 exp_run_dict[exp].append(run)
69 except Exception as e:
70 print(f"[WARNING] Skipping line: {line.strip()} due to error: {e}")
71 continue
72 return exp_run_dict
73
74
75def process_cosgain(ccpath, gt):
76 """Main function to process wiregain data and generate plots."""
77 import os
78 os.makedirs('plots/constant', exist_ok=True)
79
80 database_file = f'{ccpath}/database.txt'
81
82 # Parse the database to get exp -> [runs] mapping
83 exp_run_dict = parse_database(database_file, 'dbstore/CDCDedxCosineCor')
84
85 # Process each exp-run pair
86 for exp, run_list in exp_run_dict.items():
87 for run in run_list:
88 print(f"[INFO] Processing exp={exp}, run={run}")
89 cal = CDCDedxValidationAlgorithm()
90 cal.setGlobalTag(gt)
91 prev_data = cal.getcosgain(exp, run)
92 cal.setGlobalTag("")
93 cal.setTestingPayload(database_file)
94 new_data = cal.getcosgain(exp, run)
95 cal.setTestingPayload("")
96
97 # Extract wiregain vectors
98 prev_cc = prev_data.cosgain if prev_data else []
99 new_cc = new_data.cosgain if new_data else []
100 costh = new_data.costh if new_data else []
101
102 # Skip empty payloads
103 if not prev_cc or not new_cc:
104 print(f"[WARNING] Empty cosgain data for exp={exp}, run={run}. Skipping.")
105 return None, None
106
107 # Convert to DataFrames
108 df_prev = pd.DataFrame([[x] for x in prev_cc], columns=['cosgain'])
109 df_new = pd.DataFrame([[x] for x in new_cc], columns=['cosgain'])
110 df_costh = pd.DataFrame([[x] for x in costh], columns=['costh'])
111
112 pdf_path = f'plots/constant/cosgain_e{exp}_r{run}.pdf'
113 with PdfPages(pdf_path) as pdf:
114 fig, axes = plt.subplots(1, 2, figsize=(20, 6))
115
116 # Left plot
117 hist(0.7, 1.3, xlabel=r"$\cos\theta$", ylabel="dE/dx avg. mean ($e^{+}e^{-}$)", ax=axes[0])
118 axes[0].plot(df_costh['costh'], df_new['cosgain'], '*', label='new')
119 axes[0].plot(df_costh['costh'], df_prev['cosgain'], '*', label='prev')
120 axes[0].legend()
121
122 # Right plot
123 hist(0.99, 1.01, xlabel=r"$\cos\theta$", ylabel="Gain Ratio (new/prev)", ax=axes[1])
124 axes[1].plot(df_costh['costh'], df_new['cosgain']/df_prev['cosgain'], '*', label='ratio')
125 axes[1].legend()
126
127 fig.suptitle(f"CosGain Calibration - Experiment {exp}", fontsize=20)
128 fig.tight_layout()
129 pdf.savefig(fig)
130 plt.close(fig)
STL class.
Definition plot.py:1