23 from ROOT
import Belle2
24 from ROOT
import TH1F, TH2F
25 from ROOT
import AddressOf, gROOT
26 from ROOT
import TLorentzVector
34 file_num = sys.argv[1]
37 gROOT.ProcessLine(
'struct TreeStruct {\
38 int run; /* run number */ \
39 int itrk; /* track counter */ \
40 float offset; /* current bunch offset */ \
41 int usedTrk; /* number of tracks used for bunch reconstruction */ \
42 int slot; /* slot ID */ \
43 float p; /* extHit momentum */ \
44 float cth; /* extHit local cos(theta) (global must be pretty much the same) */ \
45 float phi; /* extHit local phi */ \
46 float z; /* extHit local z */ \
47 float x; /* extHit local x */ \
48 float tof; /* extHit time-of-flight */ \
49 int charge; /* particle charge */ \
50 float poca_x; /* POCA x */ \
51 float poca_y; /* POCA y */ \
52 float poca_z; /* POCA z */ \
53 int hitsCDC; /* number of CDC hits */ \
54 float dEcms; /* delta Ecms for muon */ \
55 float rec_t0; /* t0 of this track determined with bunch finder */ \
56 int valid_t0; /* reconstruction status of t0 */ \
57 int nfot; /* number of photons */ \
58 int channel[1000]; /* channel */ \
59 int pixel[1000] ; /* pixel ID */ \
60 float time[1000]; /* photon time */ \
61 float timeErr[1000]; /* photon time uncertainty */ \
62 int pulseHeight[1000]; /* photon pulse height */ \
63 float pulseWidth[1000]; /* photon pulse width */ \
64 int sample[1000]; /* sample number modulo 256 */ \
65 int status[1000]; /* calibration status bits */ \
66 float t0[1000]; /* leading PDF peak: position */ \
67 float wid0[1000]; /* leading PDF peak: width w/o TTS */ \
68 float t1[1000]; /* next to leading PDF peak: position */ \
69 float t_pdf[1000]; /* associated pdf peak time */ \
70 int type[1000]; /* 0 bkg, 1 direct, 2 reflected */ \
71 int nx[1000]; /* total number of reflections in x */ \
72 int ny[1000]; /* total number of reflections in y */ \
73 int nxm[1000]; /* number of reflections in x before mirror */ \
74 int nym[1000]; /* number of reflections in y before mirror */ \
75 int nxe[1000]; /* number of reflections in x in prism */ \
76 int nye[1000]; /* number of reflections in y in prism */ \
77 int nys[1000]; /* number of reflections on slanted surface of prism */ \
78 float xd[1000]; /* unfolded x coordinate of a pixel */ \
79 float yd[1000]; /* unfolded y coordinate of a pixel */ \
80 float xm[1000]; /* unfolded x coordinate of a reconstructed point on mirror */ \
81 float kx[1000]; /* reconstructed photon direction in x at emission */ \
82 float ky[1000]; /* reconstructed photon direction in y at emission */ \
83 float alpha[1000]; /* impact angle on photo-cathode [degrees] */ \
86 int_arrays = [
'channel',
'pixel',
'pulseHeight',
'sample',
'status',
'type',
'nx',
'ny',
87 'nxm',
'nym',
'nxe',
'nye',
'nys']
88 float_arrays = [
'time',
'timeErr',
'pulseWidth',
't0',
'wid0',
't1',
't_pdf',
'alpha',
89 'xd',
'yd',
'xm',
'kx',
'ky']
91 from ROOT
import TreeStruct
95 ''' Makes a flat ntuple '''
101 ''' initialize: open root file, construct ntuple '''
104 expNo = evtMetaData.obj().getExperiment()
105 runNo = evtMetaData.obj().
getRun()
106 exp_run =
'-e' +
'{:0=4d}'.format(expNo) +
'-r' +
'{:0=5d}'.format(runNo)
108 outName =
'out_data/timeResoNtuple' + exp_run +
'.root'
110 outName =
'out_mc/timeResoNtuple' + exp_run +
'-' + file_num +
'.root'
113 self.
filefile = ROOT.TFile(outName,
'recreate')
116 self.
bunchOffsetbunchOffset = TH1F(
"bunchOffset",
"bunch offset", 100, -1.0, 1.0)
117 self.
bunchOffsetbunchOffset.SetXTitle(
"bunch offset [ns]")
119 self.
h_cth_vs_ph_cth_vs_p = TH2F(
"cth_vs_p",
"local cos #theta vs. p", 100, 0.0, 10.0,
121 self.
h_cth_vs_ph_cth_vs_p.SetXTitle(
"p [GeV/c]")
122 self.
h_cth_vs_ph_cth_vs_p.SetYTitle(
"cos #theta")
124 self.
h_momentumh_momentum = TH1F(
"momentum",
"momentum", 100, 0.0, 10.0)
125 self.
h_momentumh_momentum.SetXTitle(
"p [GeV/c]")
127 self.
h_cthh_cth = TH1F(
"cos_theta",
"local cos #theta", 100, -1.0, 1.0)
128 self.
h_cthh_cth.SetXTitle(
"cos #theta")
130 self.
h_phih_phi = TH1F(
"local_phi",
"local phi", 100, -math.pi, math.pi)
131 self.
h_phih_phi.SetXTitle(
"local #phi")
133 self.
h_zh_z = TH1F(
"local_z",
"local z", 100, -140.0, 140.0)
134 self.
h_zh_z.SetXTitle(
"local z [cm]")
136 self.
h_xh_x = TH1F(
"local_x",
"local x", 100, -23.0, 23.0)
137 self.
h_xh_x.SetXTitle(
"local x [cm]")
139 self.
h_chargeh_charge = TH1F(
"charge",
"charge", 3, -1.5, 1.5)
140 self.
h_chargeh_charge.SetXTitle(
"charge")
142 self.
h_poca_xyh_poca_xy = TH2F(
"poca_xy",
"POCA distribution in x-y", 100, -1.0, 1.0,
144 self.
h_poca_xyh_poca_xy.SetXTitle(
"x [cm]")
145 self.
h_poca_xyh_poca_xy.SetYTitle(
"y [cm]")
147 self.
h_poca_zh_poca_z = TH1F(
"poca_z",
"POCA distribution in z", 100, -2.0, 2.0)
148 self.
h_poca_zh_poca_z.SetXTitle(
"z [cm]")
150 self.
h_hitsCDCh_hitsCDC = TH1F(
"cdc_hits",
"CDC hits", 100, 0.0, 100.0)
151 self.
h_hitsCDCh_hitsCDC.SetXTitle(
"number of CDC hits")
153 self.
h_Ecmsh_Ecms = TH1F(
"Ecms",
"c.m.s. energy of muon", 300, 4.5, 6.0)
154 self.
h_Ecmsh_Ecms.SetXTitle(
"E_{cm} [GeV/c]")
157 self.
treetree = ROOT.TTree(
'tree',
'time resolution')
160 self.
datadata.itrk = 0
162 for key
in TreeStruct.__dict__.keys():
165 if isinstance(self.
datadata.__getattribute__(key), int):
167 if key
in int_arrays:
168 formstring =
'[nfot]/I'
169 elif key
in float_arrays:
170 formstring =
'[nfot]/F'
171 self.
treetree.Branch(key, AddressOf(self.
datadata, key), key + formstring)
174 ''' sort PDF peaks according to their positions '''
176 py_list = [x
for x
in unsortedPeaks]
177 return sorted(py_list, key=
lambda x: (x.mean))
180 ''' make histogram of PDF peak positions for the first 20 tracks '''
183 if self.
nhistonhisto > 20:
185 h = TH2F(
'pdf' + str(self.
nhistonhisto),
'muon PDF, itrk = ' + str(self.
datadata.itrk),
186 512, 0.0, 512.0, 1000, 0.0, 75.0)
187 h.SetXTitle(
'pixelID - 1')
188 h.SetYTitle(
'peak positions [ns]')
196 ''' returns c.m.s. energy of a particle '''
197 mom = tfit.getMomentum()
198 lorentzLab = TLorentzVector()
199 mass = chargedStable.getMass()
200 lorentzLab.SetXYZM(mom.X(), mom.Y(), mom.Z(), mass)
202 lorentzCms = T.labToCms(lorentzLab)
203 return [lorentzCms.Energy(), T.getCMSEnergy() / 2]
206 ''' returns true if track fulfills selection criteria '''
208 if abs(self.
datadata.dEcms) > 0.1:
210 if abs(self.
datadata.poca_x) > 0.2:
212 if abs(self.
datadata.poca_y) > 0.2:
214 if abs(self.
datadata.poca_z) > 0.5:
219 ''' returns timo-of-flight of extrapolated track '''
221 extHits = track.getRelationsWith(
'ExtHits')
224 for extHit
in extHits:
225 if abs(extHit.getPdgCode()) != pdg:
227 if extHit.getDetectorID() != Belle2.Const.TOP:
229 if extHit.getCopyID() != slot:
231 if extHit.getStatus() == Belle2.EXT_ENTER:
233 elif extHit.getStatus() == Belle2.EXT_EXIT:
236 return (extEnter.getTOF() + extExit.getTOF()) / 2
240 ''' event processing '''
244 b2.B2ERROR(
'no TOPRecBunch')
246 if not recBunch.isReconstructed():
248 self.
bunchOffsetbunchOffset.Fill(recBunch.getCurrentOffset())
251 self.
datadata.run = evtMetaData.getRun()
252 self.
datadata.offset = recBunch.getCurrentOffset()
253 self.
datadata.usedTrk = recBunch.getUsedTracks()
256 pdfs = track.getRelated(
'TOPPDFCollections')
259 self.
datadata.slot = pdfs.getModuleID()
260 momentum = pdfs.getAssociatedLocalMomentum()
261 position = pdfs.getAssociatedLocalHit()
262 self.
datadata.p = momentum.Mag()
263 self.
datadata.cth = momentum.CosTheta()
264 self.
datadata.phi = momentum.Phi()
265 self.
datadata.z = position.Z()
266 self.
datadata.x = position.X()
267 self.
datadata.tof = self.
getTOFgetTOF(track, 13, self.
datadata.slot)
269 tfit = track.getTrackFitResultWithClosestMass(Belle2.Const.muon)
270 except BaseException:
271 b2.B2ERROR(
"No trackFitResult available")
273 self.
datadata.charge = tfit.getChargeSign()
274 pocaPosition = tfit.getPosition()
275 self.
datadata.poca_x = pocaPosition.X()
276 self.
datadata.poca_y = pocaPosition.Y()
277 self.
datadata.poca_z = pocaPosition.Z()
278 self.
datadata.hitsCDC = tfit.getHitPatternCDC().getNHits()
279 Ecms = self.
getEcmsgetEcms(tfit, Belle2.Const.muon)
280 self.
datadata.dEcms = Ecms[0] - Ecms[1]
284 topll = track.getRelated(
'TOPLikelihoods')
285 extHit = topll.getRelated(
'ExtHits')
286 timeZero = extHit.getRelated(
'TOPTimeZeros')
287 self.
datadata.rec_t0 = timeZero.getTime()
288 self.
datadata.valid_t0 = timeZero.isValid()
289 except BaseException:
290 self.
datadata.rec_t0 = 0
291 self.
datadata.valid_t0 = 0
297 self.
h_zh_z.Fill(self.
datadata.z)
298 self.
h_xh_x.Fill(self.
datadata.x)
303 self.
h_Ecmsh_Ecms.Fill(Ecms[0])
305 pdf = pdfs.getHypothesisPDF(13)
306 except BaseException:
307 b2.B2ERROR(
"No PDF available for PDG = 13")
309 self.
datadata.itrk += 1
311 x0 = position.X() - momentum.X() / momentum.Y() * position.Y()
312 z0 = position.Z() - momentum.Z() / momentum.Y() * position.Y()
313 self.
datadata.nfot = 0
315 if digit.getModuleID() == self.
datadata.slot
and digit.getHitQuality() == 1:
316 k = self.
datadata.nfot
319 self.
datadata.nfot += 1
320 self.
datadata.channel[k] = digit.getChannel()
321 self.
datadata.pixel[k] = digit.getPixelID()
322 self.
datadata.time[k] = digit.getTime()
323 self.
datadata.timeErr[k] = digit.getTimeError()
324 self.
datadata.pulseHeight[k] = digit.getPulseHeight()
325 self.
datadata.pulseWidth[k] = digit.getPulseWidth()
326 self.
datadata.sample[k] = digit.getModulo256Sample()
327 self.
datadata.status[k] = digit.getStatus()
328 peaks = pdf[digit.getPixelID() - 1]
330 self.
datadata.t0[k] = 0
331 self.
datadata.wid0[k] = 0
332 self.
datadata.t1[k] = 0
334 sorted_peaks = self.
sortPeakssortPeaks(peaks)
335 self.
datadata.t0[k] = sorted_peaks[0].mean
336 self.
datadata.wid0[k] = sorted_peaks[0].width
337 self.
datadata.t1[k] = self.
datadata.t0[k] + 100
339 self.
datadata.t1[k] = sorted_peaks[1].mean
340 self.
datadata.t_pdf[k] = 0
341 self.
datadata.type[k] = 0
342 self.
datadata.nx[k] = 0
343 self.
datadata.ny[k] = 0
344 self.
datadata.nxm[k] = 0
345 self.
datadata.nym[k] = 0
346 self.
datadata.nxe[k] = 0
347 self.
datadata.nye[k] = 0
348 self.
datadata.nys[k] = 0
349 self.
datadata.xd[k] = 0
350 self.
datadata.yd[k] = 0
351 self.
datadata.xm[k] = 0
352 self.
datadata.kx[k] = 0
353 self.
datadata.ky[k] = 0
354 self.
datadata.alpha[k] = 0
355 assocPDF = digit.getRelated(
'TOPAssociatedPDFs')
357 pik = assocPDF.getSinglePeak()
359 self.
datadata.t_pdf[k] = pik.position
360 self.
datadata.type[k] = pik.type
361 self.
datadata.nx[k] = pik.nx
362 self.
datadata.ny[k] = pik.ny
363 self.
datadata.nxm[k] = pik.nxm
364 self.
datadata.nym[k] = pik.nym
365 self.
datadata.nxe[k] = pik.nxe
366 self.
datadata.nye[k] = pik.nye
368 self.
datadata.nys[k] = int(pik.nye / 2)
370 self.
datadata.nys[k] = int((pik.nye + 1) / 2)
371 self.
datadata.xd[k] = pik.xd
372 self.
datadata.yd[k] = pik.yd
374 self.
datadata.xm[k] = x0 + pik.kxe / pik.kze * (130.0 - z0)
375 self.
datadata.kx[k] = pik.kxe
376 self.
datadata.ky[k] = pik.kye
377 self.
datadata.alpha[k] = math.degrees(math.acos(abs(pik.kzd)))
382 ''' terminate: close root file '''
385 self.
filefile.Write()
386 self.
filefile.Close()
390 main = b2.create_path()
393 main.add_module(
'RootInput')
396 main.add_module(
'TOPGeometryParInitializer')
399 main.add_module(
'TOPChannelMasker')
402 main.add_module(
'TOPPDFDebugger', pdgCodes=[13])
408 progress = b2.register_module(
'Progress')
409 main.add_module(progress)
a (simplified) python wrapper for StoreArray.
a (simplified) python wrapper for StoreObjPtr.
def sortPeaks(self, unsortedPeaks)
h_cth
histogram of cos(theta)
int nhisto
histogram counter
h_cth_vs_p
histogram cos(theta) vs, momentum
h_phi
histogram of local phi
h_charge
histogram of charge
h_hitsCDC
histogram of number of hits in CDC
def pdfHistogram(self, pdf)
h_poca_xy
histogram of POCA x-y
def getEcms(self, tfit, chargedStable)
def getTOF(self, track, pdg, slot)
h_poca_z
histogram of POCA z
h_momentum
histogram of momentum
bunchOffset
histogram of bunch offset
static ExpRun getRun(map< ExpRun, pair< double, double >> runs, double t)
Get exp number + run number from time.