ATLAS Offline Software
Herwig7JOChecker.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 # Author: Lukas Kretschmann (lukas.kretschmann@cern.ch)
3 
4 # import modules
5 import os
6 import subprocess
7 
8 # import Athena modules
9 from AthenaCommon import Logging
10 athMsgLog = Logging.logging.getLogger('Herwig7JOChecker')
11 
12 # Helper function to get the current Herwig version
14  herwig7_bin_path = os.path.join(os.environ['HERWIG7_PATH'],'bin')
15  herwig7_binary = os.path.join(herwig7_bin_path,'Herwig')
16  versions = subprocess.check_output([herwig7_binary,'--version']).splitlines()
17  return(' '.join([x.decode('UTF8') for x in versions[0].split()[1:]]))
18 
19 # Helper function to remove the command prefixes from the line
20 def clean_string(list,string,replace="",strip=False):
21  for command in range(len(list)):
22  list[command] = list[command].replace(string,replace)
23  if strip:
24  list[command] = list[command].strip()
25  # return the cleaned list
26  return list
27 
28 # Helper functions to print the commands
29 def print_commands(list):
30  for command in list:
31  athMsgLog.debug(command)
32 
33 # Helper function to split command lines into command and value
34 def split_commands(list):
35  for command in range(len(list)):
36  # Search for whitespaces, since the part before the whitespace gives the parameter which is set
37  # the part after the whitespace gives the value which is set
38  whitespace_idx = list[command].index(" ")
39  # Now split the commands into the command and value set
40  list[command] = [list[command][0:whitespace_idx],list[command][whitespace_idx+1:]]
41  # return the new list
42  return list
43 
44 # Helper function to check for duplicate commands
45 def check_for_overwrites(list,file):
46  found_duplicate = False
47  existing_commands = {}
48  for command in list:
49  temp_com = command[0]
50  temp_val = command[1]
51  # Check if the same command is already present with another value
52  if temp_com in existing_commands and existing_commands[temp_com] != temp_val:
53  found_duplicate = True
54  str1 = "\nFound option that is used twice"
55  str2 = "The option %s is first set to %s" % (temp_com,existing_commands[temp_com])
56  str3 = "And then the option %s ist set to %s" % (command[0],command[1])
57  athMsgLog.info(str1+"\n"+str2+"\n"+str3)
58  file.write(str1+"\n"+str2+"\n"+str3)
59  else:
60  existing_commands[temp_com] = temp_val
61  # return the status
62  return found_duplicate
63 
64 # Helper function to write commands to file
65 def write_to_file(list,file):
66  for command in list:
67  file.write(command[0]+" "+command[1]+"\n")
68 
69 # Helper function to sort the commands into the lists
70 def sort_commands(line,cd_in_line,cd_command,set_commands,read_commands,create_commands,insert_commands):
71  # If the snippets cd's into a dir, we need to append the path to the other commands
72  # To be able to compare to the settings from the master .in file
73  if "cd" in line:
74  cd_command = line.replace("cd ","")
75  cd_command = cd_command.strip()
76  cd_in_line = True
77  # Get all the "set" commands and ignore lines that are commented out
78  elif "set" in line:
79  if cd_in_line and not line.startswith("/Herwig/"):
80  set_commands.append(cd_command+"/"+line)
81  else:
82  set_commands.append(line)
83  # Get all the "create" commands where an object is created
84  elif "create" in line:
85  if cd_in_line and not line.startswith("/Herwig/"):
86  create_commands.append(cd_command+"/"+line)
87  else:
88  create_commands.append(line)
89  # Get all the "insert" commands where an object is inserted
90  elif "insert" in line:
91  if cd_in_line and not line.startswith("/Herwig/"):
92  insert_commands.append(cd_command+"/"+line)
93  else:
94  insert_commands.append(line)
95  # Get all the "read" commands where a config snippet is read in
96  elif "read" in line:
97  read_commands.append(line)
98 
99  # return the cd status
100  return cd_in_line,cd_command,set_commands,read_commands,create_commands,insert_commands
101 
102 # Main function to check the Herwig config file
104  # Hello from the config checker
105  athMsgLog.info("Hello from the config-checker!")
106  # Check the Herwig version
107  h_version = herwig_version()
108  version = h_version[0]
109  subversion = h_version[2]
110  subsubversion = h_version[4]
111  athMsgLog.info("The current Herwig version is "+version+"."+subversion+"."+subsubversion)
112 
113  # Get the name of ther Herwig7 in-file
114  files = [f for f in os.listdir('.') if os.path.isfile(f)]
115  HerwigINFile = []
116  for file in files:
117  if ".in" in file:
118  HerwigINFile.append(file)
119 
120  # Check if there is only one files, as it should be
121  run_name = HerwigINFile[0]
122  athMsgLog.info("The Herwig7 *.in file is "+run_name)
123 
124  # Now get the settings from the .in file
125  set_commands = [] # all commands where a setting is set
126  read_commands = [] # all commands where a file is read in
127  create_commands = [] # all commands where an object is created
128  insert_commands = [] # all commands where an object is inserted
129 
130  f = open(run_name, "r")
131  cd_in_line = False
132  cd_command = ""
133  for line in f:
134  if not line.startswith("#"):
135  cd,cd_cmd,set_commands,read_commands,create_commands,insert_commands = sort_commands(line,
136  cd_in_line,cd_command,set_commands,
137  read_commands,create_commands,insert_commands)
138  cd_in_line,cd_command = cd,cd_cmd
139  else:
140  continue
141 
142  # remove the "set", "create" and "read" parts as well as the snippet prefix
143  set_commands = clean_string(set_commands,"set ","")
144  create_commands = clean_string(create_commands,"create ","")
145  read_commands = clean_string(read_commands,"read ","")
146  read_commands = clean_string(read_commands,"snippets/","")
147 
148  # Now recursiveley read in the config snippets from the read commands
149  include_path = os.environ['HERWIG7_PATH']+"/share/Herwig/"
150  snippet_path = os.environ['HERWIG7_PATH']+"/share/Herwig/snippets/"
151 
152  include_files = [f for f in os.listdir(include_path)]
153  snippet_files = [f for f in os.listdir(snippet_path)]
154 
155  # Files that we need to read in, since they are read in in the original config
156  read_files = []
157  for file in include_files:
158  for command in read_commands:
159  if file in command:
160  read_files.append(include_path+file)
161  for file in snippet_files:
162  for command in read_commands:
163  if file in command:
164  read_files.append(snippet_path+file)
165 
166  # Now loop over the snippets
167  for file in read_files:
168  if ".in" not in file:
169  athMsgLog.info("Skipping file " + file + " since it does not contain any in-file")
170  athMsgLog.info("It is just a directory, can be ignored.")
171  continue
172  else:
173  f = open(file, "r")
174  cd_in_line = False
175  cd_command = ""
176  for line in f:
177  if not line.startswith("#"):
178  cd,cd_cmd,set_commands,read_commands,create_commands,insert_commands = sort_commands(line,cd_in_line,cd_command,set_commands,read_commands,create_commands,insert_commands)
179  cd_in_line,cd_command = cd,cd_cmd
180  else:
181  continue
182  f.close()
183 
184  # remove the "set", "create" and "read" parts as well as the snippet prefix
185  set_commands = clean_string(set_commands,"set ","")
186  create_commands = clean_string(create_commands,"create ","")
187  read_commands = clean_string(read_commands,"read ","")
188  read_commands = clean_string(read_commands,"snippets/","")
189 
190  # Remove "//" and remove line breaks
191  clean_string(set_commands,"//","/",True)
192  clean_string(create_commands,"//","/",True)
193  clean_string(insert_commands,"//","/",True)
194 
195  # Print the commands
196  athMsgLog.debug("\n These are the commands found by the Herwig7JOChecker:\n")
197  print_commands(set_commands)
198  print_commands(create_commands)
199  print_commands(insert_commands)
200  athMsgLog.debug("\n")
201 
202  # Now check if there are commands executed twice
203  # It can happen that there are commands set by the user but some config snippet from Herwig sets these commands again
204  # In this case a warning needs to be displayed, this should be checked by the user
205  set_commands = split_commands(set_commands)
206  create_commands = split_commands(create_commands)
207  insert_commands = split_commands(insert_commands)
208 
209  # Now we need to check of commands are executed twice
210  with open("HerwigCommandDuplicates.txt","w") as file:
211  found_duplicate1 = check_for_overwrites(set_commands,file)
212  found_duplicate2 = check_for_overwrites(create_commands,file)
213  found_duplicate3 = check_for_overwrites(insert_commands,file)
214 
215  # Now save all the commands to an file
216  # This file will be used by JEM/PAVER for the technical validation of generator changes
217  # The files from refrence sample will be checked against the new one to spot config changes
218  with open("HerwigCommands.txt","w") as file:
219  write_to_file(set_commands,file)
220  write_to_file(create_commands,file)
221  write_to_file(insert_commands,file)
222 
223  # If there was an error, raise an exception
224  if found_duplicate1 or found_duplicate2 or found_duplicate3:
225  athMsgLog.warn("There were some settings which are overwritten, please check the log-file HerwigCommandDuplicates.txt")
226 
227  # Godbye from the config checker
228  athMsgLog.info("Commands have been written to HerwigCommands.txt")
229  athMsgLog.info("Duplicates have been written to HerwigCommandsDuplicates.txt")
230  athMsgLog.info("Godybe from the config-checker!")
231 
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
index
Definition: index.py:1
Herwig7JOChecker.check_file
def check_file()
Definition: Herwig7JOChecker.py:103
Herwig7JOChecker.check_for_overwrites
def check_for_overwrites(list, file)
Definition: Herwig7JOChecker.py:45
Herwig7JOChecker.print_commands
def print_commands(list)
Definition: Herwig7JOChecker.py:29
Herwig7JOChecker.sort_commands
def sort_commands(line, cd_in_line, cd_command, set_commands, read_commands, create_commands, insert_commands)
Definition: Herwig7JOChecker.py:70
Herwig7JOChecker.clean_string
def clean_string(list, string, replace="", strip=False)
Definition: Herwig7JOChecker.py:20
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:194
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
Herwig7JOChecker.herwig_version
def herwig_version()
Definition: Herwig7JOChecker.py:13
Trk::open
@ open
Definition: BinningType.h:40
Herwig7JOChecker.split_commands
def split_commands(list)
Definition: Herwig7JOChecker.py:34
Herwig7JOChecker.write_to_file
def write_to_file(list, file)
Definition: Herwig7JOChecker.py:65
Trk::split
@ split
Definition: LayerMaterialProperties.h:38