5 This module contains classes for plotting calibration constants.
6 Author: qingyuan.liu@desy.de
9 __all__ = [
"ConditionCheckerBase",
"PXDMaskedPixelsChecker",
"PXDDeadPixelsChecker",
"PXDOccupancyInfoChecker"]
11 from abc
import ABC, abstractmethod
12 from ROOT
import Belle2
15 from root_numpy
import array2hist
16 from pxd.utils import get_sensor_graphs, get_sensor_maps, sensorID_list
17 from pxd.utils import latex_r, nPixels, nVCells, nUCells
30 type_list = [
'hot',
'dead',
'hot_dead',
'occ_no_mask',
'occ_masked']
32 label_list = [
'Hot pixels',
'Dead pixels',
'Hot/Dead pixels',
'No Mask',
'With Mask']
33 color_list = [ROOT.kRed + 1, ROOT.kAzure - 5, ROOT.kGray + 2, ROOT.kOrange + 1, ROOT.kSpring + 5]
34 max_list = [4., 4., 20., 3., 3.]
36 _type: {
'label': _label,
'color': _color,
'max': _max}
37 for (_type, _label, _color, _max)
in zip(type_list, label_list, color_list, max_list)
44 """Abstract base class describing interfaces to make plots from condition db."""
46 def __init__(self, name, objType, tfile, rundir="", use_hist=False):
85 DBObj type (read only)
105 Call functions at beginning of a run
112 Method to define TGraph
114 ytitle (str): Label for TGraph y-axis
117 self.
graphs.update(get_sensor_graphs(ytitle))
123 name (str): name for TH2, to which sensor name will be attached
124 title (str): title for TH2
125 ztitle (str): title for z-axis (color bar)
126 kwargs: additional arguments
130 self.
hists.update(get_sensor_maps(name, title, ztitle, self.
run, **kwargs))
135 Abstract method to get content of a payload
136 Should return a Dictionary with sensorID.getID() as key and relaated calibration results as value
142 Abstract method to get a value for each TGraph
144 sensor_db_content (Any): Calibration results of a module
149 Method to get a value for each TGraph
151 h2 (TH2): If not none, get value from h2
157 Method to set TH2 bins
159 h2 (TH2): TH2F object for handling values of a pixel matrix
160 sensor_db_content (Any): Calibration results of a module
166 Method to fill plot objects
168 if self.exp < self.expstart:
169 self.expstart = self.exp
170 if self.run < self.runstart:
171 self.runstart = self.run
172 if self.run > self.runend:
173 self.runend = self.run
175 db_content = self.get_db_content()
178 for sensorID
in sensorID_list:
179 sensor_db_content = db_content[sensorID.getID()]
181 if not self.use_hist:
182 values_dict[sensorID.getID()] = self.get_graph_value(sensor_db_content)
183 gr = self.graphs[sensorID.getID()]
184 pre_values_dict[sensorID.getID()] = gr.GetPointY(gr.GetN() - 1)
191 if self.rundir !=
"" and self.hists:
192 h2 = self.hists[sensorID.getID()]
193 self.set_hist_content(h2, sensor_db_content)
195 h2.SetTitle(h2.GetTitle() + self.hist_title_suffix)
196 self.tfile.cd(self.rundir)
199 values_dict[sensorID.getID()] = self.get_graph_value_from_hist(h2)
201 if values_dict != pre_values_dict:
202 for sensorID
in sensorID_list:
203 gr = self.graphs[sensorID.getID()]
204 gr.SetPoint(gr.GetN(), self.run, values_dict[sensorID.getID()])
206 def draw_plots(self, canvas=None, cname="", ymin=0., ymax=None):
208 Method to draw plots on a TCanvas
210 canvas (TCanvas): ROOT TCanvas for plotting
211 canme (str): Name of the canvas
212 ymin (float): minimum value of y-axis for plotting
213 ymax (float): maximum of y-axis for plotting
219 canvas.SetWindowSize(1000, 400)
220 canvas.SetLeftMargin(0.09)
221 canvas.SetRightMargin(0.05)
223 for i, sensorID
in enumerate(sensorID_list):
224 sensor_id = sensorID.getID()
227 self.
graphs[sensor_id].SetMaximum(ymax)
228 self.
graphs[sensor_id].SetMinimum(ymin)
229 self.
graphs[sensor_id].Draw(
"AP")
231 self.
graphs[sensor_id].Draw(
"P")
232 if self.
graphs[
"TLegends"]:
233 for leg
in self.
graphs[
"TLegends"]:
239 Save TCanvas to png/pdf format and write it to the default ROOT file
242 canvas.SetName(cname)
243 exp_run = f
"e{self.expstart:05}_r{self.runstart:04}-{self.runend:04}"
245 latex_r.DrawLatex(0.95, 0.92,
"Belle II Experiment: " + exp_run.replace(
"_",
" "))
248 canvas.Print(f
"{exp_run}_{cname}_vs_run.png")
249 canvas.Print(f
"{exp_run}_{cname}_vs_run.pdf")
254 canvas.Print(f
"{exp_run}_{cname}_vs_run_logy.png")
255 canvas.Print(f
"{exp_run}_{cname}_vs_run_logy.pdf")
262 Checker for PXDOccupancyInfoPar
272 Method to define TGraph
278 for sensorID
in sensorID_list:
279 numID = sensorID.getID()
280 raw_occ = self.
dbObj.getOccupancy(numID)
282 content_dic[numID] = raw_occ
if raw_occ >= 0
else 0
287 return sensor_db_content * 100
291 Method to draw plots on a TCanvas
298 class PXDMaskedPixelsChecker(ConditionCheckerBase):
300 Checker for PXDMaskedPixelPar
310 Method to define TGraph
318 super().
define_hists(name=
"MaskedPixels", title=
"Masked Pixels", ztitle=
"isMasked")
321 return self.
dbObj.getMaskedPixelMap()
324 hotcount = len(sensor_db_content)
327 return hotcount * 100. / nPixels
331 for pixelID
in sensor_db_content:
332 uCell = int(pixelID / nVCells)
333 vCell = pixelID % nVCells
334 h2.SetBinContent(int(uCell + 1), int(vCell + 1), 1)
336 def draw_plots(self, canvas=None, cname="PXDHotPixel", ymin=0., ymax=plot_type_dict["hot"]["max"]):
338 Method to draw plots on a TCanvas
340 super().
draw_plots(canvas=canvas, cname=cname, ymin=ymin, ymax=ymax)
345 Checker for PXDDeadPixelPar
348 def __init__(self, name, tfile, rundir="maps", use_hist=True):
355 Method to define TGraph
363 super().
define_hists(name=
"DeadPixels", title=
"Dead Pixels", ztitle=
"isDead")
366 deadsensormap = self.
dbObj.getDeadSensorMap()
367 deaddrainmap = self.
dbObj.getDeadDrainMap()
368 deadrowmap = self.
dbObj.getDeadRowMap()
369 deadsinglesmap = self.
dbObj.getDeadSinglePixelMap()
372 for sensorID
in sensorID_list:
373 numID = sensorID.getID()
374 content_dic[numID] = {}
375 if numID
in deadsensormap:
376 content_dic[numID][
"deadsensor"] =
True
378 content_dic[numID][
"deadsensor"] =
False
379 content_dic[numID][
"deaddrains"] = deaddrainmap[numID]
380 content_dic[numID][
"deadrows"] = deadrowmap[numID]
381 content_dic[numID][
"deadsingles"] = deadsinglesmap[numID]
386 if sensor_db_content[
"deadsensor"]:
389 n_deaddrains = len(sensor_db_content[
"deaddrains"])
390 n_deadrows = len(sensor_db_content[
"deadrows"])
391 if n_deaddrains == 0
or n_deadrows == 0:
393 deadcount = n_deaddrains * 192
397 deadcount += n_deadrows * 250
399 deadcount += len(sensor_db_content[
"deadsingles"])
402 h2 = list(get_sensor_maps(sensorID_list=sensorID_list[0:1]).values())[0]
404 deadcount = h2.Integral()
407 return min(deadcount, nPixels) * 100. / nPixels
410 return h2.Integral() * 100. / nPixels
414 if sensor_db_content[
"deadsensor"]:
415 ones = np.ones(nPixels)
418 for drainID
in sensor_db_content[
"deaddrains"]:
419 for iGate
in range(192):
421 vCell = drainID % 4 + iGate * 4
422 h2.SetBinContent(int(uCell + 1), int(vCell + 1), 1)
424 for vCell
in sensor_db_content[
"deadrows"]:
425 for uCell
in range(nUCells):
426 h2.SetBinContent(int(uCell + 1), int(vCell + 1), 1)
428 for pixelID
in sensor_db_content[
"deadsingles"]:
429 uCell = int(pixelID / nVCells)
430 vCell = pixelID % nVCells
431 h2.SetBinContent(int(uCell + 1), int(vCell + 1), 1)
433 def draw_plots(self, canvas=None, cname="PXDDeadPixel", ymin=0., ymax=plot_type_dict["dead"]["max"]):
435 Method to draw plots on a TCanvas
437 super().
draw_plots(canvas=canvas, cname=cname, ymin=ymin, ymax=ymax)
442 Checker for PXDGainMapPar
452 Method to define TGraph
460 nU = self.
dbObj.getBinsU()
461 nV = self.
dbObj.getBinsV()
462 super().
define_hists(name=
"GainMap", title=
"Gain / MC default", ztitle=
"Relative gain", nUCells=nU, nVCells=nV)
465 gainMap = self.
dbObj.getCalibrationMap()
467 for sensorID
in sensorID_list:
468 numID = sensorID.getID()
469 content_dic[numID] = np.array(list(gainMap[numID]))
474 sensor_db_content (np.array): Array of gain factors of a module
476 return sensor_db_content.mean()
479 array2hist(sensor_db_content.reshape(h2.GetNbinsX(), h2.GetNbinsY()), h2)
481 def draw_plots(self, canvas=None, cname="PXDGain", ymin=0.5, ymax=2.5):
483 Method to draw plots on a TCanvas
485 super().
draw_plots(canvas=canvas, cname=cname, ymin=ymin, ymax=ymax)