9"""Implements rungain correction"""
14import matplotlib.pyplot
as plt
15import process_cosgain
as cg
16from ROOT.Belle2
import CDCDedxValidationAlgorithm
17from matplotlib.backends.backend_pdf
import PdfPages
20def compute_block_averages(values, nblocks):
21 block_size = max(1, len(values) // nblocks)
23 for i
in range(0, len(values), block_size):
24 block = values[i:i + block_size]
25 avg = sum(block) / len(block)
26 averages.extend([avg] * len(block))
27 return averages[:len(values)]
30def parse_database(database_file, calib_key):
32 Parses a calibration database file and returns:
33 {exp: [(run, rev), ...]}
37 with open(database_file)
as f:
39 if line.startswith(calib_key):
41 parts = line.strip().split()
44 _, rev, iov_str = parts
45 exp, run =
map(int, iov_str.split(
',')[:2])
47 exp_run_dict.setdefault(exp, []).append((run, rev))
48 except Exception
as e:
49 print(f
"[WARNING] Skipping line: {line.strip()} | Error: {e}")
53def getRunGain(gtpath, gt):
54 os.makedirs(
"plots/constant", exist_ok=
True)
55 database_file = os.path.join(gtpath,
"database.txt")
56 calib_key =
"dbstore/CDCDedxRunGain"
58 exp_run_dict = parse_database(database_file, calib_key)
62 for exp, run_rev_list
in exp_run_dict.items():
63 for run, rev
in run_rev_list:
64 cal = CDCDedxValidationAlgorithm()
66 prev_data = cal.getrungain(exp, run)
68 if prev_data
is not None:
69 prev.append({
"exp": exp,
"run": run,
"gain": prev_data})
71 root_file = os.path.join(gtpath, f
"dbstore_CDCDedxRunGain_rev_{rev}.root")
72 file = ROOT.TFile.Open(root_file,
"READ")
73 if file
and not file.IsZombie():
74 rgain = file.Get(
"CDCDedxRunGain")
76 gain = rgain.getRunGain()
77 rows.append({
"exp": exp,
"run": run,
"gain": gain})
79 print(f
"[ERROR] Failed to open file or file is zombie: {root_file}")
82 df_prev = pd.DataFrame(prev)
83 df = pd.DataFrame(rows)
85 print(
"[WARNING] No data to process.")
88 for exp, df_exp
in df.groupby(
"exp"):
89 df_prev_exp = df_prev[df_prev[
"exp"] == exp]
91 gains = df_exp[
"gain"].tolist()
92 average = compute_block_averages(gains, nblocks=30)
93 df_exp[
"run"] = df_exp[
"run"].astype(str)
96 df_exp_sorted = df_exp.sort_values(
"run")
97 df_prev_exp_sorted = df_prev_exp.sort_values(
"run")
100 if len(df_prev_exp_sorted) == len(df_exp_sorted):
101 ratio = df_exp_sorted[
"gain"].values / df_prev_exp_sorted[
"gain"].values
103 print(f
"[WARNING] Exp {exp}: mismatch in number of runs, skipping ratio plot.")
106 sorted_gains = sorted(gains)
107 y_min, y_max = min(sorted_gains) - 0.04, max(sorted_gains) + 0.04
108 spacing = max(1, len(gains) // 10)
111 with PdfPages(f
"plots/constant/rungain_exp{exp}.pdf")
as pdf:
112 fig, ax = plt.subplots(1, 2, figsize=(20, 6))
115 cg.hist(y_min=y_min, y_max=y_max, xlabel=
"Run", ylabel=
"RunGain constant", space=spacing, ax=ax[0])
116 ax[0].
plot(df_exp[
"run"], df_exp[
"gain"],
'*', rasterized=
True, label=f
"exp{exp}")
117 ax[0].
plot(df_exp[
"run"], average,
'-', rasterized=
True, label=
"Block Avg (30 blocks)")
118 ax[0].legend(fontsize=12)
121 if ratio
is not None:
122 cg.hist(0.99, 1.01, xlabel=
"Run", ylabel=
"Gain Ratio (new/prev)", space=spacing, ax=ax[1])
123 ax[1].
plot(df_exp_sorted[
"run"], ratio,
'*', rasterized=
True, label=
"New / Prev")
124 ax[1].axhline(1.0, color=
'gray', linestyle=
'--')
125 ax[1].legend(fontsize=12)
127 ax[1].text(0.5, 0.5,
"Ratio unavailable", ha=
"center", va=
"center", fontsize=15)
130 fig.suptitle(f
"RunGain Calibration - Experiment {exp}", fontsize=20)