ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
PhysicsAnalysis
Algorithms
AnalysisAlgorithmsConfig
python
SaveConfigUtils.py
Go to the documentation of this file.
1
# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3
from
AnaAlgorithm.AlgSequence
import
AlgSequence
4
from
AnaAlgorithm.PythonConfig
import
PrivateToolConfig
5
from
AthenaCommon.Logging
import
logging
6
7
import
os
8
import
json
9
10
def
combine_tools_and_algorithms_ELjob
(combine_dictionaries = True, text_file = 'tool_config.txt',
11
alg_file = 'alg_sequence.json', output_file = 'my_analysis_config.json'):
12
"""
13
Parse a tool configuration text file and merge it with an algorithm sequence JSON file.
14
15
Args:
16
combine_dictionaries (bool): Whether to load and merge with existing alg_file
17
text_file (str): Path to the tool configuration text file
18
alg_file (str): Path to the algorithm sequence JSON file
19
output_file (str): Path where the merged configuration will be saved
20
21
Returns:
22
dict: The resulting configuration, which is a merge of the tool configuration
23
and algorithm sequence JSON data.
24
"""
25
log = logging.getLogger(
"SaveConfigUtils"
)
26
log.info(
"Calling COMBINE_JSON_FILES with the following arguments:"
)
27
log.info(f
" - tool configuration = {text_file}"
)
28
log.info(f
" - algorithm sequence = {alg_file}"
)
29
log.info(f
" - full output config = {output_file}"
)
30
31
if
not
os.path.exists(text_file):
32
raise
FileNotFoundError(f
"The tool configuration file {text_file} was not found."
)
33
if
not
os.path.exists(alg_file):
34
raise
FileNotFoundError(f
"The algorithm sequence file {alg_file} was not found."
)
35
36
# Load or initialize the configuration
37
config = {}
38
if
combine_dictionaries:
39
with
open(alg_file,
'r'
, encoding=
'utf-8'
)
as
f:
40
try
:
41
config = json.load(f)
42
except
json.JSONDecodeError
as
e:
43
raise
ValueError(f
"Error parsing JSON in {alg_file}: {e}"
)
44
45
# Process the tool configuration file
46
current_tool_path =
None
47
current_tool_id =
None
48
current_tool_properties = {}
49
50
with
open(text_file,
'r'
)
as
f:
51
for
line
in
f:
52
line = line.strip()
53
if
not
line
or
'='
not
in
line:
54
continue
55
56
path, value =
map
(str.strip, line.split(
'='
, 1))
57
parts = path.split(
'.'
)
58
59
# There are two possiblities for 'parts':
60
# 1. Declaration of a new tool
61
# 2. Setting a property on an existing tool
62
if
len(value.split(
"/"
)) == 2
and
"'"
not
in
value
and
current_tool_path != parts:
63
# We are in case 1, meaning we are done with the previous tool (if any)
64
# Start by saving the settings of the previous tool
65
_register_settings
(config, current_tool_path, current_tool_id, current_tool_properties)
66
# Then register the new tool
67
tool_path = parts[:-1]
68
tool_id = parts[-1]
69
tool_name = value.split(
"/"
)[1]
70
_register_new_tool
(config, tool_path, tool_id, tool_name)
71
# We are ready to collect information about the new tool
72
current_tool_path = tool_path
73
current_tool_id = tool_id
74
current_tool_properties = {}
75
else
:
76
# We are in case 2: record new settings
77
property_name = parts[-1]
78
current_tool_properties[property_name] = value
79
80
# Register any remaining settings for the last tool if necessary
81
if
current_tool_properties
and
current_tool_id:
82
_register_settings
(config, current_tool_path, current_tool_id, current_tool_properties)
83
84
# Write output
85
with
open(output_file,
'w'
, encoding=
'utf-8'
)
as
f:
86
json.dump(config, f, indent=4)
87
88
return
config
89
90
91
def
_register_settings
(config, path, name, settings):
92
if
not
settings
or
path
is
None
:
return
93
current_dict = config
94
95
# Iterate through the path to reach the correct nested dictionary
96
for
key
in
path:
97
if
key
not
in
current_dict:
98
raise
ValueError(f
"Couldn't find key {key} in dictionary of algorithms and tools, this should not happen!"
)
99
current_dict = current_dict[key][
"Properties"
][
"Tools"
]
100
101
for
key,value
in
settings.items():
102
_safe_add_property
(key, value, current_dict[name])
103
104
105
def
_register_new_tool
(config, path, tool_id, name):
106
current_dict = config
107
108
# Iterate through the path to reach the correct nested dictionary
109
for
key
in
path:
110
if
key
not
in
current_dict:
111
# Create the entry with the appropriate structure
112
current_dict[key] = {
"Properties"
: {
"Tools"
: {}},
"Type"
:
""
}
113
else
:
114
# Enforce the appropriate structure
115
if
"Properties"
not
in
current_dict[key].keys():
116
current_dict[key][
"Properties"
] = {
"Tools"
: {}}
117
if
"Tools"
not
in
current_dict[key][
"Properties"
].keys():
118
current_dict[key][
"Properties"
][
"Tools"
] = {}
119
current_dict = current_dict[key][
"Properties"
][
"Tools"
]
120
121
# Ensure the tool id exists as a key with a dictionary as its value
122
if
tool_id
not
in
current_dict:
123
current_dict[tool_id] = {
"Properties"
: {}}
124
125
# Set the 'Name:' key with the given name
126
if
"Properties"
not
in
current_dict[tool_id]:
127
current_dict[tool_id][
"Properties"
] = {}
128
current_dict[tool_id][
"Properties"
][
"Name"
] = name
129
130
131
def
save_algs_from_sequence_ELjob
(sequence, output_dict):
132
"""
133
Save the algorithms in the sequence without the sequence structure.
134
Does not save the tools. You need to get them with PrintToolConfigAlg.
135
136
Args:
137
sequence (AnaAlgorithm.AlgSequence: the algorithm sequence to parse
138
output_dict (dict): the dictionary to populate
139
"""
140
# Ensure output_dict is a dictionary
141
if
not
isinstance(output_dict, dict):
142
raise
ValueError(
"output_dict must be a dictionary"
)
143
144
# Handle recursive case for AlgSequence
145
if
isinstance(sequence, AlgSequence):
146
for
alg
in
sequence:
147
nested_dict = {}
148
save_algs_from_sequence_ELjob
(alg, nested_dict)
149
output_dict[alg.name()] = nested_dict
150
else
:
151
# Handle the algorithm itself
152
_save_algorithm
(sequence, output_dict)
153
154
155
def
_save_algorithm
(sequence, output_dict):
156
""" Helper function to save individual algorithm properties """
157
output_dict[
'Type'
] = sequence.type()
158
output_dict[
'Properties'
] = {
'Tools'
: {}}
159
160
for
key, value
in
sorted(sequence._props.items()):
161
if
isinstance(value, str):
162
output_dict[
'Properties'
][key] = value
163
elif
isinstance(value, PrivateToolConfig):
164
_handle_tool_config
(value, output_dict)
165
else
:
166
_safe_add_property
(key, value, output_dict)
167
168
169
def
_handle_tool_config
(tool_config, output_dict):
170
""" Handle tool configurations inside algorithms """
171
log = logging.getLogger(
"SaveConfigUtils"
)
172
if
tool_config._prefix
in
output_dict[
'Properties'
][
'Tools'
]:
173
log.warning(f
"Already have this tool in the dict, prefix: {tool_config._prefix}. You need to ID the name somehow."
)
174
else
:
175
output_dict[
'Properties'
][
'Tools'
][tool_config._prefix] = {
'Type'
: tool_config._type}
176
177
178
def
_safe_add_property
(key, value, output_dict):
179
""" Safely adds properties to the output_dict with error handling """
180
log = logging.getLogger(
"SaveConfigUtils"
)
181
try
:
182
output_dict[
'Properties'
][key] = value
183
except
Exception
as
e:
184
log.warning(f
"Couldn't add property '{key}' to dict. Value: {value}. Error: {e}"
)
map
STL class.
python.SaveConfigUtils._register_settings
_register_settings(config, path, name, settings)
Definition
SaveConfigUtils.py:91
python.SaveConfigUtils._safe_add_property
_safe_add_property(key, value, output_dict)
Definition
SaveConfigUtils.py:178
python.SaveConfigUtils._save_algorithm
_save_algorithm(sequence, output_dict)
Definition
SaveConfigUtils.py:155
python.SaveConfigUtils.combine_tools_and_algorithms_ELjob
combine_tools_and_algorithms_ELjob(combine_dictionaries=True, text_file='tool_config.txt', alg_file='alg_sequence.json', output_file='my_analysis_config.json')
Definition
SaveConfigUtils.py:11
python.SaveConfigUtils._handle_tool_config
_handle_tool_config(tool_config, output_dict)
Definition
SaveConfigUtils.py:169
python.SaveConfigUtils.save_algs_from_sequence_ELjob
save_algs_from_sequence_ELjob(sequence, output_dict)
Definition
SaveConfigUtils.py:131
python.SaveConfigUtils._register_new_tool
_register_new_tool(config, path, tool_id, name)
Definition
SaveConfigUtils.py:105
Generated on
for ATLAS Offline Software by
1.17.0