4 Suite of standard QA plots for EIC trees to check they are filled properly.
5 It's fairly slow, but you don't need to run many events to check that all
6 values are being filled properly.
10 from collections
import namedtuple
21 from binning
import bin_log10
27 ROOT.PyConfig.IgnoreCommandLineOptions =
True
30 ROOT.SetSignalPolicy(ROOT.kSignalFast)
33 ROOT.gROOT.SetBatch(
True)
35 class LogAxis(namedtuple(
'LogAxis',
'x y z')):
37 Utility for setting ROOT pad logarithmic axes.
41 Apply the log axis settings to a ROOT pad.
43 pad.SetLogx(self.x != 0)
44 pad.SetLogy(self.y != 0)
45 pad.SetLogz(self.z != 0)
50 if self.y
and hist.GetDimension() > 1:
52 if self.z
and hist.GetDimension() > 2:
58 Simple wrapper around ROOT histogram adding some functionality.
62 Initialise with a histogram and a LogAxis giving whether
63 each axis (x, y, z) should be log10 (1) or not (0).
69 self.h.SetOption(option)
70 self.log.rebin(self.
h)
74 Draw the histogram to a ROOT pad.
85 A collection of standard histograms for event-wise properties.
90 ROOT.TH1D(
'process',
'Event process number', 200, 0., 200.),
93 ROOT.TH1D(
'tracks',
'Number of tracks per event', 100, 0., 200),
104 ROOT.TH2D(
'Q2x',
'Q^{2} vs. x', 30, 1.e-5, 10., 16, 0.1, 1000.),
107 ROOT.TH1D(
'y',
'y', 48, -0.1, 1.1),
LogAxis(0, 1, 0),
'')
109 ROOT.TH1D(
'W2',
'W^{2} (GeV^{2})', 60, 0.1, 1.e5),
112 ROOT.TH1D(
'nu',
'#nu (GeV)', 60, 0.1, 1.e5),
LogAxis(1, 0, 0),
'')
115 for i
in [
'y',
'Q2x',
'W2']:
120 self.
hists[name].h.SetTitle(orig.h.GetTitle() +
121 ' (Jacquet-Blondel)')
125 self.
hists[name].h.SetTitle(orig.h.GetTitle() +
130 Print all histograms to an output PostScript file.
134 for j
in sorted(self.
hists):
142 self.
hists[
'process'].h.Fill(event.GetProcess())
143 self.
hists[
'tracks'].h.Fill(event.GetNTracks())
146 self.
hists[
'Q2x'].h.Fill(event.GetX(), event.GetQ2())
147 self.
hists[
'y'].h.Fill(event.GetY())
148 self.
hists[
'W2'].h.Fill(event.GetW2())
149 self.
hists[
'nu'].h.Fill(event.GetNu())
150 self.
hists[
'Q2xjb'].h.Fill(event.GetXJacquetBlondel(),
151 event.GetQ2JacquetBlondel())
152 self.
hists[
'yjb'].h.Fill(event.GetYJacquetBlondel())
153 self.
hists[
'W2jb'].h.Fill(event.GetW2JacquetBlondel())
154 self.
hists[
'Q2xda'].h.Fill(event.GetXDoubleAngle(),
155 event.GetQ2DoubleAngle())
156 self.
hists[
'yda'].h.Fill(event.GetYDoubleAngle())
157 self.
hists[
'W2da'].h.Fill(event.GetW2DoubleAngle())
162 A collection of standard histograms for track-wise properties.
163 Optionally specify a list of PDG codes to accept.
164 Only tracks with one of those codes will be used when filling histograms.
169 ROOT.TH1D(
'KS',
'Track status code', 110, -10., 100.),
173 ROOT.TH1D(
'orig',
'Track parent index', 210, -10., 200.),
177 ROOT.TH2D(
'child',
'Child track indices;first;last',
178 210, -10., 200., 210, -10., 200.),
182 ROOT.TH2D(
'pypx',
'p_{y} vs. p_{x} (GeV/c);p_{x};p_{y}',
183 60, -3., 3., 60, -3., 3.),
187 ROOT.TH2D(
'ptpz',
'p_{T} vs. p_{z} (GeV/c);p_{z};p_{T}',
188 60, -40., 260., 60, -1., 11.),
192 ROOT.TH2D(
'em',
'Energy vs. mass (final-state only);m;E',
193 60, -1., 11., 60, -40., 260.),
197 ROOT.TH2D(
'vxy',
'Track vertex y vs. x',
198 51, -100., 100., 51, -100., 100.),
202 ROOT.TH2D(
'zp',
'Energy fraction vs. p (final-state only);p;z',
203 60, -40., 260., 48, -0.1, 1.1),
207 ROOT.TH2D(
'thetaphi',
'#theta vs. #phi (rad)',
208 35, -0.4, 6.6, 40, -0.5, 3.5),
212 ROOT.TH2D(
'etay',
'#eta vs. rapidity',
213 40, -20., 20., 40, -20., 20.),
217 ROOT.TH2D(
'gamma',
'p_{T} vs. #theta in #gamma-p frame',
218 40, -0.5, 3.5, 35, -1., 6.),
225 ROOT.TH1D(
'xf',
'Feynman x (final-state only)', 110, -1.1, 1.1),
230 Print all histograms to an output PostScript file.
243 Fill all histograms for a list of tracks
249 Particle = ROOT.erhic.ParticleMC
250 status = Particle.GetStatus
251 parent = Particle.GetParentIndex
252 child1 = Particle.GetChild1Index
253 childN = Particle.GetChildNIndex
258 vert = Particle.GetVertex
259 phi = Particle.GetPhi
260 theta = Particle.GetTheta
261 rap = Particle.GetRapidity
262 eta = Particle.GetEta
263 thetag = Particle.GetThetaVsGamma
264 ptg = Particle.GetPtVsGamma
269 xf = Particle.GetXFeynman
272 horig = self.orig.h.Fill
273 hchild = self.child.h.Fill
274 hpypx = self.pypx.h.Fill
275 hptpz = self.ptpz.h.Fill
276 hvxy = self.vxy.h.Fill
277 hthetaphi = self.thetaphi.h.Fill
278 hetay = self.etay.h.Fill
279 hgamma = self.gamma.h.Fill
284 beams = [2212, 2112, 11]
290 if track.GetStatus() != 1:
294 hchild(child1(track), childN(track))
295 hpypx(px(track), py(track))
296 hptpz(pz(track), pt(track))
298 hvxy(vertex.x(), vertex.y())
300 hetay(rap(track),
eta(track))
301 hgamma(thetag(track), ptg(track))
304 if track.GetPdgCode().Code()
not in beams:
305 hem(
m(track),
e(track))
306 hzp(
p(track),
z(track))
311 print 'Event', str(n).rjust(len(str(max))),
'of', max
317 outfile = ROOT.TFile(outname.replace(
'.ps',
'.root'),
'recreate')
320 nevents =
min(maxevents, tree.GetEntries())
321 for i
in xrange(0, nevents):
324 tracks = [track
for track
in tree.event.GetTracks()]
326 if (i + 1) % (nevents / 10) == 0:
328 window = ROOT.TCanvas()
329 window.Print(
''.join([outname,
'[']))
330 h.output(window, outname)
331 t.output(window, outname)
332 window.Print(
''.join([outname,
']']))
335 if __name__ ==
'__main__':
337 parser = argparse.ArgumentParser()
338 parser.add_argument(
'infile', help=
'Input ROOT file')
339 parser.add_argument(
'outfile', help=
'Output PostScript file')
340 parser.add_argument(
'--nevents', type=int, default=1000000000, help=
'Maximum number of events')
341 args = parser.parse_args()
342 file = ROOT.TFile(args.infile,
'read')
343 execute(file.EICTree, args.outfile, args.nevents)