ATLAS Offline Software
LarFCalSamplingFraction_analysis.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4 
5 """
6 Calculate FCal Sampling Fractions
7 =================================
8 
9 Calculate the FCal sampling fractions from Geant4 simulation.
10 """
11 
12 
13 
14 import argparse
15 import glob
16 import math
17 import sys
18 
19 import ROOT as root
20 
21 # To stop ROOT from hijacking '--help'
22 root.PyConfig.IgnoreCommandLineOptions = True
23 
24 
25 def _docstring(docstring):
26  """Return summary of docstring
27  """
28  return docstring.split('\n')[4] if docstring else ""
29 
30 
31 def parse_args():
32  """Parse command-line arguments
33  """
34  parser = argparse.ArgumentParser(description=_docstring(__doc__))
35  parser.add_argument("--version", action="version", version="%(prog)s 0.1")
36  parser.add_argument("-v", "--verbose", action="count", default=0,
37  help="print verbose messages; multiple -v result in more verbose messages")
38  parser.add_argument("infile", default="LArFCalSamplingFraction.aan.root",
39  help="Path to input file; wildcards are supported (default: %(default)s)")
40  parser.add_argument("-m", "--module", choices=["FCal1", "FCal2", "FCal3"],
41  help="Calculate the sampling fraction for this FCal module only; "
42  "if unspecified, it will try to parse the module from the file name")
43  parser.add_argument("-o", "--outfile", default="out.txt",
44  help="Path to output file where sampling fraction results are written "
45  "(default: %(default)s)")
46 
47  args = parser.parse_args()
48 
49  return args
50 
51 
53  """Read ntuple from the Geant4 simulation and calculate FCal sampling
54  fractions.
55 
56  Returns (E_init, samp_frac, samp_frac_err)
57  """
58  tree_name = "tree_AS"
59  print("Reading tree '{}' from file '{}'...".format(tree_name, args.infile))
60 
61  aan_chain = root.TChain(tree_name)
62  aan_chain.Add(args.infile)
63 
64  n_event = aan_chain.GetEntries()
65 
66  # Get initial electron energy [GeV]
67  for event in aan_chain:
68  E_init = round(event.E, 2) / 1000
69  break
70 
71  samp_frac = 0
72  samp_frac_sq = 0
73 
74  min_eta=1000.0;
75  max_eta=0.0;
76 
77  if args.verbose:
78  print("Event Active E [MeV] Total E [MeV]")
79 
80  # Loop over events and sum energy values
81  for event in aan_chain:
82  if args.module.lower() == "fcal1":
83  totalE = event.Calib_FCal1Active + event.Calib_FCal1Inactive
84  activeE = event.FCal1_E
85  elif args.module.lower() == "fcal2":
86  totalE = event.Calib_FCal2Active + event.Calib_FCal2Inactive
87  activeE = event.FCal2_E
88  elif args.module.lower() == "fcal3":
89  totalE = event.Calib_FCal3Active + event.Calib_FCal3Inactive
90  activeE = event.FCal3_E
91 
92  samp_frac += activeE / totalE
93  samp_frac_sq += (activeE / totalE)**2
94 
95  min_eta=min(min_eta,event.Vertex_Eta)
96  max_eta=max(max_eta,event.Vertex_Eta)
97 
98  if args.verbose:
99  print("{:<6} {:<15g} {:<15g}".format(event.Event, activeE, totalE))
100 
101  if args.verbose:
102  print("")
103 
104  # Mean sampling fractions
105  samp_frac /= n_event
106  samp_frac_sq /= n_event
107 
108  # Sampling fraction error = sqrt(<x^2> - <x>^2) / sqrt(N)
109  samp_frac_err = math.sqrt(samp_frac_sq - samp_frac**2) / math.sqrt(n_event)
110 
111  print("{} sampling fraction (E = {:g} GeV): {:g} +/- {:g}".format(args.module, E_init, samp_frac, samp_frac_err))
112 
113 
114  outfile=root.TFile.Open("SF_LAr.root","UPDATE")
115  func=root.TF1("SF_{}_eta_{:4.2f}_{:4.2f}".format(args.module,min_eta,max_eta),"pol0",min_eta,max_eta)
116  func.SetParameter(0,samp_frac);
117  func.SetParError(0,samp_frac_err);
118  func.Write()
119  outfile.Close()
120 
121  return E_init, samp_frac, samp_frac_err
122 
123 
124 def write_results(results, args):
125  with open(args.outfile, "w") as outfile:
126  outfile.write("[{}]\n".format(args.module))
127 
128  for key in sorted(results.keys()):
129  outfile.write("{:g} GeV: {} +/- {}\n".format(key, results[key][0], results[key][1]))
130 
131 def main():
132  try:
133  args = parse_args()
134 
135  if args.module is None:
136  if "fcal1" in args.infile.lower():
137  args.module = "fcal1"
138  elif "fcal2" in args.infile.lower():
139  args.module = "fcal2"
140  elif "fcal3" in args.infile.lower():
141  args.module = "fcal3"
142  else:
143  raise Exception("unknown FCal module")
144 
145  infiles = glob.glob(args.infile)
146  infiles.sort()
147 
148  results = {}
149 
150  for infile in infiles:
151  args.infile = infile
152  E_init, samp_frac, samp_frac_err = calculate_samp_frac(args)
153 
154  results[E_init] = (samp_frac, samp_frac_err)
155 
156  print("Writing results to '{}'".format(args.outfile))
157  write_results(results, args)
158 
159  except KeyboardInterrupt:
160  return 1
161 
162  except Exception as err:
163  print("error: {}".format(err))
164  return 1
165 
166 
167 if __name__ == '__main__':
168  sys.exit(main())
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename R::value_type > sorted(const R &r, PROJ proj={})
Helper function to create a sorted vector from an unsorted range.
vtune_athena.format
format
Definition: vtune_athena.py:14
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
LarFCalSamplingFraction_analysis.calculate_samp_frac
def calculate_samp_frac(args)
Definition: LarFCalSamplingFraction_analysis.py:52
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
MuonGM::round
float round(const float toRound, const unsigned int decimals)
Definition: Mdt.cxx:27
LarFCalSamplingFraction_analysis.main
def main()
Definition: LarFCalSamplingFraction_analysis.py:131
LarFCalSamplingFraction_analysis.parse_args
def parse_args()
Definition: LarFCalSamplingFraction_analysis.py:31
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:26
LarFCalSamplingFraction_analysis._docstring
def _docstring(docstring)
Definition: LarFCalSamplingFraction_analysis.py:25
LarFCalSamplingFraction_analysis.write_results
def write_results(results, args)
Definition: LarFCalSamplingFraction_analysis.py:124
Trk::open
@ open
Definition: BinningType.h:40