ATLAS Offline Software
Loading...
Searching...
No Matches
LarFCalSamplingFraction_analysis.py
Go to the documentation of this file.
1#!/usr/bin/env python
2
3# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4
5"""
6Calculate FCal Sampling Fractions
7=================================
8
9Calculate the FCal sampling fractions from Geant4 simulation.
10"""
11
12
13
14import argparse
15import glob
16import math
17import sys
18
19import ROOT as root
20
21# To stop ROOT from hijacking '--help'
22root.PyConfig.IgnoreCommandLineOptions = True
23
24
25def _docstring(docstring):
26 """Return summary of docstring
27 """
28 return docstring.split('\n')[4] if docstring else ""
29
30
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
124def 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
131def 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
167if __name__ == '__main__':
168 sys.exit(main())
void print(char *figname, TCanvas *c1)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41