Belle II Software development
validateOverlay.py
1#!/usr/bin/env python3
2
3
10
11"""
12<header>
13 <output>overlayPlots.root</output>
14 <contact>marko.staric@ijs.si</contact>
15 <description>Runs BG overlay and makes validation histograms</description>
16</header>
17"""
18
19import basf2 as b2
20from simulation import add_simulation
21import os
22import glob
23from ROOT import Belle2
24from ROOT import TH1F, TFile, TNamed, TNtuple
25import sys
26import array
27
28b2.set_random_seed(123452)
29
30
31class Histogrammer(b2.Module):
32
33 '''
34 Make validation histograms for BG overlay.
35 This validation assumes that all channels are active
36 (no masked strip, dead pixels, ...)
37 '''
38
39 def initialize(self):
40 ''' Initialize the Module: book histograms and set descriptions and checks'''
41
42
43 self.hist = []
44 self.hist.append(TH1F('PXDDigits', 'PXDDigits (no data reduction)',
45 200, 0, 100000))
46 self.hist.append(TH1F('SVDShaperDigits', 'SVDShaperDigits', 100, 0, 10000))
47 self.hist.append(TH1F('SVDShaperDigitsZS5', 'ZS5 SVDShaperDigits', 100, 0, 8000))
48 self.hist.append(TH1F('CDCHits', 'CDCHits above threshold', 100, 0, 6000))
49 self.hist.append(TH1F('TOPDigits', 'TOPDigits', 100, 0, 2000))
50 self.hist.append(TH1F('ARICHDigits', 'ARICHDigits', 100, 0, 300))
51 self.hist.append(TH1F('ECLDigits', 'ECLDigits, m_Amp > 500 (roughly 25 MeV)',
52 100, 0, 400))
53 self.hist.append(TH1F('KLMDigits', 'KLMDigits', 150, 0, 150))
54
55
56 self.hist2 = []
57 self.hist2.append(TH1F('PXDL1Occupancy', 'PXD L1 Occupancy', 100, 0, 4))
58 self.hist2.append(TH1F('PXDL2Occupancy', 'PXD L2 Occupancy', 100, 0, 4))
59 self.hist2.append(TH1F('PXDOccupancy', 'PXD Occupancy', 100, 0, 4))
60 self.hist2.append(TH1F('SVDOccupancy', 'SVD L3 Occupancy', 100, 0, 15))
61 self.hist2.append(TH1F('CDCInnerHitRate', 'CDC Hit Rate per wire for the Inner layers', 100, 0, 1000))
62 self.hist2.append(TH1F('CDCOuterHitRate', 'CDC Hit Rate per wire for the Outer layers', 100, 0, 1000))
63 self.hist2.append(TH1F('CDCHitRate', 'CDC Hit Rate per wire', 100, 0, 1000))
64 self.hist2.append(TH1F("TOPHitTime", "TOP Hit Time Distribution; time [ns]", 300, -150, 150))
65
66 self.nTOPev = 0
67
68 self.minTOPTime = None
69
70 self.maxTOPTime = None
71
72
73 self.nPXDL1 = 250*768*2 * 8
74
75 self.nPXDL2 = 250*768*2 * 12
76 if len(sys.argv) == 3 and int(sys.argv[2]) == 1003:
77 self.nPXDL2 = 250*768*2 * 2
78
79 self.nPXD = self.nPXDL1 + self.nPXDL2
80
81
82 self.nSVDL3 = 768 * 7 * 2 * 2
83
84
85 self.nCDCin = 160 * 8
86
87 self.CDCITIn = 408.7 * 1e-6
88
89 self.nCDCout = 160*6 + 192*6 + 224*6 + 256*6 + 288*6 + 320*6 + 352*6 + 384 * 6
90
91 self.CDCITout = 754.6 * 1e-6
92
93
94 self.allh = self.hist+self.hist2
95
96 for h in self.allh:
97 if h.GetName() == 'PXDOccupancy':
98 h.SetXTitle('PXD occupancy [%]')
99 option = 'shifter'
100 descr = TNamed(
101 'Description',
102 'PXD L1+L2 Occupancy per event - no data reduction (with BG overlay only and no event generator)')
103 elif h.GetName() == 'PXDL1Occupancy':
104 h.SetXTitle('PXD L1 occupancy [%]')
105 option = 'shifter'
106 descr = TNamed(
107 'Description',
108 'PXD L1 Occupancy per event - no data reduction (with BG overlay only and no event generator)')
109 elif h.GetName() == 'PXDL2Occupancy':
110 h.SetXTitle('PXD L2 occupancy [%]')
111 option = 'shifter'
112 descr = TNamed(
113 'Description',
114 'PXD L2 Occupancy per event - no data reduction (with BG overlay only and no event generator)')
115 elif h.GetName() == 'SVDOccupancy':
116 h.SetXTitle('SVD L3 ZS5 occupancy - average u,v [%]')
117 option = 'shifter'
118 descr = TNamed(
119 'Description',
120 'SVD ZS5 L3 Occupancy per event average u,v (with BG overlay only and no event generator)')
121 elif h.GetName() == 'CDCHitRate':
122 h.SetXTitle('CDC Hit Rate [kHz/wire]')
123 option = 'shifter'
124 descr = TNamed(
125 'Description',
126 'CDC Hit Rate, averaged inner/outer wires (with BG overlay only and no event generator)')
127 elif h.GetName() == 'CDCInnerHitRate':
128 h.SetXTitle('CDC Hit Rate for Inner Layers [kHz/wire]')
129 option = 'shifter'
130 descr = TNamed(
131 'Description',
132 'CDC Hit Rate per wire, for the Inner layers (with BG overlay only and no event generator)')
133 elif h.GetName() == 'CDCOuterHitRate':
134 h.SetXTitle('CDC Hit Rate for Outer Layers [kHz/wire]')
135 option = 'shifter'
136 descr = TNamed(
137 'Description',
138 'CDC Hit Rate per wire, for the Outer layers (with BG overlay only and no event generator)')
139 else:
140 h.SetXTitle('number of digits in event')
141 option = 'shifter'
142 descr = TNamed('Description', 'Number of background ' + h.GetName() +
143 ' per event (with BG overlay only and no event generator)')
144
145 if h.GetName() == 'PXDDigits':
146 option = 'expert'
147 elif h.GetName() == 'SVDShaperDigits':
148 option = 'expert'
149 elif h.GetName() == 'SVDShaperDigitsZS5':
150 option = 'expert'
151 elif h.GetName() == 'CDCHits':
152 option = 'expert'
153 elif h.GetName() == 'TOPHitTime':
154 option = 'expert'
155
156 h.SetYTitle('entries per bin')
157 h.GetListOfFunctions().Add(descr)
158 check = TNamed('Check', 'Distribution must agree with its reference')
159 h.GetListOfFunctions().Add(check)
160 contact = TNamed('Contact', 'marko.staric@ijs.si')
161 h.GetListOfFunctions().Add(contact)
162 options = TNamed('MetaOptions', option)
163 h.GetListOfFunctions().Add(options)
164
165 ntplvar = "PXDL1_occupancy:PXDL2_occupancy:PXD_occupancy:SVDL3ZS5_occupancy"
166 ntplvar += ":CDCInner_hitRate:CDCOuter_hitRate:CDC_hitRate:TOP_hitRate"
167
168
169 self.ntpl = TNtuple("ntpl", "Average Background Levels", (ntplvar))
170
171 def event(self):
172 ''' Event processor: fill histograms '''
173
174 for h in self.hist:
175 digits = Belle2.PyStoreArray(h.GetName())
176 if h.GetName() == 'CDCHits':
177 continue
178 if h.GetName() == 'ECLDigits':
179 n = 0
180 for digit in digits:
181 if digit.getAmp() > 500: # roughly 25 MeV
182 n += 1
183 h.Fill(n)
184 else:
185 h.Fill(digits.getEntries())
186
187 # PXD
188 pxdDigits = Belle2.PyStoreArray('PXDDigits')
189 self.hist2[2].Fill(pxdDigits.getEntries()/self.nPXD * 100)
190 nL1 = 0
191 nL2 = 0
192 for pxdDigit in pxdDigits:
193 if pxdDigit.getSensorID().getLayerNumber() == 1: # check L1/L2
194 nL1 += 1
195 else:
196 nL2 += 1
197 self.hist2[0].Fill(nL1/self.nPXDL1 * 100)
198 self.hist2[1].Fill(nL2/self.nPXDL2 * 100)
199
200 # SVD
201 svdDigits = Belle2.PyStoreArray('SVDShaperDigitsZS5')
202 nL3 = 0
203 for svdDigit in svdDigits:
204 if svdDigit.getSensorID().getLayerNumber() == 3: # only check SVD L3
205 nL3 += 1
206 self.hist2[3].Fill(nL3/self.nSVDL3 * 100)
207
208 # CDC
209 cdcHits = Belle2.PyStoreArray('CDCHits')
210 nCDC_in = 0
211 nCDC_out = 0
212 for cdcHit in cdcHits: # count wires of inner/outer layers
213 if cdcHit.getISuperLayer() == 0 and cdcHit.getADCCount() > 15:
214 nCDC_in += 1
215 if cdcHit.getISuperLayer() != 0 and cdcHit.getADCCount() > 18:
216 nCDC_out += 1
217 self.hist2[4].Fill(nCDC_in/self.nCDCin / self.CDCITIn)
218 self.hist2[5].Fill(nCDC_out/self.nCDCout / self.CDCITout)
219 self.hist2[6].Fill((nCDC_in+nCDC_out) / (self.nCDCin * self.CDCITIn + self.nCDCout * self.CDCITout))
220 self.hist[3].Fill(nCDC_in+nCDC_out)
221
222 # TOP
223 self.nTOPev += 1
224 for TOPDigit in Belle2.PyStoreArray('TOPDigits'):
225 if TOPDigit.getHitQuality() != Belle2.TOPDigit.c_Good:
226 continue
227 self.hist2[7].Fill(TOPDigit.getTime())
228 if self.minTOPTime:
229 self.minTOPTime = min(self.minTOPTime, TOPDigit.getTime())
230 self.maxTOPTime = max(self.maxTOPTime, TOPDigit.getTime())
231 else:
232 self.minTOPTime = TOPDigit.getTime()
233 self.maxTOPTime = TOPDigit.getTime()
234
235 def terminate(self):
236 """ Write histograms to file."""
237
238 TOPbg = self.hist2[7].Integral(101, 150)/self.nTOPev/50e-3/16/32
239
240 # ntpl content "PXDL1:PXDL2:PXD:SVDL3ZS5:CDCInner:CDCOuter:CDC:TOP");
241 values = [self.hist2[0].GetMean(), self.hist2[1].GetMean(), self.hist2[2].GetMean(),
242 self.hist2[3].GetMean(), self.hist2[4].GetMean(), self.hist2[5].GetMean(),
243 self.hist2[6].GetMean(), float(TOPbg)]
244
245 self.ntpl.Fill(array.array("f", values),)
246 tfile = TFile('overlayPlots.root', 'recreate')
247 self.ntpl.Write()
248 for h in self.allh:
249 h.Write()
250 tfile.Close()
251
252
253bg = None
254exp = 0
255if len(sys.argv) == 3:
256 b2.B2INFO('Using background samples for experiment ' + sys.argv[2] + ' at ' + sys.argv[1])
257 bg = glob.glob(str(sys.argv[1]) + '/*.root')
258 exp = int(sys.argv[2])
259elif 'BELLE2_BACKGROUND_DIR' in os.environ:
260 bg = glob.glob(os.environ['BELLE2_BACKGROUND_DIR'] + '/*.root')
261 if bg is None:
262 b2.B2FATAL('No beam background samples found in folder ' +
263 os.environ['BELLE2_BACKGROUND_DIR'])
264 b2.B2INFO('Using background samples from ' + os.environ['BELLE2_BACKGROUND_DIR'])
265else:
266 b2.B2FATAL('variable BELLE2_BACKGROUND_DIR is not set')
267
268# Create path
269main = b2.create_path()
270
271# Set number of events to generate
272eventinfosetter = b2.register_module('EventInfoSetter')
273eventinfosetter.param({'evtNumList': [1000], 'runList': [1], 'expList': [exp]})
274main.add_module(eventinfosetter)
275
276# Simulation
277add_simulation(main, bkgfiles=bg, bkgOverlay=True, usePXDDataReduction=False, forceSetPXDDataReduction=True,
278 simulateT0jitter=False)
279
280# Add SVD offline zero-suppression (ZS5)
281main.add_module(
282 'SVDZeroSuppressionEmulator',
283 SNthreshold=5,
284 ShaperDigits='SVDShaperDigits',
285 ShaperDigitsIN='SVDShaperDigitsZS5',
286 FADCmode=True)
287
288# Make histograms
289main.add_module(Histogrammer())
290
291# Show progress of processing
292main.add_module('Progress')
293
294# Process events
295b2.process(main)
296
297# Print call statistics
298print(b2.statistics)
A (simplified) python wrapper for StoreArray.
Definition: PyStoreArray.h:72
nCDCout
number of outer CDC wires
ntpl
ntuple to store background levels
nSVDL3
number of L3 strips (u+v)
nCDCin
number of inner CDC wires
allh
merged list of all histograms
nPXDL2
number of PXD pixels (L2)
CDCITout
integration time of the outer CDC layers [ms]
nPXDL1
number of PXD pixels (L1)
CDCITIn
integration time of the inner CDC layers [ms]
hist
list of digits histograms
hist2
list of occupancy-like histograms
nPXD
number of PXD pixels (L1+L2)