9 from PixelCalibAlgs.Recovery
import ReadDbFile, ReadNewCalib
10 from PathResolver
import PathResolver
13 from matplotlib.backends.backend_agg
import FigureCanvasAgg
14 from matplotlib.figure
import Figure
21 m_array = [
charge(parameters, 3*(1+i))
for i
in range(14)]
24 m_array = [
charge(parameters, 5*(1+i))
for i
in range(8)]
26 return ar.array(
'd',m_array)
29 num = tot*parameters[2] - parameters[0]*parameters[1]
30 den = parameters[0] - tot
31 return (num/den)
if den != 0
else 0
34 return a/(a+b)*100
if (a+b) != 0
else 999.99
40 expected_charge = 20000
47 expected_charge = 16000
49 if abs(parameters[9]-expected_charge)/expected_charge*100 > 5:
50 return True, [parameters[9], abs(parameters[9]-expected_charge)/expected_charge*100, expected_charge]
53 low = expected_charge*(1-error/100)
54 high = expected_charge*(1+error/100)
55 realQ =
charge(parameters, tot)
57 if realQ < low
or realQ > high:
58 return True, [
charge(parameters, tot), abs(
charge(parameters, tot)-expected_charge)/expected_charge*100,expected_charge]
61 def EvoMon(old_calib, new_calib, mapping, old_iov, new_iov):
67 information = {
"Total_mods": 0,
69 "IBL" :{
"bad":0,
"ok":0},
70 "Blayer":{
"bad":0,
"ok":0},
71 "L1" :{
"bad":0,
"ok":0},
72 "L2" :{
"bad":0,
"ok":0},
73 "Disk" :{
"bad":0,
"ok":0}
77 for mod
in range(2048):
79 mod_str = mapping[
str(mod)]
81 print(
"%-18s - %4i" % (mod_str, mod), end=
'\r')
82 plot_range = np.array([0,75000])
84 if str(mod)
not in new_calib:
87 if mod_str.startswith(
"L0"):
89 elif mod_str.startswith(
"L1"):
91 elif mod_str.startswith(
"L2"):
93 elif mod_str.startswith(
"D"):
97 if mod_str.startswith(
"LI_S15"):
100 information[
"Total_mods"] += 1
101 fig = Figure(figsize=(13,10))
102 axs = fig.add_subplot(1,1,1)
105 for fe
in range(len(new_calib[
str(mod)])):
107 information[
"Total_FE"] += 1
113 if mod_layer !=
"IBL":
114 newCal_normal_pix = new_calib[
str(mod)][fe][12:15]
115 oldCal_normal_pix = old_calib[
str(mod)][fe][12:15]
123 newQ = new_calib[
str(mod)][fe][4:20]
124 oldQ = old_calib[
str(mod)][fe][4:20]
126 plot_range = np.array([0,35000])
129 m,b = np.polyfit(newQ ,oldQ,1)
131 boolFit = (abs((1-m)/m)*100) > 5
133 if boolFit
or boolTOT:
134 key =
"%-18s - %i" % (mod_str, mod)
136 if key
not in log_info:
137 log_info[key] =
"\tFE%02i ---> slope: %5.2f - dev: %5.1f%%\n" % (fe,m, abs((1-m)/m)*100)
139 log_info[key] +=
"\tFE%02i ---> slope: %5.2f - dev: %5.1f%%\n" % (fe,m, abs((1-m)/m)*100)
141 if key
not in log_info:
142 log_info[key] =
"\tFE%02i ---> Charge= %5ie (dev %6.2f%%) out of error bars. Expected: %5ie\n" % (fe, realQ[0], realQ[1], realQ[2])
144 log_info[key] +=
"\tFE%02i ---> Charge= %5ie (dev %6.2f%%) out of error bars. Expected: %5ie\n" % (fe, realQ[0], realQ[1], realQ[2])
146 information[mod_layer][
"bad"] += 1
155 information[mod_layer][
"ok"] += 1
159 lstyle =
"dotted" if fe < 8
else "solid"
160 axs.plot(newQ ,oldQ, marker=
'o', linestyle=lstyle, label = (
"FE%02d" % (fe)))
161 axs.set_xlim(plot_range)
162 axs.set_ylim(plot_range)
165 fig.suptitle(
"Hash ID %d - %s" % (mod, mod_str))
166 axs.legend(loc=
'upper left', ncol=4)
167 axs.set_xlabel(new_iov+
" - Charge[e]")
168 axs.set_ylabel(old_iov+
" - Charge[e]")
169 axs.plot(plot_range,plot_range,
"k:",lw=1)
171 if mod_layer ==
'IBL':
172 axs.plot([16000,16000],plot_range,
"k:",lw=1)
173 axs.text(17000,1000,
"TOT@10 = 16 ke")
174 elif mod_layer ==
'Blayer':
175 axs.plot([20000,20000],plot_range,
"k:",lw=1)
176 axs.text(21000,1000,
"TOT@18 = 20 ke")
178 axs.plot([20000,20000],plot_range,
"k:",lw=1)
179 axs.text(21000,1000,
"TOT@30 = 20 ke")
181 storage =
"plots/" + mod_layer +
"/"
183 canvas = FigureCanvasAgg(fig)
184 canvas.print_figure(storage+
"Id"+
str(mod)+
"_" +mod_str+status+
".png", dpi=150)
187 fig = Figure(figsize=(13,10))
188 fig.suptitle(
"Fit slopes for all modules")
189 axs = fig.add_subplot(1,1,1)
190 axs.hist(np.clip(slopes, -1, 2), bins=100)
191 axs.set_xlabel(
"Fit slope")
192 axs.set_ylabel(
"Counts")
194 stats = (f
'$\\mu$ = {np.mean(np.clip(slopes, -1, 2)):.3f}\n'
195 f
'$\\sigma$ = {np.std(np.clip(slopes, -1, 2)):.3f}')
196 bbox = dict(boxstyle=
'round', fc=
'blanchedalmond', ec=
'orange', alpha=0.5)
197 axs.text(0.95, 0.07, stats, fontsize=9, bbox=bbox, transform=axs.transAxes)
199 FigureCanvasAgg(fig).print_figure(
"plots/FitSlopes.png", dpi=150)
201 return information, log_info
207 lines = fp.readlines()
209 arrayline = line.rstrip(
"\n").
split(
', ')
210 mydict[arrayline[1]] = arrayline[0]
215 with open(file)
as fp:
216 lines = fp.readlines()
218 arrayline = line.rstrip(
"\n").
split(
' ')
220 if arrayline[0]
not in mydict:
221 mydict[arrayline[0]] = []
224 while(
"" in arrayline):
227 mydict[arrayline[0]].
append([
int(arrayline[i])
if i<13
else float(arrayline[i])
for i
in range(1,len(arrayline)) ])
229 return mydict,
"[latest,0]"
232 new_iov =
"Latest IOV"
233 old_iov =
"Older IOV"
235 print(
"Files chosen for the comparison:")
237 print(
"New calibration: '%s'" % path_newCalib)
238 new_calib, new_iov =
"",
""
239 if "PIX_FINAL_calibration_candidate.txt" in path_newCalib:
241 elif "ChargeCalib_" in path_newCalib:
246 print(
"Old calibration: '%s'" % path_oldCalib)
247 old_calib, old_iov =
ReadDbFile(path_oldCalib)
252 os.makedirs(
"plots/Blayer", exist_ok=
True)
253 os.makedirs(
"plots/L1" , exist_ok=
True)
254 os.makedirs(
"plots/L2" , exist_ok=
True)
255 os.makedirs(
"plots/Disk" , exist_ok=
True)
256 os.makedirs(
"plots/IBL" , exist_ok=
True)
258 information, log_info =
EvoMon(old_calib, new_calib, mapping, old_iov, new_iov )
261 fout =
open(
"EvoMonitoring_log.txt",
"w")
263 fout.write(
"_______________ LOG _______________\n\n" )
264 fout.write(
"Files chosen for the comparison:\n" )
265 fout.write(
"New calibration: '%s'\n" % (path_newCalib) )
266 fout.write(
"Old calibration: '%s'\n" % (path_oldCalib) )
267 fout.write(
"Data base IOV: %s\n\n" % (old_iov) )
269 fout.write(
"-"*20+
" SUMMARY "+
"-"*20+
"\n" )
270 fout.write(
"%-20s: %5i\n" % (
"Total mods in det.", information[
"Total_mods"]))
271 fout.write(
"%-20s: %5i\n" % (
"Total FE in det." , information[
"Total_FE"] ))
272 fout.write(
"%-20s: %5i\n" % (
"Total FE IBL" , information[
"IBL"][
"ok"] +information[
"IBL"][
"bad"] ))
273 fout.write(
"%-20s: %5i\n" % (
"Total FE Blayer" , information[
"Blayer"][
"ok"]+information[
"Blayer"][
"bad"]))
274 fout.write(
"%-20s: %5i\n" % (
"Total FE L1" , information[
"L1"][
"ok"] +information[
"L1"][
"bad"] ))
275 fout.write(
"%-20s: %5i\n" % (
"Total FE L2" , information[
"L2"][
"ok"] +information[
"L2"][
"bad"] ))
276 fout.write(
"%-20s: %5i\n\n" % (
"Total FE Disk" , information[
"Disk"][
"ok"] +information[
"Disk"][
"bad"] ))
278 fout.write(
'FrontEnds deviating more than 5% of TOT vs charge gradient between new and previous calibration:\n')
279 fout.write(
"%-11s: %-4i (%6.2f%%)\n" % (
"IBL FEs" , information[
"IBL"][
"bad"] ,
percent(information[
"IBL"][
"bad"] ,information[
"IBL"][
"ok"]) ))
280 fout.write(
"%-11s: %-4i (%6.2f%%)\n" % (
"Blayer FEs", information[
"Blayer"][
"bad"],
percent(information[
"Blayer"][
"bad"],information[
"Blayer"][
"ok"])))
281 fout.write(
"%-11s: %-4i (%6.2f%%)\n" % (
"L1 FEs" , information[
"L1"][
"bad"] ,
percent(information[
"L1"][
"bad"] ,information[
"L1"][
"ok"]) ))
282 fout.write(
"%-11s: %-4i (%6.2f%%)\n" % (
"L2 FEs" , information[
"L2"][
"bad"] ,
percent(information[
"L2"][
"bad"] ,information[
"L2"][
"ok"]) ))
283 fout.write(
"%-11s: %-4i (%6.2f%%)\n\n" % (
"Disk FEs" , information[
"Disk"][
"bad"] ,
percent(information[
"Disk"][
"bad"] ,information[
"Disk"][
"ok"]) ))
285 fout.write(
"+"*20+
" List of bad FE "+
"+"*20+
"\n" )
286 fout.write(
"Expected TOT vs. charge for the different layers:\n")
287 fout.write(
"%-10s: TOT@%2i = %2ike\n" % (
"IBL" , 10, 16))
288 fout.write(
"%-10s: TOT@%2i = %2ike\n" % (
"Blayer" , 18, 20))
289 fout.write(
"%-10s: TOT@%2i = %2ike\n\n" % (
"L1/L2/Disk", 30, 20))
291 for key, val
in log_info.items():
298 fin =
open(
"EvoMonitoring_log.txt",
"r")
302 if __name__ ==
"__main__":
305 parser = argparse.ArgumentParser(prog=
'python -m PixelCalibAlgs.EvoMonitoring',
306 description=
"""Compares two IOV and plots the results.\n\n
307 Example: python -m PixelCalibAlgs.EvoMonitoring --new "path/to/file" --old "path/to/file" """)
309 parser.add_argument(
'--new', default=
"PIX_FINAL_calibration_candidate.txt", help=
"New calibration file (output format from the Recovery.py)")
310 parser.add_argument(
'--old', default=
"PixelChargeCalibration-DATA-RUN2-UPD4-27.log", help=
"Old DB IOV calibration")
312 args = parser.parse_args()