ATLAS Offline Software
Loading...
Searching...
No Matches
python.AutogenDocumentation Namespace Reference

Functions

Dict[str, List[Dict[str, Any]]] load_output_variables (str yaml_filepath)
Dict[str, Any] extract_block_options (Type block_class)
Optional[str] interpret_physical_unit (str info)
str process_info_links (str info)
str link_jira_tickets (str info)
List[Dict[str, Any]] extract_from_classes (List[Type] block_classes, Optional[Union[str, List[str]]] output_vars_yaml=None)
None save_as_yaml (List[Dict[str, Any]] data, str filepath)
str generate_block_markdown (Dict[str, Any] block_info)
None process_markdown_with_autogen (str input_filepath, str output_filepath, List[Dict[str, Any]] block_data)

Variables

 logger = logging.getLogger("AutogenDocumentation")

Detailed Description

Core methods to extract options information from ConfigBlock classes and merge with
output variables metadata from a YAML file.

Function Documentation

◆ extract_block_options()

Dict[str, Any] python.AutogenDocumentation.extract_block_options ( Type block_class)
Extract options information from a ConfigBlock subclass.

Args:
    block_class: A class that inherits from ConfigBlock

Returns:
    A dictionary containing the class name and its options

Definition at line 40 of file AutogenDocumentation.py.

40def extract_block_options(block_class: Type) -> Dict[str, Any]:
41 """
42 Extract options information from a ConfigBlock subclass.
43
44 Args:
45 block_class: A class that inherits from ConfigBlock
46
47 Returns:
48 A dictionary containing the class name and its options
49 """
50 # Create a temporary instance to access the options
51 instance = block_class()
52
53 # Get the options dictionary
54 options_dict = instance.getOptions()
55
56 # Extract information for each option
57 options_list = []
58 for option_name, option_obj in options_dict.items():
59 # skip some specific options
60 if option_name in ["groupName", "propertyOverrides", "ignoreDependencies"]:
61 continue
62 option_info = {
63 "label": option_name,
64 "type": option_obj.type.__name__ if option_obj.type is not None else "None",
65 "default": option_obj.default,
66 "info": option_obj.info,
67 "required": option_obj.required,
68 "noneAction": option_obj.noneAction,
69 "physicalUnit": interpret_physical_unit(option_obj.info),
70 }
71 # Check if this option has expert mode settings
72 if (
73 hasattr(instance, "_expertModeSettings")
74 and option_name in instance._expertModeSettings
75 ):
76 expert_rule = instance._expertModeSettings[option_name]
77 if not isinstance(expert_rule, list):
78 expert_rule = [expert_rule]
79 else:
80 expert_rule = None
81 option_info["expertMode"] = expert_rule
82 options_list.append(option_info)
83
84 return {
85 "class": block_class.__name__,
86 "module": block_class.__module__,
87 "docstring": inspect.getdoc(block_class),
88 "options": options_list,
89 }
90
91

◆ extract_from_classes()

List[Dict[str, Any]] python.AutogenDocumentation.extract_from_classes ( List[Type] block_classes,
Optional[Union[str, List[str]]] output_vars_yaml = None )
Extract options information from a list of ConfigBlock classes and merge
with output variables metadata.

Args:
    block_classes: List of classes that inherit from ConfigBlock
    output_vars_yaml: Optional path to YAML file or list of paths to YAML files
                     containing output variables. If multiple files provided,
                     their contents will be merged. Files are located using
                     find_datafile.

Returns:
    List of dictionaries, each containing information about a block class

Definition at line 190 of file AutogenDocumentation.py.

192) -> List[Dict[str, Any]]:
193 """
194 Extract options information from a list of ConfigBlock classes and merge
195 with output variables metadata.
196
197 Args:
198 block_classes: List of classes that inherit from ConfigBlock
199 output_vars_yaml: Optional path to YAML file or list of paths to YAML files
200 containing output variables. If multiple files provided,
201 their contents will be merged. Files are located using
202 find_datafile.
203
204 Returns:
205 List of dictionaries, each containing information about a block class
206 """
207 # Load output variables if YAML file(s) provided
208 output_vars_map = {}
209 if output_vars_yaml:
210 # Normalize to list for uniform processing
211 yaml_files = (
212 [output_vars_yaml]
213 if isinstance(output_vars_yaml, str)
214 else output_vars_yaml
215 )
216
217 # Load and merge all YAML files
218 for yaml_file in yaml_files:
219 # Locate the file
220 resolved_path = find_datafile(yaml_file)
221 if resolved_path is None:
222 raise FileNotFoundError(f"Could not locate YAML file: {yaml_file}")
223
224 file_vars = load_output_variables(resolved_path)
225 # Merge with existing map (later files can override earlier ones)
226 for class_name, variables in file_vars.items():
227 if class_name in output_vars_map:
228 # Merge variable lists, avoiding duplicates if needed
229 output_vars_map[class_name].extend(variables)
230 else:
231 output_vars_map[class_name] = variables
232
233 results = []
234 for block_class in block_classes:
235 info = extract_block_options(block_class)
236 # Merge output variables if available
237 class_name = block_class.__name__
238 info["output_variables"] = output_vars_map.get(class_name, [])
239
240 results.append(info)
241
242 return results
243
244

◆ generate_block_markdown()

str python.AutogenDocumentation.generate_block_markdown ( Dict[str, Any] block_info)
Generate Markdown documentation for a single block.

Args:
    block_info: Dictionary containing block information with keys:
        - class: Block class name
        - module: Module containing the block
        - options: List of option dictionaries
        - output_variables: List of output variable dictionaries

Returns:
    Markdown string for this block

Definition at line 252 of file AutogenDocumentation.py.

252def generate_block_markdown(block_info: Dict[str, Any]) -> str:
253 """
254 Generate Markdown documentation for a single block.
255
256 Args:
257 block_info: Dictionary containing block information with keys:
258 - class: Block class name
259 - module: Module containing the block
260 - options: List of option dictionaries
261 - output_variables: List of output variable dictionaries
262
263 Returns:
264 Markdown string for this block
265 """
266 markdown = ""
267
268 # Options section
269 if block_info.get("options"):
270 for opt in block_info["options"]:
271 name = opt["label"]
272
273 # Skip these settings unless they are True
274 if name in ["skipOnData", "skipOnMC"]:
275 if not opt["default"] is True:
276 continue
277 # Skip these settings unless they are set
278 if name in ["onlyForDSIDs"]:
279 if not opt["default"] is []:
280 continue
281
282 # Option label with type, expert flag, required flag
283 label = f"`{opt['label']}` ({opt['type']})"
284 if opt["expertMode"] is not None:
285 expertOptions = list(opt["expertMode"])
286 label += f" **[expert-only options: {','.join(['`' + str(x) + '`' for x in expertOptions])}]**"
287 if opt["required"] is True or opt["noneAction"] != "ignore":
288 label += " **[REQUIRED]**"
289
290 markdown += f"{label}\n"
291 info_string = opt["info"]
292 info_string = process_info_links(info_string)
293 info_string = link_jira_tickets(info_string)
294 markdown += f": {info_string}"
295
296 if opt.get("default") != "":
297 default_val = opt["default"]
298 default_str = repr(default_val)
299
300 # Add unit information if available
301 unit = opt.get("physicalUnit")
302 if unit is None or default_val is None:
303 default_display = f"`{default_str}`"
304 elif unit == "GeV":
305 default_display = f"`{default_str}` GeV"
306 elif unit == "MeV":
307 # Convert MeV to GeV for simplified display
308 try:
309 if isinstance(default_val, (list, tuple)):
310 converted = [float(x) / 1000 for x in default_val]
311 converted_str = (
312 "[" + ", ".join(f"{x}" for x in converted) + "]"
313 )
314 else:
315 converted = float(default_val) / 1000
316 converted_str = f"{converted}"
317 except (TypeError, ValueError):
318 converted_str = "?"
319 default_display = f"`{default_str}` MeV (`{converted_str}` GeV)"
320 else:
321 default_display = f"`{default_str}` {unit}"
322
323 markdown += f" Default: {default_display}."
324
325 markdown += "\n\n"
326
327 # Output variables section
328 if block_info.get("output_variables"):
329 # Separate variables into always-saved and toggled
330 always_saved = []
331 toggled_vars = {} # toggled_by condition -> list of variables
332
333 for var in block_info["output_variables"]:
334 if var.get("toggled_by"):
335 condition = var["toggled_by"]
336 if condition not in toggled_vars:
337 toggled_vars[condition] = []
338 toggled_vars[condition].append(var)
339 else:
340 always_saved.append(var)
341
342 # Always-saved variables section
343 if always_saved:
344 markdown += '!!! success "Registers the following variables:"\n'
345 for var in always_saved:
346 var_name = var.get("name", "N/A")
347 var_desc = var.get("description", "")
348 markdown += f" - `{var_name}`: {var_desc}\n"
349 markdown += "\n"
350
351 # Toggled variables sections
352 for condition, vars_list in toggled_vars.items():
353 markdown += (
354 f'!!! success "Additional variables toggled by `{condition}`:"\n'
355 )
356 for var in vars_list:
357 var_name = var.get("name", "N/A")
358 var_desc = var.get("description", "")
359 markdown += f" - `{var_name}`: {var_desc}\n"
360 markdown += "\n"
361 else:
362 logger.warning(
363 f"Block {block_info.get('class')} didn't register any output variables."
364 )
365
366 return markdown
367
368

◆ interpret_physical_unit()

Optional[str] python.AutogenDocumentation.interpret_physical_unit ( str info)
Extract a physical unit from an info string.
Currently looks for energy units like MeV or GeV.

Args:
    info: The information string from an option.

Returns:
    The detected unit as a string ("MeV", "GeV", etc.) or None if no unit is found.

Definition at line 92 of file AutogenDocumentation.py.

92def interpret_physical_unit(info: str) -> Optional[str]:
93 """
94 Extract a physical unit from an info string.
95 Currently looks for energy units like MeV or GeV.
96
97 Args:
98 info: The information string from an option.
99
100 Returns:
101 The detected unit as a string ("MeV", "GeV", etc.) or None if no unit is found.
102 """
103 if not info:
104 return None
105
106 # Check for specific units
107 patterns = [
108 r"\[MeV\]",
109 r"\‍(MeV\‍)",
110 r"\‍(in MeV\‍)",
111 r"\[in MeV\]",
112 r"\[GeV\]",
113 r"\‍(GeV\‍)",
114 r"\‍(in GeV\‍)",
115 r"\[in GeV\]",
116 r"\[mm\]",
117 r"\‍(mm\‍)",
118 r"\‍(in mm\‍)",
119 r"\[in mm\]",
120 ]
121 for pattern in patterns:
122 if re.search(pattern, info):
123 if "MeV" in pattern:
124 return "MeV"
125 elif "GeV" in pattern:
126 return "GeV"
127 elif "mm" in pattern:
128 return "mm"
129 return None
130
131

◆ link_jira_tickets()

str python.AutogenDocumentation.link_jira_tickets ( str info)
Convert JIRA ticket references in a string to Markdown links.

- JIRA tickets are of the form: all-caps letters, a dash, then digits (e.g., ATLASG-2358)
- Converted to Markdown links: [ATLASG-2358](https://its.cern.ch/jira/browse/ATLASG-2358)

Args:
    info: Input string that may contain JIRA tickets.

Returns:
    The string with JIRA tickets converted to Markdown links.

Definition at line 163 of file AutogenDocumentation.py.

163def link_jira_tickets(info: str) -> str:
164 """
165 Convert JIRA ticket references in a string to Markdown links.
166
167 - JIRA tickets are of the form: all-caps letters, a dash, then digits (e.g., ATLASG-2358)
168 - Converted to Markdown links: [ATLASG-2358](https://its.cern.ch/jira/browse/ATLASG-2358)
169
170 Args:
171 info: Input string that may contain JIRA tickets.
172
173 Returns:
174 The string with JIRA tickets converted to Markdown links.
175 """
176 if not info:
177 return info
178
179 # Regex pattern: one or more uppercase letters, dash, one or more digits
180 pattern = r"\b([A-Z]+-\d+)\b"
181
182 def replace_match(match):
183 ticket = match.group(1)
184 url = f"https://its.cern.ch/jira/browse/{ticket}"
185 return f"[{ticket}]({url})"
186
187 return re.sub(pattern, replace_match, info)
188
189

◆ load_output_variables()

Dict[str, List[Dict[str, Any]]] python.AutogenDocumentation.load_output_variables ( str yaml_filepath)
Load output variables metadata from YAML file.

Expected YAML format:
    BlockClassName:
      - name: variable_name
        description: Variable description
        toggled_by: Optional condition description

Args:
    yaml_filepath: Path to the YAML file

Returns:
    Dictionary mapping block class names to their output variables

Definition at line 19 of file AutogenDocumentation.py.

19def load_output_variables(yaml_filepath: str) -> Dict[str, List[Dict[str, Any]]]:
20 """
21 Load output variables metadata from YAML file.
22
23 Expected YAML format:
24 BlockClassName:
25 - name: variable_name
26 description: Variable description
27 toggled_by: Optional condition description
28
29 Args:
30 yaml_filepath: Path to the YAML file
31
32 Returns:
33 Dictionary mapping block class names to their output variables
34 """
35 with open(yaml_filepath, "r") as f:
36 data = yaml.safe_load(f)
37 return data if data else {}
38
39

◆ process_info_links()

str python.AutogenDocumentation.process_info_links ( str info)
Scan an info string for backtick-enclosed substrings of the form `A::B`.
Turn them into a link to the appropriate module/files.

Args:
    info: The input info string.

Returns:
    The processed string with Markdown links where applicable.

Definition at line 132 of file AutogenDocumentation.py.

132def process_info_links(info: str) -> str:
133 """
134 Scan an info string for backtick-enclosed substrings of the form `A::B`.
135 Turn them into a link to the appropriate module/files.
136
137 Args:
138 info: The input info string.
139
140 Returns:
141 The processed string with Markdown links where applicable.
142 """
143 if not info:
144 return info
145
146 # Regex to match `A::B` inside backticks
147 pattern = r"`([^`]+)::([^`]+)`"
148
149 def replace_match(match):
150 A, B = match.group(1), match.group(2)
151 if A == "CP" or A == "ORUtils":
152 url = f"https://acode-browser1.usatlas.bnl.gov/lxr/search?%21v=head&_filestring=**{B}**&_string="
153 return f"[`{A}::{B}`]({url})"
154 elif A == "xAOD" or A == "AthOnnx":
155 url = f"https://acode-browser1.usatlas.bnl.gov/lxr/ident?v=head&_i={B}&_identdefonly=1&_remember=1"
156 else:
157 # TODO: any other cases to handle?
158 return f"`{A}::{B}`"
159
160 return re.sub(pattern, replace_match, info)
161
162

◆ process_markdown_with_autogen()

None python.AutogenDocumentation.process_markdown_with_autogen ( str input_filepath,
str output_filepath,
List[Dict[str, Any]] block_data )
Process an input markdown file, replacing AUTOGEN<BlockName> markers
with generated block documentation.

Looks for lines of the form "AUTOGEN<BlockName>" and replaces them
with the generated markdown for that block. All other content is
left untouched.

Args:
    input_filepath: Path to the input markdown file
    output_filepath: Path to write the processed output
    block_data: List of extracted block information dictionaries

Raises:
    FileNotFoundError: If input file does not exist
    ValueError: If a referenced block is not found in block_data

Definition at line 369 of file AutogenDocumentation.py.

371) -> None:
372 """
373 Process an input markdown file, replacing AUTOGEN<BlockName> markers
374 with generated block documentation.
375
376 Looks for lines of the form "AUTOGEN<BlockName>" and replaces them
377 with the generated markdown for that block. All other content is
378 left untouched.
379
380 Args:
381 input_filepath: Path to the input markdown file
382 output_filepath: Path to write the processed output
383 block_data: List of extracted block information dictionaries
384
385 Raises:
386 FileNotFoundError: If input file does not exist
387 ValueError: If a referenced block is not found in block_data
388 """
389 # Create a mapping of block names to their markdown
390 block_markdown_map = {
391 block["class"]: generate_block_markdown(block) for block in block_data
392 }
393
394 # Read input file
395 with open(input_filepath, "r") as f:
396 lines = f.readlines()
397
398 output_lines = []
399 for line in lines:
400 stripped = line.strip()
401
402 # Check if this line is an AUTOGEN marker
403 if stripped.startswith("AUTOGEN<") and stripped.endswith(">"):
404 # Extract block name from AUTOGEN<BlockName>
405 block_name = stripped[8:-1] # Remove 'AUTOGEN<' and '>'
406
407 if block_name in block_markdown_map:
408 output_lines.append(block_markdown_map[block_name])
409 else:
410 raise ValueError(
411 f"Block '{block_name}' not found in extracted block data"
412 )
413 else:
414 output_lines.append(line)
415
416 # Write output file
417 with open(output_filepath, "w") as f:
418 f.writelines(output_lines)
419
420 logger.info(f"Processed markdown saved to {output_filepath}.")

◆ save_as_yaml()

None python.AutogenDocumentation.save_as_yaml ( List[Dict[str, Any]] data,
str filepath )
Save extracted data as YAML.

Definition at line 245 of file AutogenDocumentation.py.

245def save_as_yaml(data: List[Dict[str, Any]], filepath: str) -> None:
246 """Save extracted data as YAML."""
247 with open(filepath, "w") as f:
248 yaml.dump(data, f, default_flow_style=False, sort_keys=False)
249 logger.info(f"Saved YAML to {filepath}")
250
251

Variable Documentation

◆ logger

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

Definition at line 17 of file AutogenDocumentation.py.