9 import PATJobTransforms.physvalPostProcessingTools
as physvalPostProcessingTools
10 from PATJobTransforms.physvalPostProcessingTools
import (
12 EfficiencyComputation,
13 ProjectionComputation,
18 ResolutionComputation,
22 logging.basicConfig(level=logging.INFO)
24 from AthenaCommon.Utils.unixtools
import find_datafile
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.")
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}")
48 except Exception
as e:
49 logging.error(f
"Failed to create output file: {e}")
53 logging.info(f
"For domain: '{domain}'")
55 for rebin
in domain_config.get(
"rebinning", []): RebinningOperation.from_yaml(rebin)(root_file)
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)
72 for rebin
in domain_config.get(
"rebinning_later", []): RebinningOperation.from_yaml(rebin)(root_file)
74 logging.info(f
"Finished post processing for domain: '{domain}'")
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()
83 physvalPostProcessingTools.crash_on_error = args.crash_on_error
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
91 logging.error(
"You must provide 1 or 2 positional arguments: <input_file> [output_file]")
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)
99 logging.info(f
"Input: {input_file}")
100 logging.info(f
"Output: {output_file}")
106 logging.info(
"Post Processing started...")
108 process_domain(root_file, config_manager.get_config(args.domain), args.domain)
110 for domain, domain_config
in config_manager.get_all_configs():
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}")
120 if __name__ ==
"__main__":