ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
PhysicsAnalysis
PATJobTransforms
scripts
physvalPostProcessing.py
Go to the documentation of this file.
1
#!/usr/bin/env python3
2
3
# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4
5
import
ROOT
6
import
os
7
import
argparse
8
import
logging
9
import
PATJobTransforms.physvalPostProcessingTools
as
physvalPostProcessingTools
10
from
PATJobTransforms.physvalPostProcessingTools
import
(
11
ConfigManager,
12
EfficiencyComputation,
13
ProjectionComputation,
14
RebinningOperation,
15
HistogramAdjustment,
16
HistogramAddition,
17
HistogramBlackList,
18
ResolutionComputation,
19
ROCCurveComputation
20
)
21
22
logging.basicConfig(level=logging.INFO)
23
24
from
AthenaCommon.Utils.unixtools
import
find_datafile
25
26
try
:
27
electron_config = find_datafile(
"PATJobTransforms/physvalPostProcessingElectronConfig.yaml"
)
28
photon_config = find_datafile(
"PATJobTransforms/physvalPostProcessingPhotonConfig.yaml"
)
29
btag_config = find_datafile(
"PATJobTransforms/physvalPostProcessingBTagConfig.yaml"
)
30
except
(ImportError, FileNotFoundError)
as
e:
31
print
(f
"Error: {e}. Attempting fallback paths."
)
32
electron_config = find_datafile(
"../share/physvalPostProcessingElectronConfig.yaml"
)
33
photon_config = find_datafile(
"../share/physvalPostProcessingPhotonConfig.yaml"
)
34
btag_config = find_datafile(
"../share/physvalPostProcessingBTagConfig.yaml"
)
35
except
Exception
as
e:
36
print
(f
"Unexpected error: {e}. Please ensure the configuration files are available at the correct paths."
)
37
raise
38
39
def
create_output_file
(input_file, output_file):
40
try
:
41
ROOT.TFile.Cp(input_file, output_file)
42
output_root = ROOT.TFile.Open(output_file,
"UPDATE"
)
43
if
not
output_root
or
output_root.IsZombie():
44
logging.error(f
"Could not open {output_file}"
)
45
return
None
46
# logging.info(f"Opened {output_file} file for updating.")
47
return
output_root
48
except
Exception
as
e:
49
logging.error(f
"Failed to create output file: {e}"
)
50
return
None
51
52
def
process_domain
(root_file, domain_config, domain):
53
logging.info(f
"For domain: '{domain}'"
)
54
55
for
rebin
in
domain_config.get(
"rebinning"
, []): RebinningOperation.from_yaml(rebin)(root_file)
56
actions = []
57
if
"resolutions"
in
domain_config:
58
for
res
in
domain_config[
"resolutions"
]: actions.append(
lambda
res=res: ResolutionComputation.from_yaml(res)(root_file))
59
if
"projections"
in
domain_config:
60
for
proj
in
domain_config[
"projections"
]: actions.append(
lambda
proj=proj: ProjectionComputation.from_yaml(proj)(root_file))
61
if
"efficiencies"
in
domain_config:
62
for
eff
in
domain_config[
"efficiencies"
]: actions.append(
lambda
eff=eff: EfficiencyComputation.from_yaml(eff)(root_file))
63
if
"adding_histograms"
in
domain_config:
64
for
add
in
domain_config[
"adding_histograms"
]: actions.append(
lambda
add=add: HistogramAddition.from_yaml(add)(root_file))
65
if
"adjustments"
in
domain_config:
66
for
adj
in
domain_config[
"adjustments"
]: actions.append(
lambda
adj=adj: HistogramAdjustment.from_yaml(adj)(root_file))
67
if
"roc_curves"
in
domain_config:
68
for
roc
in
domain_config[
"roc_curves"
]: actions.append(
lambda
roc=roc: ROCCurveComputation.from_yaml(roc)(root_file))
69
for
action
in
actions: action()
70
for
list
in
domain_config.get(
"blacklist"
, []): HistogramBlackList.from_yaml(list)(root_file)
71
72
for
rebin
in
domain_config.get(
"rebinning_later"
, []): RebinningOperation.from_yaml(rebin)(root_file)
73
74
logging.info(f
"Finished post processing for domain: '{domain}'"
)
75
76
def
main
():
77
parser = argparse.ArgumentParser(description=
"NTUPLE PHYSVAL Histogram Post-processing Tool"
)
78
parser.add_argument(
"files"
, nargs=
"*"
, help=
"Input ROOT file and optionally output file name"
)
79
parser.add_argument(
"--domain"
, type=str, help=
"Specific domain to process (e.g., Electron, Photon, BTag)"
)
80
parser.add_argument(
"--crash_on_error"
, action=
"store_true"
, help=
"Crash on first error instead of just warning"
)
81
args = parser.parse_args()
82
83
physvalPostProcessingTools.crash_on_error = args.crash_on_error
84
85
if
len(args.files) == 1:
86
input_file = args.files[0]
87
output_file = os.path.splitext(input_file)[0] +
"_after_post_process.root"
88
elif
len(args.files) == 2:
89
input_file, output_file = args.files
90
else
:
91
logging.error(
"You must provide 1 or 2 positional arguments: <input_file> [output_file]"
)
92
exit(1)
93
94
config_manager = ConfigManager()
95
config_manager.add_configuration(
"Electron"
, electron_config)
96
config_manager.add_configuration(
"Photon"
, photon_config)
97
config_manager.add_configuration(
"BTag"
, btag_config)
98
99
logging.info(f
"Input: {input_file}"
)
100
logging.info(f
"Output: {output_file}"
)
101
102
root_file =
create_output_file
(input_file, output_file)
103
if
not
root_file:
104
exit(1)
105
106
logging.info(
"Post Processing started..."
)
107
if
args.domain:
108
process_domain
(root_file, config_manager.get_config(args.domain), args.domain)
# Processing specified domain
109
else
:
110
for
domain, domain_config
in
config_manager.get_all_configs():
111
process_domain
(root_file, domain_config, domain)
# Processing all domains
112
113
try
:
114
root_file.Close()
115
logging.info(f
"Postprocessing complete. Output saved to: {output_file}"
)
116
except
Exception
as
e:
117
logging.error(f
"Failed to close ROOT file: {e}"
)
118
exit(1)
119
120
if
__name__ ==
"__main__"
:
121
main
()
print
void print(char *figname, TCanvas *c1)
Definition
TRTCalib_StrawStatusPlots.cxx:26
physvalPostProcessing.main
main()
Definition
physvalPostProcessing.py:76
physvalPostProcessing.create_output_file
create_output_file(input_file, output_file)
Definition
physvalPostProcessing.py:39
physvalPostProcessing.process_domain
process_domain(root_file, domain_config, domain)
Definition
physvalPostProcessing.py:52
Generated on
for ATLAS Offline Software by
1.17.0