ATLAS Offline Software
Loading...
Searching...
No Matches
python.CPBaseRunner.CPBaseRunner Class Reference
Inheritance diagram for python.CPBaseRunner.CPBaseRunner:
Collaboration diagram for python.CPBaseRunner.CPBaseRunner:

Public Member Functions

 __init__ (self)
 args (self)
 inputList (self)
 outputName (self)
 printFlags (self)
 addCustomArguments (self)
 makeAlgSequence (self)
 run (self)
 setup (self)
 printAvailableArguments (self)
 modifyParserArguments (self)
 modifyYamlConfig (self)
 modifyAlgSequence (self)

Static Public Member Functions

 findLocalPathYamlConfig (textConfigPath)
 findRepoPathYamlConfig (textConfigPath)

Public Attributes

 logger = logging.getLogger("CPBaseRunner")
 parser = self._defaultParseArguments()
 rawConfig = None
 flags = self._defaultFlagsInitialization()
 config = self._readYamlConfig()

Protected Member Functions

 _defaultFlagsInitialization (self)
 _defaultParseArguments (self)
 _mergeYamlconfig (self, Path yaml_path, list[Path] yaml_paths)
 _readYamlConfig (self)
 _findYamlConfig (self, local=True)

Static Protected Member Functions

 _parseInputFileList (Path path)

Protected Attributes

 _args = None
list _inputList = None

Detailed Description

Definition at line 10 of file CPBaseRunner.py.

Constructor & Destructor Documentation

◆ __init__()

python.CPBaseRunner.CPBaseRunner.__init__ ( self)

Definition at line 11 of file CPBaseRunner.py.

11 def __init__(self):
12 self.logger = logging.getLogger("CPBaseRunner")
13 self._args = None
14 self._inputList = None
15 self.parser = self._defaultParseArguments()
16 self.rawConfig = None
17 # parse the arguments here is a bad idea
18

Member Function Documentation

◆ _defaultFlagsInitialization()

python.CPBaseRunner.CPBaseRunner._defaultFlagsInitialization ( self)
protected

Definition at line 75 of file CPBaseRunner.py.

75 def _defaultFlagsInitialization(self):
76 from AthenaConfiguration.AllConfigFlags import initConfigFlags
77 flags = initConfigFlags()
78 flags.Input.Files = self.inputList
79 flags.Exec.MaxEvents = self.args.max_events
80 flags.Exec.SkipEvents = self.args.skip_n_events
81 flags.Exec.EventPrintoutInterval = 10000
82 return flags
83

◆ _defaultParseArguments()

python.CPBaseRunner.CPBaseRunner._defaultParseArguments ( self)
protected

Definition at line 84 of file CPBaseRunner.py.

84 def _defaultParseArguments(self):
85 parser = argparse.ArgumentParser(
86 description='Runscript for CP Algorithm unit tests')
87 baseGroup = parser.add_argument_group('Base Script Options')
88 baseGroup.add_argument('-i', '--input-list', dest='input_list',
89 help='path to text file containing list of input files, or a single root file')
90 baseGroup.add_argument('-o', '--output-name', dest='output_name', default='output',
91 help='output name of the analysis root file')
92 baseGroup.add_argument('-e', '--max-events', dest='max_events', type=int, default=-1,
93 help='Number of events to run')
94 baseGroup.add_argument('-t', '--text-config', dest='text_config',
95 help='path to the YAML configuration file. Tips: use atlas_install_data(path/to/*.yaml) in CMakeLists.txt can help locating the config just by the config file name.')
96 baseGroup.add_argument('--no-systematics', dest='no_systematics',
97 action='store_true', help='Disable systematics')
98 baseGroup.add_argument('--skip-n-events', dest='skip_n_events', type=int, default=0,
99 help='Skip the first N events in the run, not first N events for each file. This is meant for debugging only. \nIn Eventloop, this option disable the cutbookkeeper algorithms due to technical reasons, and can only be ran in direct-driver.')
100 baseGroup.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.')
101 return parser
102

◆ _findYamlConfig()

python.CPBaseRunner.CPBaseRunner._findYamlConfig ( self,
local = True )
protected

Definition at line 129 of file CPBaseRunner.py.

129 def _findYamlConfig(self, local=True):
130 # Find local and abs path first
131 if local and ((yamlConfig := CPBaseRunner.findLocalPathYamlConfig(self.args.text_config)) is not None):
132 return yamlConfig, [yamlConfig.parent if yamlConfig is not None else None]
133 # Then search in the analysis repository and warn for duplicates
134 else:
135 yamlConfig, yamlBasePath = CPBaseRunner.findRepoPathYamlConfig(self.args.text_config)
136 # Try the slowest method using AthenaCommon if nothing found
137 if not yamlConfig:
138 from AthenaCommon.Utils.unixtools import find_datafile
139 yamlConfig = find_datafile(self.args.text_config)
140 if yamlConfig is None:
141 return None, None
142 yamlConfig = Path(yamlConfig)
143 return yamlConfig, [yamlConfig.parent]
144
145 if len(yamlConfig) > 1:
146 raise FileExistsError(
147 f'Multiple files named \"{self.args.text_config}\" found in the analysis repository. Please provide a more specific path to the config file.\nMatches found:\n' + '\n'.join(yamlConfig))
148 else:
149 return yamlConfig[0], [yamlBasePath[0]]
150

◆ _mergeYamlconfig()

python.CPBaseRunner.CPBaseRunner._mergeYamlconfig ( self,
Path yaml_path,
list[Path] yaml_paths )
protected

Definition at line 103 of file CPBaseRunner.py.

103 def _mergeYamlconfig(self, yaml_path: Path, yaml_paths: list[Path]):
104 with yaml_path.open("r", encoding="utf-8") as cfg_file:
105 import yaml
106 config_data = yaml.safe_load(cfg_file)
107 from AnalysisAlgorithmsConfig.ConfigText import combineConfigFiles
108 combined = combineConfigFiles(config_data, yaml_paths, fragment_key="include")
109 if combined:
110 with open("merged_config.yaml", "w") as cfg:
111 cfg.write(yaml.dump(config_data))
112 self.logger.info("Merged included fragments into main config.")
113 return config_data, combined
114

◆ _parseInputFileList()

python.CPBaseRunner.CPBaseRunner._parseInputFileList ( Path path)
staticprotected

Definition at line 188 of file CPBaseRunner.py.

188 def _parseInputFileList(path: Path):
189 files = []
190 with path.open('r') as inputText:
191 for line in inputText.readlines():
192 # Strip the line and skip comments and empty lines
193 line = line.strip()
194 if line.startswith('#') or not line:
195 continue
196 # On grid, input files are listed in one line separated by a comma
197 if ',' in line:
198 files += line.split(',')
199 continue
200 line_path = Path(line)
201 if line_path.is_dir():
202 if not any(line_path.iterdir()):
203 raise FileNotFoundError(
204 f"The directory \"{path}\" is empty. Please provide a directory with .root files.")
205 for root_file in line_path.iterdir():
206 if '.root' in root_file.suffixes:
207 files.append(str(root_file))
208 # This also catches grid input with only one file
209 else:
210 files.append(line)
211
212 # Remove leading/trailing whitespaces from file names
213 files = [file.strip() for file in files]
214 if not files:
215 raise FileNotFoundError(
216 f"No valid input files found in \"{path}\"! Please check the input file list.")
217 return files
218

◆ _readYamlConfig()

python.CPBaseRunner.CPBaseRunner._readYamlConfig ( self)
protected

Definition at line 115 of file CPBaseRunner.py.

115 def _readYamlConfig(self):
116 yamlConfig, yamlPaths = self._findYamlConfig(local=True)
117 if yamlConfig is None:
118 raise FileNotFoundError(f'Failed to locate \"{self.args.text_config}\" config file! '
119 'Check if you have a typo in -t/--text-config argument or missing file in the analysis configuration sub-directory.')
120 self.logger.info(f"Found YAML config at: {yamlConfig}")
121 self.logger.info("Setting up configuration based on YAML config:")
122
123 from AnalysisAlgorithmsConfig.ConfigText import TextConfig
124 self.rawConfig, merged = self._mergeYamlconfig(yamlConfig, yamlPaths)
125 self.modifyYamlConfig()
126 config = TextConfig(config=self.rawConfig)
127 return config
128

◆ addCustomArguments()

python.CPBaseRunner.CPBaseRunner.addCustomArguments ( self)

Definition at line 63 of file CPBaseRunner.py.

63 def addCustomArguments(self):
64 pass
65

◆ args()

python.CPBaseRunner.CPBaseRunner.args ( self)

Definition at line 20 of file CPBaseRunner.py.

20 def args(self):
21 if self._args is None:
22 self._args = self.parser.parse_args()
23 return self._args
24

◆ findLocalPathYamlConfig()

python.CPBaseRunner.CPBaseRunner.findLocalPathYamlConfig ( textConfigPath)
static

Definition at line 152 of file CPBaseRunner.py.

152 def findLocalPathYamlConfig(textConfigPath):
153 configPath = Path(textConfigPath).expanduser()
154 if configPath.is_absolute() and configPath.is_file():
155 return configPath
156 cwdPath = Path.cwd() / configPath
157 if cwdPath.is_file():
158 return cwdPath
159 return None
160

◆ findRepoPathYamlConfig()

python.CPBaseRunner.CPBaseRunner.findRepoPathYamlConfig ( textConfigPath)
static
Search for the file up to two levels deep within the first DATAPATH entry.
First, check directly under the analysis repository (depth 0).
Then, check immediate subdirectories (depth 1), looking for the file inside each.
Returns a list of all matches found and a list of packages/base paths.

Definition at line 162 of file CPBaseRunner.py.

162 def findRepoPathYamlConfig(textConfigPath):
163 """
164 Search for the file up to two levels deep within the first DATAPATH entry.
165 First, check directly under the analysis repository (depth 0).
166 Then, check immediate subdirectories (depth 1), looking for the file inside each.
167 Returns a list of all matches found and a list of packages/base paths.
168 """
169 matches = []
170 basePaths = []
171 analysisRepoPath = Path(environ.get("DATAPATH", "").split(pathsep)[0])
172 # Depth 0: Directly under analysisRepoPath
173 searchPath = analysisRepoPath / textConfigPath
174 if searchPath.is_file():
175 matches.append(searchPath)
176 basePaths.append(analysisRepoPath if searchPath.parent == analysisRepoPath else analysisRepoPath / Path(textConfigPath).parts[0])
177 # Depth 1: Inside immediate subdirectories
178 for subdir in analysisRepoPath.iterdir():
179 if not subdir.is_dir():
180 continue
181 candidate = analysisRepoPath / subdir / textConfigPath
182 if candidate.is_file():
183 matches.append(candidate)
184 basePaths.append(analysisRepoPath / subdir)
185 return matches, basePaths
186
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179

◆ inputList()

python.CPBaseRunner.CPBaseRunner.inputList ( self)

Definition at line 26 of file CPBaseRunner.py.

26 def inputList(self):
27 if self._inputList is None:
28 if self.args.input_list.endswith('.txt'):
29 self._inputList = CPBaseRunner._parseInputFileList(
30 Path(self.args.input_list))
31 elif ".root" in self.args.input_list:
32 self._inputList = [self.args.input_list]
33 else:
34 raise FileNotFoundError(f'Input file list \"{self.args.input_list}\" is not supported! '
35 'Please provide a text file with a list of input files or a single root file.')
36 self.logger.info("Initialized input files: %s", self._inputList)
37 return self._inputList
38

◆ makeAlgSequence()

python.CPBaseRunner.CPBaseRunner.makeAlgSequence ( self)

Definition at line 67 of file CPBaseRunner.py.

67 def makeAlgSequence(self):
68 pass
69

◆ modifyAlgSequence()

python.CPBaseRunner.CPBaseRunner.modifyAlgSequence ( self)

Definition at line 243 of file CPBaseRunner.py.

243 def modifyAlgSequence(self): # noqa: B027
244 # For AthAnalysis: self.configSeq.some_attribute = some_value
245 # For EventLoop: self.algSeq.some_attribute = some_value
246 # The seemingly trivial log is to prevent CI from complaining about empty hook functions
247 pass

◆ modifyParserArguments()

python.CPBaseRunner.CPBaseRunner.modifyParserArguments ( self)

Definition at line 233 of file CPBaseRunner.py.

233 def modifyParserArguments(self): # noqa: B027
234 # Example: self.parser.add_argument('--no-filter', dest='no_filter', action='store_true', help='Disable filtering')
235 # The seemingly trivial log is to prevent CI from complaining about empty hook functions
236 pass
237

◆ modifyYamlConfig()

python.CPBaseRunner.CPBaseRunner.modifyYamlConfig ( self)

Definition at line 238 of file CPBaseRunner.py.

238 def modifyYamlConfig(self): # noqa: B027
239 # Example: self.rawConfig['SomeSection']['SomeOption'] = some_value
240 # The seemingly trivial log is to prevent CI from complaining about empty hook functions
241 pass
242

◆ outputName()

python.CPBaseRunner.CPBaseRunner.outputName ( self)

Definition at line 40 of file CPBaseRunner.py.

40 def outputName(self):
41 if self.args.output_name.endswith('.root'):
42 return self.args.output_name[:-5]
43 else:
44 return self.args.output_name
45

◆ printAvailableArguments()

python.CPBaseRunner.CPBaseRunner.printAvailableArguments ( self)

Definition at line 224 of file CPBaseRunner.py.

224 def printAvailableArguments(self):
225 self.parser.description = 'CPRunScript available arguments'
226 self.parser.usage = argparse.SUPPRESS
227 self.parser.print_help()
228

◆ printFlags()

python.CPBaseRunner.CPBaseRunner.printFlags ( self)

Definition at line 46 of file CPBaseRunner.py.

46 def printFlags(self):
47 self.logger.info("="*73)
48 self.logger.info("="*20 + "FLAG CONFIGURATION" + "="*20)
49 self.logger.info("="*73)
50 self.logger.info(" Input files: %s", self.flags.Input.Files)
51 self.logger.info(" isMC: %s", self.flags.Input.isMC)
52 self.logger.info(" RunNumber: %s",
53 self.flags.Input.RunNumbers)
54 self.logger.info(" MCCampaign: %s",
55 self.flags.Input.MCCampaign)
56 self.logger.info(" GeneratorInfo: %s",
57 self.flags.Input.GeneratorsInfo)
58 self.logger.info(" MaxEvents: %s", self.flags.Exec.MaxEvents)
59 self.logger.info(" SkipEvents: %s", self.flags.Exec.SkipEvents)
60 self.logger.info("="*73)
61

◆ run()

python.CPBaseRunner.CPBaseRunner.run ( self)

Definition at line 71 of file CPBaseRunner.py.

71 def run(self):
72 pass
73
int run(int argc, char *argv[])

◆ setup()

python.CPBaseRunner.CPBaseRunner.setup ( self)

Definition at line 219 of file CPBaseRunner.py.

219 def setup(self):
220 self.modifyParserArguments()
221 self.flags = self._defaultFlagsInitialization()
222 self.config = self._readYamlConfig()
223
bool setup(asg::AnaToolHandle< Interface > &tool, const std::string &type, const std::vector< std::string > &config, const std::string &progressFile="")
mostly useful for athena, which will otherwise re-use the previous tool

Member Data Documentation

◆ _args

python.CPBaseRunner.CPBaseRunner._args = None
protected

Definition at line 13 of file CPBaseRunner.py.

◆ _inputList

python.CPBaseRunner.CPBaseRunner._inputList = None
protected

Definition at line 14 of file CPBaseRunner.py.

◆ config

python.CPBaseRunner.CPBaseRunner.config = self._readYamlConfig()

Definition at line 222 of file CPBaseRunner.py.

◆ flags

python.CPBaseRunner.CPBaseRunner.flags = self._defaultFlagsInitialization()

Definition at line 221 of file CPBaseRunner.py.

◆ logger

python.CPBaseRunner.CPBaseRunner.logger = logging.getLogger("CPBaseRunner")

Definition at line 12 of file CPBaseRunner.py.

◆ parser

python.CPBaseRunner.CPBaseRunner.parser = self._defaultParseArguments()

Definition at line 15 of file CPBaseRunner.py.

◆ rawConfig

python.CPBaseRunner.CPBaseRunner.rawConfig = None

Definition at line 16 of file CPBaseRunner.py.


The documentation for this class was generated from the following file: