80 parser = argparse.ArgumentParser(description="NTUPLE PHYSVAL Histogram Post-processing Tool")
81 parser.add_argument("files", nargs="*", help="Input ROOT file and optionally output file name")
82 parser.add_argument("--domain", type=str, help="Specific domain to process (e.g., Electron, Photon, BTag)")
83 parser.add_argument("--crash_on_error", action="store_true", help="Crash on first error instead of just warning")
84 args = parser.parse_args()
85
86 physvalPostProcessingTools.crash_on_error = args.crash_on_error
87
88 if len(args.files) == 1:
89 input_file = args.files[0]
90 output_file = os.path.splitext(input_file)[0] + "_after_post_process.root"
91 elif len(args.files) == 2:
92 input_file, output_file = args.files
93 else:
94 logging.error("You must provide 1 or 2 positional arguments: <input_file> [output_file]")
95 exit(1)
96
97 config_manager = ConfigManager()
98 config_manager.add_configuration("Electron", electron_config)
99 config_manager.add_configuration("Photon", photon_config)
100 config_manager.add_configuration("BTag", btag_config)
101
102 logging.info(f"Input: {input_file}")
103 logging.info(f"Output: {output_file}")
104
105 root_file = create_output_file(input_file, output_file)
106 if not root_file:
107 exit(1)
108
109 logging.info("Post Processing started...")
110 if args.domain:
111 process_domain(root_file, config_manager.get_config(args.domain), args.domain)
112 else:
113 for domain, domain_config in config_manager.get_all_configs():
114 process_domain(root_file, domain_config, domain)
115
116 try:
117 root_file.Close()
118 logging.info(f"Postprocessing complete. Output saved to: {output_file}")
119 except Exception as e:
120 logging.error(f"Failed to close ROOT file: {e}")
121 exit(1)
122