ATLAS Offline Software
Functions | Variables
Herwig7ConfigDecoder Namespace Reference

Functions

def extract_herwig_lines (input_file="Herwig.run", temp_file="HerwigConfigDecoder_RunCardDump.txt", skip_particles=False, skip_decays=False)
 
def run_herwig_get_commands (commands, phase="paths")
 
def execute_herwig_get (herwig_lines, output_file="HerwigConfigDecoder_InterfaceDump.txt", max_lines=None)
 
def process_valid_interfaces (input_file="HerwigConfigDecoder_InterfaceDump.txt", output_file="HerwigConfigDecoder_ConfigParameters.txt")
 
def remove_duplicate_blocks (input_file="HerwigConfigDecoder_ConfigParameters.txt")
 
def DecodeRunCard (input_file='Herwig.run', skip_particles=False, skip_decays=False)
 

Variables

 athMsgLog = Logging.logging.getLogger('Herwig7ConfigDecoder')
 

Function Documentation

◆ DecodeRunCard()

def Herwig7ConfigDecoder.DecodeRunCard (   input_file = 'Herwig.run',
  skip_particles = False,
  skip_decays = False 
)
Main function to decode a Herwig run card by extracting paths, executing commands, and processing interfaces.

Args:
    input_file (str): Path to the Herwig run card file (default: 'Herwig.run').
    skip_particles (bool): If True, skip particle-related lines.
    skip_decays (bool): If True, skip decay-related lines.

Definition at line 344 of file Herwig7ConfigDecoder.py.

344 def DecodeRunCard(input_file='Herwig.run', skip_particles=False, skip_decays=False):
345  """Main function to decode a Herwig run card by extracting paths, executing commands, and processing interfaces.
346 
347  Args:
348  input_file (str): Path to the Herwig run card file (default: 'Herwig.run').
349  skip_particles (bool): If True, skip particle-related lines.
350  skip_decays (bool): If True, skip decay-related lines.
351  """
352  athMsgLog.info("Hello from the config-decoder!")
353 
354  # Step 1: Extract Herwig configuration lines
355  herwig_lines = extract_herwig_lines(
356  input_file=input_file,
357  skip_particles=skip_particles,
358  skip_decays=skip_decays
359  )
360 
361  # Step 2: Execute Herwig 'get' commands for the extracted paths
362  if herwig_lines:
363  execute_herwig_get(herwig_lines)
364 
365  # Step 3: Process valid interfaces for the paths
367 
368  # Step 4: Remove any duplicate blocks in the final output
370 
371  athMsgLog.info("Goodbye from the config-decoder!")

◆ execute_herwig_get()

def Herwig7ConfigDecoder.execute_herwig_get (   herwig_lines,
  output_file = "HerwigConfigDecoder_InterfaceDump.txt",
  max_lines = None 
)
Execute Herwig 'get' commands for all provided paths in a single shell session and save the results.

Args:
    herwig_lines (list): List of Herwig configuration paths to process.
    output_file (str): Path to the output file for results (default: 'HerwigConfigDecoder_InterfaceDump.txt').
    max_lines (int, optional): Maximum number of lines to process (default: None, processes all lines).

Definition at line 170 of file Herwig7ConfigDecoder.py.

170 def execute_herwig_get(herwig_lines, output_file="HerwigConfigDecoder_InterfaceDump.txt", max_lines=None):
171  """Execute Herwig 'get' commands for all provided paths in a single shell session and save the results.
172 
173  Args:
174  herwig_lines (list): List of Herwig configuration paths to process.
175  output_file (str): Path to the output file for results (default: 'HerwigConfigDecoder_InterfaceDump.txt').
176  max_lines (int, optional): Maximum number of lines to process (default: None, processes all lines).
177  """
178  try:
179  # Check if Herwig path is set
180  herwig_path = os.getenv('HERWIG7_PATH')
181  if not herwig_path:
182  athMsgLog.error("Error: Environment variable HERWIG7_PATH is not set")
183  return
184 
185  # Limit the number of lines to process if specified
186  lines_to_process = herwig_lines[:max_lines] if max_lines is not None else herwig_lines
187 
188  # Open the output file and process the Herwig paths
189  with open(output_file, 'w') as outfile:
190  total_tasks = len(lines_to_process)
191  athMsgLog.info(f"Processing {total_tasks} Herwig paths")
192  results = run_herwig_get_commands(lines_to_process, phase="paths")
193 
194  # Sort results to maintain original order
195  results.sort(key=lambda x: lines_to_process.index(x[0]) if x[0] in lines_to_process else float('inf'))
196 
197  # Write results to the output file
198  for line, output in results:
199  if not line:
200  continue
201  outfile.write(f"{line}\n{output}\n\n")
202  athMsgLog.debug(f"Success! Parsed the options for: {line}")
203 
204  athMsgLog.info(f"Results saved to {output_file} (processed {len(lines_to_process)} lines)")
205 
206  except Exception as e:
207  athMsgLog.info(f"Error: An error occurred during execution: {str(e)}")
208 

◆ extract_herwig_lines()

def Herwig7ConfigDecoder.extract_herwig_lines (   input_file = "Herwig.run",
  temp_file = "HerwigConfigDecoder_RunCardDump.txt",
  skip_particles = False,
  skip_decays = False 
)
Extract unique lines containing '/Herwig/' (excluding 'cvmfs') from the input file and save to a temporary file.

Args:
    input_file (str): Path to the input Herwig run card file (default: 'Herwig.run').
    temp_file (str): Path to the temporary output file for extracted lines (default: 'HerwigConfigDecoder_RunCardDump.txt').
    skip_particles (bool): If True, skip lines related to /Herwig/Particles, /Herwig/Masses, and /Herwig/Widths.
    skip_decays (bool): If True, skip lines related to /Herwig/Decays.

Returns:
    list: List of unique Herwig configuration lines extracted.

Definition at line 13 of file Herwig7ConfigDecoder.py.

13 def extract_herwig_lines(input_file="Herwig.run", temp_file="HerwigConfigDecoder_RunCardDump.txt", skip_particles=False, skip_decays=False):
14  """Extract unique lines containing '/Herwig/' (excluding 'cvmfs') from the input file and save to a temporary file.
15 
16  Args:
17  input_file (str): Path to the input Herwig run card file (default: 'Herwig.run').
18  temp_file (str): Path to the temporary output file for extracted lines (default: 'HerwigConfigDecoder_RunCardDump.txt').
19  skip_particles (bool): If True, skip lines related to /Herwig/Particles, /Herwig/Masses, and /Herwig/Widths.
20  skip_decays (bool): If True, skip lines related to /Herwig/Decays.
21 
22  Returns:
23  list: List of unique Herwig configuration lines extracted.
24  """
25  try:
26  # Read the input file and filter lines containing '/Herwig/' while excluding 'cvmfs'
27  with open(input_file, 'r') as infile:
28  all_lines = [line.strip() for line in infile if '/Herwig/' in line and 'cvmfs' not in line]
29  herwig_lines = []
30  seen_paths = set() # Track unique paths to avoid duplicates
31  skip_particles_count = 0
32  skip_decays_count = 0
33  for line in all_lines:
34  # Skip particle-related lines if specified
35  if skip_particles and ('/Herwig/Particles' in line or '/Herwig/Masses' in line or '/Herwig/Widths' in line):
36  skip_particles_count += 1
37  continue
38  # Skip decay-related lines if specified
39  if skip_decays and '/Herwig/Decays' in line:
40  skip_decays_count += 1
41  continue
42  # Skip duplicate lines
43  if line in seen_paths:
44  athMsgLog.debug(f"Skipped duplicate path: {line}")
45  continue
46  seen_paths.add(line)
47  herwig_lines.append(line)
48  # Clean up specific Herwig path formatting issues
49  for i in range(len(herwig_lines)):
50  if '|}/Herwig' in herwig_lines[i]:
51  herwig_lines[i] = herwig_lines[i].replace('|}/Herwig', '/Herwig')
52  elif '}/Herwig' in herwig_lines[i]:
53  herwig_lines[i] = herwig_lines[i].replace('}/Herwig', '/Herwig')
54 
55  # Log information about skipped lines
56  skipped_count = len(all_lines) - len(herwig_lines)
57  if skipped_count > 0:
58  athMsgLog.debug(f"Skipped {skipped_count} lines (including {len(all_lines) - len(seen_paths) - skip_particles_count - skip_decays_count} duplicates)")
59  if skip_particles_count > 0:
60  athMsgLog.debug(f"Skipped {skip_particles_count} /Herwig/Particles, /Herwig/Masses and /Herwig/Widths lines due to --skip-particles")
61  if skip_decays_count > 0:
62  athMsgLog.debug(f"Skipped {skip_decays_count} /Herwig/Decays lines due to --skip-decays")
63 
64  # Write the filtered unique lines to the temporary file
65  with open(temp_file, 'w') as outfile:
66  outfile.writelines(line + '\n' for line in herwig_lines)
67 
68  athMsgLog.info(f"Successfully extracted {len(herwig_lines)} unique lines to {temp_file}")
69  return herwig_lines
70  except FileNotFoundError:
71  athMsgLog.info(f"Error: Input file '{input_file}' not found")
72  return []
73  except Exception as e:
74  athMsgLog.info(f"Error: An error occurred: {str(e)}")
75  return []
76 

◆ process_valid_interfaces()

def Herwig7ConfigDecoder.process_valid_interfaces (   input_file = "HerwigConfigDecoder_InterfaceDump.txt",
  output_file = "HerwigConfigDecoder_ConfigParameters.txt" 
)
Process valid interfaces for each /Herwig/ path, execute 'get' commands, and save results.

Args:
    input_file (str): Path to the input file containing Herwig paths and interfaces (default: 'HerwigConfigDecoder_InterfaceDump.txt').
    output_file (str): Path to the output file for interface results (default: 'HerwigConfigDecoder_ConfigParameters.txt').

Definition at line 209 of file Herwig7ConfigDecoder.py.

209 def process_valid_interfaces(input_file="HerwigConfigDecoder_InterfaceDump.txt", output_file="HerwigConfigDecoder_ConfigParameters.txt"):
210  """Process valid interfaces for each /Herwig/ path, execute 'get' commands, and save results.
211 
212  Args:
213  input_file (str): Path to the input file containing Herwig paths and interfaces (default: 'HerwigConfigDecoder_InterfaceDump.txt').
214  output_file (str): Path to the output file for interface results (default: 'HerwigConfigDecoder_ConfigParameters.txt').
215  """
216  try:
217  # Check if Herwig path is set
218  herwig_path_env = os.getenv('HERWIG7_PATH')
219  if not herwig_path_env:
220  athMsgLog.error("Error: Environment variable HERWIG7_PATH is not set")
221  return
222 
223  # Read the input file and process each block of Herwig paths and interfaces
224  with open(input_file, 'r') as infile, open(output_file, 'w') as outfile:
225  content = infile.read()
226  blocks = content.split('\n\n')
227 
228  all_tasks = []
229  block_paths = []
230  errors = [] # Buffer for "No valid interfaces" errors
231  seen_paths = set() # Track unique paths to avoid duplicates
232  for block in blocks:
233  lines = block.split('\n')
234  if not lines or not lines[0].startswith('/Herwig/'):
235  continue
236 
237  herwig_path = lines[0].strip()
238  if herwig_path in seen_paths:
239  athMsgLog.debug(f"Skipped duplicate path in herwig_results.txt: {herwig_path}")
240  continue
241  seen_paths.add(herwig_path)
242  block_paths.append(herwig_path)
243  # Extract valid interfaces from the block
244  valid_interfaces = [
245  line.strip()[2:] for line in lines[1:]
246  if line.strip().startswith('* ')
247  ]
248 
249  if not valid_interfaces:
250  errors.append((herwig_path, f"No valid interfaces found for {herwig_path}"))
251  outfile.write(f"{herwig_path}\nNo valid interfaces found\n\n")
252  continue
253 
254  all_tasks.extend([(herwig_path, interface) for interface in valid_interfaces])
255 
256  if not all_tasks:
257  athMsgLog.info("No interfaces to process")
258  # Log any buffered errors before returning
259  for _, error_msg in errors:
260  athMsgLog.debug(error_msg)
261  return
262 
263  # Process all interfaces in a single shell session
264  athMsgLog.info(f"Processing {len(all_tasks)} interfaces")
265  results = run_herwig_get_commands(all_tasks, phase="interfaces")
266 
267  # Log buffered errors
268  for _, error_msg in errors:
269  athMsgLog.debug(error_msg)
270 
271  # Organize results by Herwig path
272  path_results = {}
273  for herwig_path, get_command, filtered_output in results:
274  if herwig_path not in path_results:
275  path_results[herwig_path] = []
276  path_results[herwig_path].append((get_command, filtered_output))
277 
278  # Write results to the output file
279  for herwig_path in block_paths:
280  if herwig_path not in path_results:
281  continue
282  athMsgLog.debug(f"Processing interfaces for {herwig_path}:")
283  outfile.write(f"{herwig_path}\n")
284  for get_command, filtered_output in path_results[herwig_path]:
285  athMsgLog.debug(f"{get_command} ::: {filtered_output}")
286  outfile.write(f"{get_command} ::: {filtered_output}\n")
287  outfile.write("\n")
288 
289  athMsgLog.info(f"Interface results saved to {output_file}")
290 
291  except FileNotFoundError:
292  athMsgLog.info(f"Error: Input file '{input_file}' not found")
293  except Exception as e:
294  athMsgLog.info(f"Error: An error occurred during interface processing: {str(e)}")
295 

◆ remove_duplicate_blocks()

def Herwig7ConfigDecoder.remove_duplicate_blocks (   input_file = "HerwigConfigDecoder_ConfigParameters.txt")
Remove duplicate blocks in the configuration parameters file, keeping the first occurrence.

Args:
    input_file (str): Path to the input file to process (default: 'HerwigConfigDecoder_ConfigParameters.txt').

Definition at line 296 of file Herwig7ConfigDecoder.py.

296 def remove_duplicate_blocks(input_file="HerwigConfigDecoder_ConfigParameters.txt"):
297  """Remove duplicate blocks in the configuration parameters file, keeping the first occurrence.
298 
299  Args:
300  input_file (str): Path to the input file to process (default: 'HerwigConfigDecoder_ConfigParameters.txt').
301  """
302  try:
303  # Read the input file and split into blocks
304  with open(input_file, 'r') as infile:
305  content = infile.read()
306  blocks = content.rstrip().split('\n\n')
307 
308  # Keep the first block for each unique Herwig path
309  path_blocks = {}
310  for block in blocks:
311  lines = block.split('\n')
312  if not lines or not lines[0].startswith('/Herwig/'):
313  continue
314  herwig_path = lines[0].strip()
315  if herwig_path not in path_blocks:
316  path_blocks[herwig_path] = block
317  else:
318  athMsgLog.debug(f"Removed duplicate block for {herwig_path}")
319 
320  # Collect unique blocks in their original order
321  unique_blocks = []
322  seen_paths = set()
323  for block in blocks:
324  lines = block.split('\n')
325  if not lines or not lines[0].startswith('/Herwig/'):
326  continue
327  herwig_path = lines[0].strip()
328  if herwig_path not in seen_paths:
329  seen_paths.add(herwig_path)
330  unique_blocks.append(path_blocks[herwig_path])
331 
332  # Write the unique blocks back to the file
333  with open(input_file, 'w') as outfile:
334  outfile.write('\n\n'.join(unique_blocks) + '\n')
335 
336  athMsgLog.info(f"Removed duplicate blocks in {input_file}")
337  athMsgLog.info(f"Retained {len(unique_blocks)} unique blocks")
338 
339  except FileNotFoundError:
340  athMsgLog.info(f"Error: Input file '{input_file}' not found")
341  except Exception as e:
342  athMsgLog.info(f"Error: An error occurred while removing duplicate blocks: {str(e)}")
343 

◆ run_herwig_get_commands()

def Herwig7ConfigDecoder.run_herwig_get_commands (   commands,
  phase = "paths" 
)
Execute multiple Herwig 'get' commands in a single shell session and parse the output.

Args:
    commands (list): List of commands or tuples (for interfaces) to execute.
    phase (str): Execution phase, either 'paths' for path commands or 'interfaces' for interface commands.

Returns:
    list: List of tuples containing the command and its output or error message.

Definition at line 77 of file Herwig7ConfigDecoder.py.

77 def run_herwig_get_commands(commands, phase="paths"):
78  """Execute multiple Herwig 'get' commands in a single shell session and parse the output.
79 
80  Args:
81  commands (list): List of commands or tuples (for interfaces) to execute.
82  phase (str): Execution phase, either 'paths' for path commands or 'interfaces' for interface commands.
83 
84  Returns:
85  list: List of tuples containing the command and its output or error message.
86  """
87  if not commands:
88  return []
89 
90  # Retrieve Herwig installation path from environment variable
91  herwig_path = os.getenv('HERWIG7_PATH')
92  if not herwig_path:
93  return [(cmd, "Error: Environment variable HERWIG7_PATH is not set") for cmd in commands]
94 
95  # Construct the Herwig command to read the default repository
96  herwig_cmd = f"{herwig_path}/bin/Herwig read --repo={herwig_path}/share/Herwig/HerwigDefaults.rpo"
97 
98  try:
99  # Create a temporary script file to store the commands
100  temp_script = f"temp_herwig_script_{os.getpid()}.in"
101  with open(temp_script, 'w') as f:
102  for cmd in commands:
103  if phase == "paths":
104  f.write(f"get {cmd}\n")
105  else: # interfaces
106  f.write(f"get {cmd[0]}:{cmd[1]}\n")
107 
108  # Execute the Herwig command with the temporary script as input
109  cmd = f"cat {temp_script} | {herwig_cmd}"
110  result = subprocess.run(
111  cmd,
112  shell=True,
113  capture_output=True,
114  text=True,
115  timeout=10 * len(commands) # Scale timeout based on number of commands
116  )
117 
118  # Process the command output
119  output = result.stdout.strip()
120  if result.stderr:
121  output += f"\nError: {result.stderr.strip()}"
122 
123  # Clean up the temporary script file
124  Path(temp_script).unlink()
125 
126  # Split output into individual command responses
127  outputs = output.split("Herwig> get ")[1:] if output else []
128  results = []
129  for i, cmd in enumerate(commands):
130  if i < len(outputs):
131  raw_output = outputs[i].strip()
132  # Remove the command itself from the output
133  cmd_str = cmd if phase == "paths" else f"{cmd[0]}:{cmd[1]}"
134  if raw_output.startswith(cmd_str):
135  raw_output = raw_output[len(cmd_str):].strip()
136  if phase == "interfaces":
137  # Apply filtering for interface outputs
138  if len(raw_output.split("\n")) == 1:
139  if raw_output.split("\n")[0] != '' and raw_output.split("\n")[0] != 'Herwig>':
140  filtered_output = raw_output.split("\n")[0]
141  elif raw_output.split("\n")[0] != 'Herwig>':
142  filtered_output = "No response from the interface"
143  else:
144  filtered_output = "No response from the interface"
145  elif len(raw_output.split("\n")) == 2:
146  filtered_output = "No response from the interface"
147  elif len(raw_output.split("\n")) == 3:
148  if all("Herwig" in line for line in raw_output.split("\n")):
149  filtered_output = "No response from the interface"
150  else:
151  filtered_output = raw_output.split("\n")[1]
152  else:
153  filtered_output = raw_output
154  results.append((cmd[0], f"{cmd[0]}:{cmd[1]}", filtered_output))
155  else:
156  results.append((cmd, raw_output))
157  else:
158  if phase == "interfaces":
159  results.append((cmd[0], f"{cmd[0]}:{cmd[1]}", "Error: No output received"))
160  else:
161  results.append((cmd, "Error: No output received"))
162 
163  return results
164 
165  except subprocess.TimeoutExpired:
166  return [(cmd, "Error: Command timed out") if phase == "paths" else (cmd[0], f"{cmd[0]}:{cmd[1]}", "Error: Command timed out") for cmd in commands]
167  except Exception as e:
168  return [(cmd, f"Error: {str(e)}") if phase == "paths" else (cmd[0], f"{cmd[0]}:{cmd[1]}", f"Error: {str(e)}") for cmd in commands]
169 

Variable Documentation

◆ athMsgLog

Herwig7ConfigDecoder.athMsgLog = Logging.logging.getLogger('Herwig7ConfigDecoder')

Definition at line 11 of file Herwig7ConfigDecoder.py.

replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
Herwig7ConfigDecoder.remove_duplicate_blocks
def remove_duplicate_blocks(input_file="HerwigConfigDecoder_ConfigParameters.txt")
Definition: Herwig7ConfigDecoder.py:296
Herwig7ConfigDecoder.DecodeRunCard
def DecodeRunCard(input_file='Herwig.run', skip_particles=False, skip_decays=False)
Definition: Herwig7ConfigDecoder.py:344
Herwig7ConfigDecoder.run_herwig_get_commands
def run_herwig_get_commands(commands, phase="paths")
Definition: Herwig7ConfigDecoder.py:77
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
Herwig7ConfigDecoder.extract_herwig_lines
def extract_herwig_lines(input_file="Herwig.run", temp_file="HerwigConfigDecoder_RunCardDump.txt", skip_particles=False, skip_decays=False)
Definition: Herwig7ConfigDecoder.py:13
Herwig7ConfigDecoder.execute_herwig_get
def execute_herwig_get(herwig_lines, output_file="HerwigConfigDecoder_InterfaceDump.txt", max_lines=None)
Definition: Herwig7ConfigDecoder.py:170
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:194
Herwig7ConfigDecoder.process_valid_interfaces
def process_valid_interfaces(input_file="HerwigConfigDecoder_InterfaceDump.txt", output_file="HerwigConfigDecoder_ConfigParameters.txt")
Definition: Herwig7ConfigDecoder.py:209
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
Trk::open
@ open
Definition: BinningType.h:40
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:67
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65