16 derivedGroup = self.parser.add_argument_group(
'EventLoop specific arguments')
17 derivedGroup.add_argument(
'--direct-driver', dest=
'direct_driver',
18 action=
'store_true', help=
'Run the job with the direct driver')
19 derivedGroup.add_argument(
'--work-dir', dest=
'work_dir', nargs=
'?', const=
'workDir', default=
None,
20 help=
'The work directory for the EL job. defaults to "workDir".')
21 derivedGroup.add_argument(
'--merge-output-files', dest=
'merge_output_files', action=
'store_true', help=
'Merge the output histogram and n-tuple files into a single file.')
22 derivedGroup.add_argument(
'--dump-full-config', dest=
'dump_full_config', action=
'store_true', help=
'Save the full CP configuration log to a json file. This can be useful for debugging purposes.')
24 expertGroup = self.parser.add_argument_group(
'Experts arguments')
25 expertGroup.add_argument(
'--run-perf-stat', dest=
'run_perf_stat', action=
'store_true', help=
'Run xAOD::PerfStats to get input branch access data. This is mostly useful for AMG experts wanting to understand branch access patterns.')
26 expertGroup.add_argument(
'--algorithm-timers', dest=
'algorithm_timers', action=
'store_true', help=
'Enable algorithm timers. This is mostly useful for AMG experts wanting to understand tool performance.')
27 expertGroup.add_argument(
'--algorithm-memory-monitoring', dest=
'algorithm_memory_monitoring', action=
'store_true', help=
'Enable algorithm memory monitoring. This is mostly useful for AMG experts wanting to understand tool memory usage. Note that this is imperfect and may in cases assign memory to the wrong algorithm.')
58 from AnalysisAlgorithmsConfig.SaveConfigUtils
import save_algs_from_sequence_ELjob, combine_tools_and_algorithms_ELjob
60 with(open(
"_alg_sequence.json",
'w', encoding=
'utf-8'))
as seq_out_file:
63 save_algs_from_sequence_ELjob(self.
algSeq, output_dict)
64 json.dump(output_dict, seq_out_file, ensure_ascii=
False, indent=4)
65 except Exception
as e:
66 self.logger.warning(f
'Dumping full config failed with: {e}')
67 self.logger.warning(
'Please also check if "PrintConfiguration" is enabled in the text config.')
69 combine_tools_and_algorithms_ELjob(combine_dictionaries=
False, alg_file=
"_alg_sequence.json", output_file=
"full_config.json")
70 self.logger.info(
"Combining full config to full_config.json succeeded")
72 except Exception
as e:
73 self.logger.warning(f
'Combining full config failed with: {e}')
74 self.logger.warning(
'Please also check if "PrintConfiguration" is enabled in the text config.')
76 os.remove(
"_alg_sequence.json")
79 from pathlib
import Path
81 self.logger.info(
"Moving the analysis root file and the hist file to the top level.")
82 workDir = Path(self.args.work_dir)
if self.args.work_dir
else Path(
'workDir')
83 rootfileSymlink = (workDir /
'data-ANALYSIS' / f
'{self.outputName}.root')
84 rootfilePath = rootfileSymlink.resolve()
85 histfileSymlink = (workDir / f
'hist-{self.outputName}.root')
86 histfilePath = histfileSymlink.resolve()
87 currentDir = Path.cwd()
89 if rootfilePath.exists():
90 self.logger.info(f
"Moving {rootfilePath} to {currentDir / f'{self.outputName}.root'}")
91 if rootfileSymlink.is_symlink():
92 rootfileSymlink.unlink()
93 shutil.move(str(rootfilePath), str(currentDir / f
"{self.outputName}.root"))
95 self.logger.warning(f
"Root file {rootfilePath} does not exist or merging is enabled, skipping move.")
97 if histfilePath.exists():
98 self.logger.info(f
"Moving {histfilePath} to {currentDir / f'hist-{self.outputName}.root'}")
99 if histfileSymlink.is_symlink():
100 histfileSymlink.unlink()
101 shutil.move(str(histfilePath), str(currentDir / f
"hist-{self.outputName}.root"))
103 self.logger.warning(f
"Histogram file {histfilePath} does not exist or merging, skipping move.")
105 newHistFile = currentDir / f
"hist-{self.outputName}.root"
107 if self.args.merge_output_files
and newHistFile.exists():
108 self.logger.info(f
"renaming the hist-{self.outputName}.root to {self.outputName}.root")
109 newHistFile.rename(currentDir / f
"{self.outputName}.root")
136 ROOT.xAOD.Init().ignore()
141 self.
job = ROOT.EL.Job()
143 self.
job.options().setDouble(ROOT.EL.Job.optFilesPerWorker, 100)
144 self.
job.options().setDouble(ROOT.EL.Job.optMaxEvents, self.flags.Exec.MaxEvents)
145 self.
job.options().setString(ROOT.EL.Job.optSubmitDirMode,
'unique-link')
146 self.
job.options().setDouble(ROOT.EL.Job.optSkipEvents, self.flags.Exec.SkipEvents)
149 self.
job.algsAdd(alg)
150 if self.args.merge_output_files:
151 self.
job.options().setString(ROOT.EL.Job.optStreamAliases,
"ANALYSIS=" + ROOT.EL.Job.histogramStreamName)
153 self.
job.outputAdd(ROOT.EL.OutputStream(
'ANALYSIS'))
155 if self.args.run_perf_stat:
156 self.
job.options().setBool(ROOT.EL.Job.optXAODPerfStats, 1)
157 if self.args.algorithm_timers:
158 self.
job.options().setBool(ROOT.EL.Job.optAlgorithmTimer, 1)
159 if self.args.algorithm_memory_monitoring:
160 self.
job.options().setBool(ROOT.EL.Job.optAlgorithmMemoryMonitor, 1)
162 driver = ROOT.EL.DirectDriver()
if self.args.direct_driver
else ROOT.EL.ExecDriver()
165 if self.args.dump_full_config:
169 if self.args.work_dir
is None: