Belle II Software development
process_wiregain.py
1
8
9"""Implements wirgain correction"""
10
11import pandas as pd
12import numpy as np
13import matplotlib.pyplot as plt
14import ROOT
15from ROOT.Belle2 import CDCDedxValidationAlgorithm
16import process_cosgain as cg
17from matplotlib.backends.backend_pdf import PdfPages
18ROOT.gROOT.SetBatch(True)
19
20
21def remove_nowg(df):
22 # Inner layers: index < 1280 and wiregain != 0
23 il = df.loc[(df.index < 1280) & (df['wiregain'] != 0)].copy()
24
25 # Outer layers: index >= 1280 and wiregain != 0
26 ol = df.loc[(df.index >= 1280) & (df['wiregain'] != 0)].copy()
27
28 return il, ol
29
30
31def sep_inout(df):
32 il = df[df.index < 8].copy()
33 ol = df[df.index >= 8].copy()
34 return il, ol
35
36
37def process_wiregain_pair(cal, exp, run, database_file, gt):
38 """Process wiregain for a given exp-run pair."""
39
40 cal.setGlobalTag(gt)
41 prev_data = cal.getwiregain(exp, run)
42 cal.setGlobalTag("")
43 cal.setTestingPayload(database_file)
44 new_data = cal.getwiregain(exp, run)
45 cal.setTestingPayload("")
46
47 # Extract wiregain vectors
48 prev_wg = prev_data.wiregain if prev_data else []
49 new_wg = new_data.wiregain if new_data else []
50
51 # Skip empty payloads
52 if not prev_wg or not new_wg:
53 print(f"[WARNING] Empty wiregain data for exp={exp}, run={run}. Skipping.")
54 return None, None
55
56 # Convert to DataFrames
57 df_prev = pd.DataFrame([[x] for x in prev_wg], columns=['wiregain'])
58 df_new = pd.DataFrame([[x] for x in new_wg], columns=['wiregain'])
59
60 # Split into inner and outer layers
61 il_prev, ol_prev = remove_nowg(df_prev)
62 il_new, ol_new = remove_nowg(df_new)
63
64 return il_prev, ol_prev, il_new, ol_new
65
66
67def process_layermean(cal, exp, run, database_file, gt):
68
69 # Also add layer mean plots
70 cal.setGlobalTag(gt)
71 prev_data = cal.getwiregain(exp, run)
72 cal.setGlobalTag("")
73 cal.setTestingPayload(database_file)
74 new_data = cal.getwiregain(exp, run)
75 cal.setTestingPayload("")
76
77 df_prev_lm = pd.DataFrame([[x] for x in prev_data.layermean], columns=['layergain'])
78 df_new_lm = pd.DataFrame([[x] for x in new_data.layermean], columns=['layergain'])
79
80 il_lm_prev, ol_lm_prev = sep_inout(df_prev_lm)
81 il_lm_new, ol_lm_new = sep_inout(df_new_lm)
82
83 il_ratio = (il_lm_new['layergain'] / il_lm_prev['layergain']).dropna()
84 ol_ratio = (ol_lm_new['layergain'] / ol_lm_prev['layergain']).dropna()
85
86 return il_ratio, ol_ratio
87
88
89def plot_wiregain_all(il_prev, ol_prev, il_new, ol_new, exp, run, pdf, il_lay, ol_lay):
90 """Plot overlay, ratio and difference into a single PDF page."""
91
92 fig, ax = plt.subplots(2, 2, figsize=(20, 12))
93
94 # 1. Wiregain overlay (top-left)
95 ax[0, 0].set_title("Inner previous Wiregain")
96 cg.hist(0., 4, xlabel="#wire", ylabel="wg constant", space=100, ax=ax[0, 0])
97 ax[0, 0].plot(il_prev['wiregain'], 'o', label="Inner (prev)", markersize=5, alpha=0.7)
98 ax[0, 0].legend(fontsize=12)
99
100 ax[0, 1].set_title("Outer previous Wiregain")
101 cg.hist(0., 3, xlabel="#wire", ylabel="wg constant", space=1000, ax=ax[0, 1])
102 ax[0, 1].plot(ol_prev['wiregain'], '^', label="Outer (prev)", markersize=5, alpha=0.7)
103 ax[0, 1].legend(fontsize=12)
104
105 ax[1, 0].set_title("Inner new Wiregain")
106 cg.hist(0., 4, xlabel="#wire", ylabel="wg constant", space=100, ax=ax[1, 0])
107 ax[1, 0].plot(il_new['wiregain'], 's', label="Inner (new)", markersize=5, alpha=0.7)
108 ax[1, 0].legend(fontsize=12)
109
110 ax[1, 1].set_title("Outer new Wiregain")
111 cg.hist(0., 3, xlabel="#wire", ylabel="wg constant", space=1000, ax=ax[1, 1])
112 ax[1, 1].plot(ol_new['wiregain'], 'D', label="Outer (new)", markersize=5, alpha=0.7)
113 ax[1, 1].legend(fontsize=12)
114
115 fig.suptitle(f"WireGain Calibration - Experiment {exp}", fontsize=20)
116 plt.tight_layout()
117 pdf.savefig(fig)
118 plt.close(fig)
119
120 fig, ax = plt.subplots(2, 2, figsize=(20, 12))
121
122 # # 2. Ratio (top-right)
123 ax[0, 0].set_title("Inner Wiregain Ratio")
124 il_r = (il_new['wiregain'] / il_prev['wiregain']).dropna()
125 ol_r = (ol_new['wiregain'] / ol_prev['wiregain']).dropna()
126 cg.hist(0.7, 1.5, xlabel="#wire", ylabel="wiregain ratio", space=100, ax=ax[0, 0])
127 ax[0, 0].plot(il_r, '*', rasterized=True, label='Inner Layer')
128 ax[0, 0].legend(fontsize=12)
129
130 ax[0, 1].set_title("Outer Wiregain Ratio")
131 il_r = (il_new['wiregain'] / il_prev['wiregain']).dropna()
132 ol_r = (ol_new['wiregain'] / ol_prev['wiregain']).dropna()
133 cg.hist(0.7, 1.5, xlabel="#wire", ylabel="wiregain ratio", space=1000, ax=ax[0, 1])
134 ax[0, 1].plot(ol_r, '*', rasterized=True, label='Outer Layer')
135 ax[0, 1].legend(fontsize=12)
136
137 # 4. Ratio (middle-right)
138 ax[1, 0].set_title("Inner Wiregain Ratio (zoom)")
139 cg.hist(0.92, 1.05, xlabel="#wire", ylabel="wiregain ratio", space=100, ax=ax[1, 0])
140 ax[1, 0].plot(il_r, '*', rasterized=True, label='Inner Layer')
141 ax[1, 0].legend(fontsize=12)
142
143 ax[1, 1].set_title("Outer Wiregain Ratio (zoom)")
144 cg.hist(0.92, 1.05, xlabel="#wire", ylabel="wiregain ratio", space=1000, ax=ax[1, 1])
145 ax[1, 1].plot(ol_r, '*', rasterized=True, label='Outer Layer')
146 ax[1, 1].legend(fontsize=12)
147
148 plt.tight_layout()
149 pdf.savefig(fig)
150 plt.close(fig)
151
152 fig, ax = plt.subplots(1, 2, figsize=(20, 6))
153
154 # 5. Ratio Histogram (bottom -left)
155 ax[0].set_title("Wiregain Ratio histo")
156 cg.hist(x_min=0.7, x_max=1.5, xlabel=r"$\Delta$ wiregains", ylabel="Normalized count", fs1=10, fs2=6, ax=ax[0])
157
158 scale1 = 1 / il_r.shape[0] if il_r.shape[0] > 0 else 1
159 scale2 = 1 / ol_r.shape[0] if ol_r.shape[0] > 0 else 1
160
161 counts1, bins1 = np.histogram(il_r, bins=200)
162 counts2, bins2 = np.histogram(ol_r, bins=200)
163
164 ax[0].hist(bins1[:-1], bins=200, histtype='step', linewidth=2.5,
165 weights=counts1 * scale1, label='Inner layer')
166 ax[0].hist(bins2[:-1], bins=200, histtype='step', linewidth=2.5,
167 weights=counts2 * scale2, label='Outer Layer')
168
169 ax[0].legend(fontsize=12)
170
171 # 6. Layer Gain Ratio (bottom-right)
172 ax[1].set_title("Layer Gain Ratio")
173 cg.hist(0.9, 1.1, xlabel="#layer", ylabel="layer average ratio", space=5, fs1=10, fs2=6, ax=ax[1])
174 ax[1].plot(il_lay, '*', label="Inner Layers")
175 ax[1].plot(ol_lay, '*', label="Outer Layers")
176 ax[1].legend(fontsize=12)
177
178 plt.tight_layout()
179 pdf.savefig(fig)
180 plt.close(fig)
181
182
183def process_wiregain(wgpath, gt):
184 """Main function to process wiregain data and generate plots."""
185 import os
186 os.makedirs('plots/constant', exist_ok=True)
187 database_file = f'{wgpath}/database.txt'
188
189 exp_run_dict = cg.parse_database(database_file, "dbstore/CDCDedxWireGain")
190
191 for exp, run_list in exp_run_dict.items():
192 for run in run_list:
193 print(f"[INFO] Processing exp={exp}, run={run}")
194 cal = CDCDedxValidationAlgorithm()
195 il_prev, ol_prev, il_new, ol_new = process_wiregain_pair(cal, exp, run, database_file, gt)
196
197 if il_prev is None or ol_prev is None or il_new is None or ol_new is None:
198 continue
199
200 il_lay, ol_lay = process_layermean(cal, exp, run, database_file, gt)
201
202 pdf_path = f'plots/constant/wiregain_e{exp}_r{run}.pdf'
203 with PdfPages(pdf_path) as pdf:
204 plot_wiregain_all(il_prev, ol_prev, il_new, ol_new, exp, run, pdf, il_lay, ol_lay)
205
206 return exp_run_dict
Definition plot.py:1