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