EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
verify.py
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file verify.py
1 #!/usr/bin/env python
2 
3 from array import array
4 import os
5 
6 import ROOT
7 try:
8  ROOT.PyConfig.IgnoreCommandLineOptions = True
9 except AttributeError:
10  pass
11 ROOT.gSystem.Load('libeicsmear')
12 ROOT.gROOT.SetBatch(True)
13 
14 def parse():
15  """Parse command line arguments and return in an argparse.Namespace."""
16  from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
17  parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
18  parser.add_argument('file', nargs='+', help='input ASCII file')
19  parser.add_argument('-o', '--outdir', default='.',
20  help='output directory')
21  parser.add_argument('-f', '--format', default='pdf', choices=['ps', 'pdf'],
22  help='output file format')
23  parser.add_argument('-n', '--nevents', default=-1, type=int,
24  help='number of events per file')
25  return parser.parse_args()
26 
27 def build(filename, outdir='.', nevents=-1):
28  """Build a ROOT tree from the named text file.
29 
30  Returns the name of the resultant ROOT file.
31 
32  """
33  base, extension = os.path.splitext(filename)
34  ROOT.BuildTree(filename, outdir, nevents)
35  return '.'.join([base, 'root'])
36 
37 def histogram(typename, *args, **kwargs):
38  """Return a histogram of the requested type.
39 
40  args -- normal histogram constructor arguments
41  kwargs -- additional attributes to attach to the histogram
42 
43  e.g. to create a TH1D with a 'cut' attribute:
44 
45  histogram(ROOT.TH1D, 'myhist', '', 10, 0, 10, cut='x>10')
46 
47  """
48  h = typename(*args)
49  attributes = {'select': h.GetName(), 'cut': '', 'log': ''} # Defaults
50  attributes.update(kwargs)
51  for name, value in attributes.iteritems():
52  setattr(h, name, value)
53  h.SetOption(attributes.get('opt', ''))
54  return h
55 
56 def th1d(*args, **kwargs):
57  """Return a TH1D"""
58  return histogram(ROOT.TH1D, *args, **kwargs)
59 
60 def th2d(*args, **kwargs):
61  """Return a TH2D"""
62  return histogram(ROOT.TH2D, *args, **kwargs)
63 
64 def fill_histogram_from_tree(self, tree):
65  """Fill a histogram from a tree.
66 
67  Uses the histogram's 'select' and 'cut' attributes to determine
68  what is plotted.
69 
70  """
71  try:
72  counts = tree.Project(self.GetName(), self.select, self.cut)
73  except:
74  print 'Error filling histogram', self.GetName(),\
75  'from tree, histogram will not be filled'
76 
77 # Add as a new member function to TH1
78 ROOT.TH1.FillTree = fill_histogram_from_tree
79 
80 class Histograms(object):
81  """A collection of basic histograms."""
82 
83  def name(self, string):
84  """Return the string prepended by this object's file basename."""
85  return '_'.join([self.base, string])
86 
87  def __init__(self, rootfile):
88  """Initialise histograms and associate them with a ROOT file."""
89  rootfile.cd()
90  self.file = rootfile
91  self.base, extension = os.path.splitext(file.GetName())
92  self.out = '.'.join([self.base, 'pdf'])
93  name = self.name
94  self.window = ROOT.TCanvas(name('canvas'), '', 1, 1, 800, 800)
95  self.page(open=True)
96  # erhic::EventDis variables
97  self.histograms = [
98  th1d(name('beamlepton'), 'Beam lepton ID', 300, -3000., 3000.,
99  select='BeamLepton().Id().Code()'),
100  th1d(name('beamhadron'), 'Beam hadron ID', 300, -3000., 3000.,
101  select='BeamHadron().Id().Code()'),
102  th1d(name('scattered'), 'Scattered lepton ID', 300, -3000., 3000.,
103  select='ScatteredLepton().Id().Code()'),
104  th1d(name('boson'), 'Exchange boson ID', 300, -3000., 3000.,
105  select='ExchangeBoson().Id().Code()'),
106  th1d(name('nu'), 'nu', 25, 1., 5., select='log10(nu)'),
107  th2d(name('Q2x'), '$Q^{2}$ vs. $x_{Bj}$', 25, -5., 0., 25, -1., 4.,
108  select='log10(QSquared):log10(x)', opt='colz'),
109  th1d(name('xf'), '$x_{F}$', 55, -1.1, 1.1, select='xFeynman',
110  cut='KS==1 && id!=ScatteredLepton().Id().Code()'),
111  th1d(name('z'), '$z$', 60, -0.1, 1.1, select='z',
112  cut='KS==1 && id!=ScatteredLepton().Id().Code()', log='y'),
113  th1d(name('pt'), '$p_{T}$ vs. virtual photon', 60, 0., 3.,
114  select='ptVsGamma', log='y'),
115  th1d(name('ptot'), 'Total final-state momentum', 100, 0., 300.,
116  select='FinalStateMomentum().P()'),
117  th1d(name('ctot'), 'Total final-state charge', 100, -2., 2.,
118  select='FinalStateCharge()'),
119  th2d(name('pthb'), 'Get4VectorInHadronBosonFrame().Pt():ptVsGamma',
120  50, 0., 10., 50, 0., 10.,
121  select='Get4VectorInHadronBosonFrame().Pt():ptVsGamma',
122  opt='colz'),
123  th2d(name('mass'), 'Photon mass$^{2}$ vs. $Q^{2}$',
124  25, -1., 4., 25, -1., 4.,
125  select='log10(-(ExchangeBoson().Get4Vector().M2())):'
126  'log10(QSquared)',
127  opt='colz')
128  ]
129  # x, Q2, W2 and y, for each calculation method
130  for method in ['', 'JB', 'DA']:
131  def var(string):
132  """Insert method into a string."""
133  if '{' in string:
134  return string.format(method)
135  else:
136  return ''.join([string, method])
137  self.histograms += [
138  th1d(name(var('x')), var('$x_{{Bj}}{}$'), 25, -5., 0.,
139  select=var('log10(x{})')),
140  th1d(name(var('Q2')), var('$Q^{{2}}{}$'), 25, -1., 4.,
141  select=var('log10(QSquared)'), log='y'),
142  th1d(name(var('y')), var('$y{}$'), 25, -0.1, 1.1,
143  select=var('y')),
144  th1d(name(var('W2')), var('$W^{{2}}{}$'), 25, 1., 6.,
145  select=var('log10(WSquared)'))
146  ]
147  # erhic::EventMC variables:
148  self.histograms += [
149  th1d(name('number'), 'Event number', 100, 0.,
150  file.EICTree.GetEntries(), select='number'),
151  th1d(name('process'), 'Process', 200, 0., 200., select='process'),
152  th1d(name('nTracks'), 'Number of tracks', 200, 0., 200.,
153  select='nTracks'),
154  th2d(name('tracks'), 'particles.GetEntries() vs. nTracks',
155  200, 0., 200., 200, 0., 200.,
156  select='@particles.GetEntries():nTracks', opt='colz'),
157  th1d(name('Ein'), 'ELeptonInNucl', 25, 0., 12000.,
158  select='ELeptonInNucl'),
159  th1d(name('Eout'), 'ELeptonOutNucl', 25, 0., 12000.,
160  select='ELeptonOutNucl'),
161  th2d(name('hadronic'),
162  'HadronicFinalStateMomentum().M2():WSquared',
163  25, 1., 6., 25, 1., 6.,
164  select='log10(HadronicFinalStateMomentum().M2()):'
165  'log10(WSquared)', opt='colz')
166  ]
167 
168  def page(self, open=False, close=False, log=''):
169  """Print the current contents of the window."""
170  if open:
171  self.window.Print(self.out + '[')
172  elif close:
173  self.window.Print(self.out + ']')
174  else:
175  self.window.SetLogx('x' in log)
176  self.window.SetLogy('y' in log)
177  self.window.SetLogz('z' in log)
178  self.window.Print(self.out)
179 
180  def make(self):
181  """Fill and print all histograms."""
182  self.file.cd()
183  for histogram in self.histograms:
184  histogram.FillTree(self.file.EICTree)
185  self.window.cd()
186  histogram.Draw()
187  self.page(log=histogram.log)
188 
189  def close(self):
190  """Cloes the ROOT file and image file."""
191  self.file.Write()
192  self.page(close=True)
193 
194 
196  """PYHTIA-specific histograms"""
197 
198  def __init__(self, file):
199  super(PythiaHistograms, self).__init__(file)
200  name = self.name
201  self.histograms += [
202  th2d(name('trueX'), '$x_{Bj}$', 25, -5., 0., 25, -5., 0.,
203  select='log10(x):log10(trueX)', opt='colz'),
204  th2d(name('trueQ2'), '$Q^{2}$', 25, -1., 4., 25, -1., 4.,
205  select='log10(QSquared):log10(trueQ2)', opt='colz'),
206  th2d(name('trueY'), '$y$', 25, -0.1, 1.1, 25, -0.1, 1.1,
207  select='y:trueY', opt='colz'),
208  th2d(name('trueW2'), '$W^{2}$', 25, 1., 6., 25, 1., 6.,
209  select='log10(WSquared):log10(trueW2)', opt='colz')
210  ]
211 
212 
214  """DJANGOH-specific histograms"""
215 
216  def __init__(self, file):
217  super(DjangohHistograms, self).__init__(file)
218  name = self.name
219  self.histograms += [
220  th2d(name('dtrueX'), '$x_{Bj}$', 25, -5., 0., 25, -5., 0.,
221  select='log10(x):log10(dtrueX)', opt='colz'),
222  th2d(name('dtrueQ2'), '$Q^{2}$', 25, -1., 4., 25, -1., 4.,
223  select='log10(QSquared):log10(dtrueQ2)', opt='colz'),
224  th2d(name('dtrueY'), '$y$', 25, -0.1, 1.1, 25, -0.1, 1.1,
225  select='y:dtrueY', opt='colz'),
226  th2d(name('dtrueW2'), '$W^{2}$', 25, 1., 6., 25, 1., 6.,
227  select='log10(WSquared):log10(dtrueW2)', opt='colz')
228  ]
229 
230 
231 # Define Histograms to make for each generator
232 HISTOGRAMS = {'pythia': PythiaHistograms,
233  'lepto': Histograms,
234  'milou': Histograms,
235  'djangoh': DjangohHistograms,
236  'pepsi': Histograms,
237  'gmc_trans': Histograms}
238 
239 def event_type(file):
240  """Return the event type for a ROOT file.
241 
242  e.g. 'pythia', 'lepto'.
243 
244  """
245  file.EICTree.GetEntry(0)
246  return file.EICTree.event.ClassName().lstrip('erhic::Event').lower()
247 
248 if __name__ == '__main__':
249  options = parse()
250  # Build ROOT files
251  names = [build(name, options.outdir, options.nevents)
252  for name in options.file]
253  # Open ROOT files for updating with histograms
254  root_files = [ROOT.TFile(name, 'update') for name in names]
255  # Initialise histograms
256  histograms = [HISTOGRAMS[event_type(file)](file) for file in root_files]
257  # Fill, draw and write histograms
258  for histogram in histograms:
259  histogram.make()
260  histogram.close()