18 import matplotlib.pyplot
as plt
21 r.PyConfig.IgnoreCommandLineOptions =
True
24 plt.style.use(
"belle2")
27 def progress(count, total):
29 filled_len = int(round(bar_len * count / total))
30 percents = round(100 * count / total, 1)
31 bar =
'=' * filled_len +
'-' * (bar_len - filled_len)
32 sys.stdout.write(f
'[{bar}] {percents}%\r')
36 def get_full_path(name, exp, run, base_dir):
37 return f
'{base_dir}/{name}/{name}_{exp}.{run}/{name}_1'
40 def get_combined(histos, pattern):
42 Sum histograms that match a certain pattern shell-style, e.g.
43 "*" all, "L3*" all layer 3, "*U" all U-sensors
46 histos (dict{label : TH1}): dictionary of
47 patern (str): shell-styel matching pattern
50 good_keys = [key
for key
in histos.keys()
if fnmatch.fnmatch(key, pattern)]
52 assert len(good_keys) > 0
54 h = histos[good_keys[0]].Clone()
55 h.SetName(h.GetName().split(
'__')[0]+f
'__{pattern}')
56 h.SetTitle(h.GetName().split(
'__')[0]+f
' in {pattern}')
58 for key
in good_keys[1:]:
64 def get_histo_offTracks(histo_all, histo_onTracks):
66 Substract the histogram with the clusters on tracks from the histogram with all the clusters
67 to get the histogram with the clusters off tracks
70 histo_offTracks = histo_all.Clone(histo_all.GetName().replace(
'all',
'offTracks'))
71 histo_offTracks.SetTitle(histo_offTracks.GetTitle().replace(
'All',
'OffTracks'))
72 histo_offTracks.Add(histo_onTracks, -1)
73 return histo_offTracks
74 except (ReferenceError, TypeError):
78 def get_agreement(histo_eventT0, histo_diff, min_entries=100):
80 Get the mean of the difference between the mean time of the clusters on tracks and
81 the mean eventT0 divided by the RMS of the event T0
83 if histo_eventT0.GetEntries() > min_entries
and histo_diff.GetEntries() > min_entries:
84 return histo_diff.GetMean()/histo_eventT0.GetRMS()
89 def get_precision(histo_diff, min_entries=100):
91 Get the RMS of the difference between the mean time of the clusters on tracks
93 if histo_diff.GetEntries() > min_entries:
94 return histo_diff.GetRMS()
99 def get_agreement2(histo_eventT0, histo_onTracks, min_entries=100):
101 Get the difference between the mean time of the clusters on tracks and the mean eventT0 divided by the RMS of the event T0
104 if histo_eventT0.GetEntries() > min_entries
and histo_onTracks.GetEntries() > min_entries:
105 return (histo_onTracks.GetMean() - histo_eventT0.GetMean())/histo_eventT0.GetRMS()
110 def get_shift_plot(shift_histos, min_entries=100):
112 The creates a 2D plot to visualize the shift of mean of the
113 cluster time distribution for each cluster sizes for each sensor group.
117 for key, hShift
in shift_histos.items():
118 if hShiftVal
is None:
119 nxbins = len(shift_histos)
120 nybins = hShift.GetNbinsY()
121 hShiftVal = r.TH2F(
"hShiftVal",
"Cluster Size VS Shift Values in Each Sensor Group",
122 nxbins, 0.5, nxbins + 0.5, nybins, 0.5, nybins + 0.5)
123 hShiftVal.GetZaxis().SetTitle(
"(Not fitted) Mean of Cluster Time Distribution (in ns)")
124 hShiftVal.GetYaxis().SetTitle(
"Cluster Size")
126 for ij
in range(hShift.GetNbinsY()):
127 hist = hShift.ProjectionX(
"tmp", ij + 1, ij + 1,
"")
128 if hist.GetSumOfWeights() > min_entries:
129 hShiftVal.SetBinContent(binNumber, ij + 1, hist.GetMean())
131 hShiftVal.GetXaxis().SetBinLabel(binNumber, key)
134 hShiftVal.SetStats(0)
135 hShiftVal.GetXaxis().LabelsOption(
"V")
139 def get_shift_agreement(shift_histo, min_entries=100):
141 It calculates the mean of cluster-time distribution for each cluster size.
142 Then returns the average of the squared sum of the means.
145 if isinstance(shift_histo, r.TH2):
146 for ij
in range(shift_histo.GetNbinsY()):
147 hist = shift_histo.ProjectionX(
"tmp", ij + 1, ij + 1,
"")
148 if hist.GetSumOfWeights() > min_entries:
149 hmean = hist.GetMean()
150 mean_values.append(hmean * hmean)
151 if not len(mean_values):
154 return np.sqrt(np.sum(mean_values)) / len(mean_values)
157 def make_roc(hist_sgn, hist_bkg, lower_is_better=False, two_sided=True):
158 from hist_utils
import hist2array
159 dist_sgn = hist2array(hist_sgn)
160 dist_bkg = hist2array(hist_bkg)
161 dist_sgn = dist_sgn/dist_sgn.sum()
162 dist_bkg = dist_bkg/dist_bkg.sum()
164 dist_sgn = np.append(dist_sgn, [0])
165 dist_bkg = np.append(dist_bkg, [0])
166 eff_sgn = tuple(reversed([sum(dist_sgn[i:-(1+i)])
for i
in range(math.ceil(len(dist_sgn)/2)+1)]))
167 eff_bkg = tuple(reversed([sum(dist_bkg[i:-(1+i)])
for i
in range(math.ceil(len(dist_bkg)/2)+1)]))
169 if not lower_is_better:
170 dist_sgn = np.array(tuple(reversed(dist_sgn)))
171 dist_bkg = np.array(tuple(reversed(dist_bkg)))
172 eff_sgn = [sum(dist_sgn[:i+1])
for i
in range(len(dist_sgn))]
173 eff_bkg = [sum(dist_bkg[:i+1])
for i
in range(len(dist_bkg))]
174 return eff_sgn, [1-i
for i
in eff_bkg]
177 def get_roc_auc(hist_sgn, hist_bkg, lower_is_better=False, two_sided=True, min_entries=100):
178 if hist_sgn.GetEntries() > min_entries
and hist_bkg.GetEntries() > min_entries:
180 return np.trapz(*reversed(make_roc(
182 lower_is_better=lower_is_better,
183 two_sided=two_sided)))
188 def np2plt_hist(np_hist):
189 return {
'x': np_hist[1][0][:-1],
'bins': np_hist[1][0],
'weights': np_hist[0]}
192 def make_combined_plot(pattern, histos, title=None):
193 from hist_utils
import hist2array
194 h_onTracks = hist2array(get_combined(histos[
'onTracks'], pattern), return_edges=
True)
195 h_offTracks = hist2array(get_combined(histos[
'offTracks'], pattern), return_edges=
True)
196 h_eventT0 = hist2array(histos[
'eventT0'], return_edges=
True)
199 h_eventT0 = (h_eventT0[0]*sum(h_onTracks[0])/sum(h_eventT0[0]), h_eventT0[1])
202 plt.hist(h_onTracks[1][0][:-1], h_onTracks[1][0], weights=h_onTracks[0], histtype=
'step', label=
'on tracks')
203 plt.hist(h_offTracks[1][0][:-1], h_offTracks[1][0], weights=h_offTracks[0], histtype=
'step', label=
'off tracks')
204 plt.hist(h_eventT0[1][0][:-1], h_eventT0[1][0], weights=h_eventT0[0], histtype=
'step', label=
'event T0')
205 plt.legend(loc=
'upper right')
206 plt.xlabel(
'cluster time [ns]')
207 if title
is not None:
214 ladder_of_layer = [7, 10, 12, 16]
215 sensor_on_layer = [2, 3, 4, 5]
216 for layer
in range(3, 7):
217 for ladder
in range(1, ladder_of_layer[layer-3]+1):
218 for sensor
in range(1, sensor_on_layer[layer-3]+1):
219 for side
in [
'U',
'V']:
220 names_sides.append(f
'L{layer}L{ladder}S{sensor}{side}')
224 names_grouped_sides = []
225 for layer
in range(3, 7):
226 for sensor
in range(1, sensor_on_layer[layer-3]+1):
227 for side
in [
'U',
'V']:
228 names_grouped_sides.append(f
'L{layer}L*S{sensor}{side}')
231 time_algorithms = [
'CoG6',
'CoG3',
'ELS3']
234 def get_histos(CollectorHistograms):
238 histos[
'eventT0'] = CollectorHistograms[
'hEventT0'][0]
241 histos[
'onTracks'] = {}
243 histos[
'timeShifter'] = {}
245 __hClsTimeOnTracks__ = CollectorHistograms[
'hClsTimeOnTracks'][0]
246 __hClsTimeAll__ = CollectorHistograms[
'hClsTimeAll'][0]
247 __hClsDiffTimeOnTracks__ = CollectorHistograms[
'hClsDiffTimeOnTracks'][0]
248 __hClusterSizeVsTimeResidual__ = CollectorHistograms[
'hClusterSizeVsTimeResidual'][0]
249 __hBinToSensorMap__ = CollectorHistograms[
'hBinToSensorMap'][0]
251 for name_side
in names_sides:
252 sensorBin = __hBinToSensorMap__.GetXaxis().FindBin(name_side)
254 hClsTimeOnTracks = __hClsTimeOnTracks__.ProjectionX(
"hClsTimeOnTracks_tmp", sensorBin, sensorBin)
255 hClsTimeAll = __hClsTimeAll__.ProjectionX(
"hClsTimeAll_tmp", sensorBin, sensorBin)
256 hClsDiffTimeOnTracks = __hClsDiffTimeOnTracks__.ProjectionX(
"hClsDiffTimeOnTracks_tmp", sensorBin, sensorBin)
258 __hClusterSizeVsTimeResidual__.GetZaxis().SetRange(sensorBin, sensorBin)
259 hClusterSizeVsTimeResidual = __hClusterSizeVsTimeResidual__.Project3D(
"yxe")
261 hClsTimeOnTracks.SetNameTitle(f
"clsTimeOnTracks__{name_side}", f
"clsTimeOnTracks__{name_side}")
262 hClsTimeAll.SetNameTitle(f
"clsTimeAll__{name_side}", f
"clsTimeAll__{name_side}")
263 hClsDiffTimeOnTracks.SetNameTitle(f
"clsDiffTimeOnTracks__{name_side}", f
"clsDiffTimeOnTracks__{name_side}")
264 hClusterSizeVsTimeResidual.SetNameTitle(f
"clusterSizeVsTimeResidual__{name_side}",
265 f
"Cluster Size vs Time Residual in {name_side}")
267 hClsTimeOnTracks.SetDirectory(0)
268 hClsTimeAll.SetDirectory(0)
269 hClsDiffTimeOnTracks.SetDirectory(0)
270 hClusterSizeVsTimeResidual.SetDirectory(0)
272 histos[
'onTracks'][name_side] = hClsTimeOnTracks
273 histos_all[name_side] = hClsTimeAll
274 histos[
'diff'][name_side] = hClsDiffTimeOnTracks
275 histos[
'timeShifter'][name_side] = hClusterSizeVsTimeResidual
277 histos[
'offTracks'] = {key: get_histo_offTracks(histos_all[key], histos[
'onTracks'][key])
278 for key
in histos[
'onTracks']}
281 for kind
in [
'onTracks',
'offTracks',
'diff']:
282 for key, value
in histos[kind].items():
283 if not isinstance(value, r.TH1):
284 histos[kind][key] = r.TH1F(f
'{kind}_{key}', f
'{kind}_{key}', 300, -150, 150)
289 def get_merged_collector_histograms(files):
291 CollectorHistograms = {}
293 num_files = len(files)
294 print(f
'Looping over {num_files} files')
295 progress(0, num_files)
296 for count, in_file_name
in enumerate(files):
298 in_file = r.TFile(str(in_file_name))
300 for algo
in time_algorithms:
302 base_dir = f
'SVDTimeValidationCollector_{algo}'
303 iov = in_file.Get(f
'{base_dir}/RunRange').getIntervalOfValidity()
304 exp, run = iov.getExperimentLow(), iov.getRunLow()
306 if algo
not in CollectorHistograms:
307 CollectorHistograms[algo] = {}
308 if exp
not in CollectorHistograms[algo]:
309 CollectorHistograms[algo][exp] = {}
310 if run
not in CollectorHistograms[algo][exp]:
311 CollectorHistograms[algo][exp][run] = {
"hEventT0": [],
312 "hClsTimeOnTracks": [],
314 "hClsDiffTimeOnTracks": [],
315 "hClusterSizeVsTimeResidual": [],
316 "hBinToSensorMap": []}
318 __hEventT0__ = in_file.Get(get_full_path(
'hEventT0', exp, run, base_dir))
319 __hClsTimeOnTracks__ = in_file.Get(get_full_path(
'__hClsTimeOnTracks__',
321 __hClsTimeAll__ = in_file.Get(get_full_path(
'__hClsTimeAll__',
323 __hClsDiffTimeOnTracks__ = in_file.Get(get_full_path(
'__hClsDiffTimeOnTracks__',
325 __hClusterSizeVsTimeResidual__ = in_file.Get(get_full_path(
'__hClusterSizeVsTimeResidual__',
327 __hBinToSensorMap__ = in_file.Get(get_full_path(
'__hBinToSensorMap__',
329 __hEventT0__.SetDirectory(0)
330 __hClsTimeOnTracks__.SetDirectory(0)
331 __hClsTimeAll__.SetDirectory(0)
332 __hClsDiffTimeOnTracks__.SetDirectory(0)
333 __hClusterSizeVsTimeResidual__.SetDirectory(0)
334 __hBinToSensorMap__.SetDirectory(0)
335 CollectorHistograms[algo][exp][run][
"hEventT0"].append(__hEventT0__)
336 CollectorHistograms[algo][exp][run][
"hClsTimeOnTracks"].append(__hClsTimeOnTracks__)
337 CollectorHistograms[algo][exp][run][
"hClsTimeAll"].append(__hClsTimeAll__)
338 CollectorHistograms[algo][exp][run][
"hClsDiffTimeOnTracks"].append(__hClsDiffTimeOnTracks__)
339 CollectorHistograms[algo][exp][run][
"hClusterSizeVsTimeResidual"].append(__hClusterSizeVsTimeResidual__)
340 CollectorHistograms[algo][exp][run][
"hBinToSensorMap"].append(__hBinToSensorMap__)
345 progress(count+1, num_files)
349 for algo
in CollectorHistograms:
350 for exp
in CollectorHistograms[algo]:
351 for run
in CollectorHistograms[algo][exp]:
352 for key
in CollectorHistograms[algo][exp][run]:
353 for hist
in CollectorHistograms[algo][exp][run][key][1:]:
354 CollectorHistograms[algo][exp][run][key][0].Add(hist)
356 return CollectorHistograms