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

Functions

 settingIsTrue (setting)
 get_mg5_version ()
 is_version_or_newer (args)
 isNLO_from_run_card (run_card)
 error_check (errors_a, return_code)
 write_test_script ()
 modify_param_card (param_card_input=None, param_card_backup=None, process_dir=MADGRAPH_GRIDPACK_LOCATION, params={}, output_location=None)
 find_key_and_update (akey, dictionary)

Variables

 mglog = Logging.logging.getLogger('MadGraphUtils')
str MADGRAPH_GRIDPACK_LOCATION = 'madevent'
bool MADGRAPH_CATCH_ERRORS = True
list MADGRAPH_COMMAND_STACK = []

Function Documentation

◆ error_check()

python.MadGraphUtilsHelpers.error_check ( errors_a,
return_code )

Definition at line 72 of file MadGraphUtilsHelpers.py.

72def error_check(errors_a, return_code):
73 if not MADGRAPH_CATCH_ERRORS:
74 return
75 if errors_a is None:
76 # stderr is not always captured (e.g. catch_errors=False).
77 # Still fail on non-zero return code.
78 if return_code != 0:
79 mglog.error(f'Detected a bad return code: {return_code}')
80 write_test_script()
81 raise RuntimeError('Error detected in MadGraphControl process')
82 return
83 unmasked_error = False
84 my_debug_file = None
85 bad_variables = []
86 # Make sure we are getting a string and not a byte string (python3 ftw)
87 errors = errors_a
88 if type(errors)==bytes:
89 errors = errors.decode('utf-8')
90 if len(errors):
91 mglog.info('Some errors detected by MadGraphControl - checking for serious errors')
92 for err in errors.split('\n'):
93 if len(err.strip())==0:
94 continue
95 # Errors to do with I/O... not clear on their origin yet
96 if 'Inappropriate ioctl for device' in err:
97 mglog.info(err)
98 continue
99 if 'stty: standard input: Invalid argument' in err:
100 mglog.info(err)
101 continue
102 # Errors for PDF sets that should be fixed in MG5_aMC 2.7
103 if 'PDF already installed' in err:
104 mglog.info(err)
105 continue
106 if 'Read-only file system' in err:
107 mglog.info(err)
108 continue
109 if 'HTML' in err:
110 # https://bugs.launchpad.net/mg5amcnlo/+bug/1870217
111 mglog.info(err)
112 continue
113 if 'impossible to set default multiparticles' in err:
114 # https://answers.launchpad.net/mg5amcnlo/+question/690004
115 mglog.info(err)
116 continue
117 if 'More information is found in' in err:
118 my_debug_file = err.split("'")[1]
119 if err.startswith('tar'):
120 mglog.info(err)
121 continue
122 if 'python2 support will be removed' in err:
123 mglog.info(err)
124 continue
125 if 'python3.12 support is still experimental' in err:
126 mglog.info(err)
127 continue
128 # Another new python 3.12 message in MG5_aMC 3.6
129 if 'python3.12+ support: For reweighting feature, please use 3.6.X release.' in err:
130 mglog.info(err)
131 continue
132 # silly ghostscript issue in 21.6.46 nightly
133 if 'required by /lib64/libfontconfig.so' in err or\
134 'required by /lib64/libgs.so' in err:
135 mglog.info(err)
136 continue
137 if 'Error: Symbol' in err and 'has no IMPLICIT type' in err:
138 bad_variables += [ err.split('Symbol ')[1].split(' at ')[0] ]
139 # error output from tqdm (progress bar)
140 if 'it/s' in err:
141 mglog.info(err)
142 continue
143 mglog.error(err)
144 unmasked_error = True
145 # This is a bit clunky, but needed because we could be several places when we get here
146 if my_debug_file is None:
147 debug_files = glob.glob('*debug.log')+glob.glob('*/*debug.log')
148 for debug_file in debug_files:
149 # This protects against somebody piping their output to my_debug.log and it being caught here
150 has_subproc = os.access(os.path.join(os.path.dirname(debug_file),'SubProcesses'),os.R_OK)
151 if has_subproc:
152 my_debug_file = debug_file
153 break
154
155 if my_debug_file is not None:
156 if not unmasked_error:
157 mglog.warning('Found a debug file at '+my_debug_file+' but no apparent error. Will terminate.')
158 mglog.error('MadGraph5_aMC@NLO appears to have crashed. Debug file output follows.')
159 with open(my_debug_file,'r') as error_output:
160 for l in error_output:
161 mglog.error(l.replace('\n',''))
162 mglog.error('End of debug file output')
163
164 if bad_variables:
165 mglog.warning('Appeared to detect variables in your run card that MadGraph did not understand:')
166 mglog.warning(' Check your run card / JO settings for %s',bad_variables)
167
168 # Check the return code
169 if return_code!=0:
170 mglog.error(f'Detected a bad return code: {return_code}')
171 unmasked_error = True
172
173 # Now raise an error if we were in either of the error states
174 if unmasked_error or my_debug_file is not None:
175 write_test_script()
176 raise RuntimeError('Error detected in MadGraphControl process')
177 return
178
179
180# Write a short test script for standalone debugging
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179

◆ find_key_and_update()

python.MadGraphUtilsHelpers.find_key_and_update ( akey,
dictionary )
 Helper function when looking at param cards
In some cases it's tricky to match keys - they may differ
only in white space. This tries to sort out when we have
a match, and then uses the one in blockParams afterwards.
In the case of no match, it returns the original key.

Definition at line 344 of file MadGraphUtilsHelpers.py.

344def find_key_and_update(akey,dictionary):
345 """ Helper function when looking at param cards
346 In some cases it's tricky to match keys - they may differ
347 only in white space. This tries to sort out when we have
348 a match, and then uses the one in blockParams afterwards.
349 In the case of no match, it returns the original key.
350 """
351 test_key = ' '.join(akey.strip().replace('\t',' ').split())
352 for key in dictionary:
353 mod_key = ' '.join(key.strip().replace('\t',' ').split())
354 if mod_key==test_key:
355 return key
356 return akey
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:312

◆ get_mg5_version()

python.MadGraphUtilsHelpers.get_mg5_version ( )
Return MadGraph version string (e.g. '3.5.1')

Used to include MG version in gridpack names for better traceability.
Reads version from $MADPATH/VERSION file.

Definition at line 21 of file MadGraphUtilsHelpers.py.

21def get_mg5_version():
22 """Return MadGraph version string (e.g. '3.5.1')
23
24 Used to include MG version in gridpack names for better traceability.
25 Reads version from $MADPATH/VERSION file.
26 """
27 with open(os.environ['MADPATH']+'/VERSION','r') as version_file:
28 for line in version_file:
29 if 'version' in line:
30 return line.split('=')[1].strip()
31 raise RuntimeError('Failed to find MadGraph/MadGraph5_aMC@NLO version')
32

◆ is_version_or_newer()

python.MadGraphUtilsHelpers.is_version_or_newer ( args)

Definition at line 33 of file MadGraphUtilsHelpers.py.

33def is_version_or_newer(args):
34 # also need to find out the version (copied from generate)
35 import os
36 version=None
37 version_file = open(os.environ['MADPATH']+'/VERSION','r')
38
39 for line in version_file:
40 if 'version' in line:
41 version=line.split('=')[1].strip()
42 version_file.close()
43
44 if not version:
45 raise RuntimeError('Failed to find MadGraph/MadGraph5_aMC@NLO version in '+version_file)
46
47 vs=[int(v) for v in version.split('.')]
48
49 # this is lazy, let's hope there wont be a subversion > 100...
50 y=int(100**max(len(vs),len(args)))
51 testnumber=0
52 for x in args:
53 testnumber+=x*y
54 y/=100
55
56 y=int(100**max(len(vs),len(args)))
57 versionnumber=0
58 for x in vs:
59 versionnumber+=x*y
60 y/=100
61 return versionnumber>=testnumber
62
#define max(a, b)
Definition cfImp.cxx:41

◆ isNLO_from_run_card()

python.MadGraphUtilsHelpers.isNLO_from_run_card ( run_card)

Definition at line 63 of file MadGraphUtilsHelpers.py.

63def isNLO_from_run_card(run_card):
64 f = open(run_card,'r')
65 if "parton_shower" in f.read().lower():
66 f.close()
67 return True
68 else:
69 f.close()
70 return False
71

◆ modify_param_card()

python.MadGraphUtilsHelpers.modify_param_card ( param_card_input = None,
param_card_backup = None,
process_dir = MADGRAPH_GRIDPACK_LOCATION,
params = {},
output_location = None )
Build a new param_card.dat from an existing one.
Params should be a dictionary of dictionaries. The first key is the block name, and the second in the param name.
Keys can include MASS (for masses) and DECAY X (for decays of particle X)

Definition at line 197 of file MadGraphUtilsHelpers.py.

197def modify_param_card(param_card_input=None,param_card_backup=None,process_dir=MADGRAPH_GRIDPACK_LOCATION,params={},output_location=None):
198 """Build a new param_card.dat from an existing one.
199 Params should be a dictionary of dictionaries. The first key is the block name, and the second in the param name.
200 Keys can include MASS (for masses) and DECAY X (for decays of particle X)"""
201 # Grab the old param card and move it into place
202
203 # Check for the default run card location
204 if param_card_input is None:
205 param_card_input=process_dir+'/Cards/param_card.dat'
206 elif param_card_input is not None and not os.access(param_card_input,os.R_OK):
207 paramcard = subprocess.Popen(['get_files','-data',param_card_input])
208 paramcard.wait()
209 if not os.access(param_card_input,os.R_OK):
210 raise RuntimeError('Could not get param card '+param_card_input)
211 mglog.info('Using input param card at '+param_card_input)
212
213 #ensure all blocknames and paramnames are upper case
214 paramsUpper = {}
215 for blockName in list(params.keys()):
216 paramsUpper[blockName.upper()] = {}
217 for paramName in list(params[blockName].keys()):
218 paramsUpper[blockName.upper()][paramName.upper()] = params[blockName][paramName]
219
220 if param_card_backup is not None:
221 mglog.info('Keeping backup of original param card at '+param_card_backup)
222 param_card_old = param_card_backup
223 else:
224 param_card_old = param_card_input+'.old_to_be_deleted'
225 if os.path.isfile(param_card_old):
226 os.unlink(param_card_old) # delete old backup
227 os.rename(param_card_input, param_card_old) # change name of original card
228
229 oldcard = open(param_card_old,'r')
230 param_card_location= process_dir+'/Cards/param_card.dat' if output_location is None else output_location
231 newcard = open(param_card_location,'w')
232 decayEdit = False #only becomes true in a DECAY block when specifying the BR
233 blockName = ""
234 doneParams = {} #tracks which params have been done
235 for linewithcomment in oldcard:
236 line=linewithcomment.split('#')[0]
237 if line.strip().upper().startswith('BLOCK') or line.strip().upper().startswith('DECAY')\
238 and len(line.strip().split()) > 1:
239 if decayEdit and blockName == 'DECAY':
240 decayEdit = False # Start a new DECAY block
241 pos = 0 if line.strip().startswith('DECAY') else 1
242 if blockName=='MASS' and 'MASS' in paramsUpper:
243 # Any residual masses to set?
244 if "MASS" in doneParams:
245 leftOvers = [ x for x in paramsUpper['MASS'] if x not in doneParams['MASS'] ]
246 else:
247 leftOvers = [ x for x in paramsUpper['MASS'] ]
248
249 for pdg_id in leftOvers:
250 mglog.warning('Adding mass line for '+str(pdg_id)+' = '+str(paramsUpper['MASS'][pdg_id])+' which was not in original param card')
251 newcard.write(' '+str(pdg_id)+' '+str(paramsUpper['MASS'][pdg_id])+'\n')
252 doneParams['MASS'][pdg_id]=True
253 if blockName=='DECAY' and 'DECAY' not in line.strip().upper() and 'DECAY' in paramsUpper:
254 # Any residual decays to include?
255 leftOvers = [ x for x in paramsUpper['DECAY'] if x not in doneParams['DECAY'] ]
256 for pdg_id in leftOvers:
257 mglog.warning('Adding decay for pdg id '+str(pdg_id)+' which was not in the original param card')
258 newcard.write( paramsUpper['DECAY'][pdg_id].strip()+'\n' )
259 doneParams['DECAY'][pdg_id]=True
260 blockName = line.strip().upper().split()[pos]
261 if decayEdit:
262 continue #skipping these lines because we are in an edit of the DECAY BR
263
264 akey = None
265 if blockName != 'DECAY' and len(line.strip().split()) > 0:
266 # The line is already without the comment.
267 # In the case of mixing matrices this is a bit tricky
268 if len(line.split())==2:
269 akey = line.upper().strip().split()[0]
270 else:
271 # Take everything but the last word
272 akey = line.upper().strip()[:line.strip().rfind(' ')].strip()
273 elif blockName == 'DECAY' and len(line.strip().split()) > 1:
274 akey = line.strip().split()[1]
275 if akey is None:
276 newcard.write(linewithcomment)
277 continue
278
279 #check if we have params for this block
280 if blockName not in paramsUpper:
281 newcard.write(linewithcomment)
282 continue
283 blockParams = paramsUpper[blockName]
284 # Check the spacing in the key
285 akey = find_key_and_update(akey,blockParams)
286
287 # look for a string key, which would follow a #
288 stringkey = None
289 if '#' in linewithcomment: #ignores comment lines
290 stringkey = linewithcomment[linewithcomment.find('#')+1:].strip()
291 if len(stringkey.split()) > 0:
292 stringkey = stringkey.split()[0].upper()
293
294 if akey not in blockParams and not (stringkey is not None and stringkey in blockParams):
295 newcard.write(linewithcomment)
296 continue
297
298 if akey in blockParams and (stringkey is not None and stringkey in blockParams):
299 raise RuntimeError('Conflicting use of numeric and string keys '+akey+' and '+stringkey)
300
301 theParam = blockParams.get(akey,blockParams[stringkey] if stringkey in blockParams else None)
302 if blockName not in doneParams:
303 doneParams[blockName] = {}
304 if akey in blockParams:
305 doneParams[blockName][akey]=True
306 elif stringkey is not None and stringkey in blockParams:
307 doneParams[blockName][stringkey]=True
308
309 #do special case of DECAY block
310 if blockName=="DECAY":
311 if theParam.splitlines()[0].split()[0].upper()=="DECAY":
312 #specifying the full decay block
313 for newline in theParam.splitlines():
314 newcard.write(newline+'\n')
315 mglog.info(newline)
316 decayEdit = True
317 else: #just updating the total width
318 newcard.write('DECAY '+akey+' '+str(theParam)+' # '+(linewithcomment[linewithcomment.find('#')+1:].strip() if linewithcomment.find('#')>0 else "")+'\n')
319 mglog.info('DECAY '+akey+' '+str(theParam)+' # '+(linewithcomment[linewithcomment.find('#')+1:].strip() if linewithcomment.find('#')>0 else "")+'\n')
320 # second special case of QNUMBERS
321 elif blockName=='QNUMBERS':
322 #specifying the full QNUMBERS block
323 for newline in theParam.splitlines():
324 newcard.write(newline+'\n')
325 mglog.info(newline)
326 decayEdit = True
327 else: #just updating the parameter
328 newcard.write(' '+akey+' '+str(theParam)+' # '+(linewithcomment[linewithcomment.find('#')+1:].strip() if linewithcomment.find('#')>0 else "")+'\n')
329 mglog.info(' '+akey+' '+str(theParam)+' # '+(linewithcomment[linewithcomment.find('#')+1:].strip() if linewithcomment.find('#')>0 else "")+'\n')
330 # Done editing the line!
331
332 #check that all specified parameters have been updated (helps to catch typos)
333 for blockName in paramsUpper:
334 if blockName not in doneParams and len(paramsUpper[blockName].keys())>0:
335 raise RuntimeError('Did not find any of the parameters for block '+blockName+' in param_card')
336 for paramName in paramsUpper[blockName]:
337 if paramName not in doneParams[blockName]:
338 raise RuntimeError('Was not able to replace parameter '+paramName+' in param_card')
339
340 # Close up and return
341 oldcard.close()
342 newcard.close()
343
int upper(int c)

◆ settingIsTrue()

python.MadGraphUtilsHelpers.settingIsTrue ( setting)

Definition at line 16 of file MadGraphUtilsHelpers.py.

16def settingIsTrue(setting):
17 if setting.replace("'",'').replace('"','').replace('.','').lower() in ['t','true']:
18 return True
19 return False
20

◆ write_test_script()

python.MadGraphUtilsHelpers.write_test_script ( )

Definition at line 181 of file MadGraphUtilsHelpers.py.

181def write_test_script():
182 mglog.info('Will write a stand-alone debugging script.')
183 mglog.info('This is an attempt to provide you commands that you can use')
184 mglog.info('to reproduce the error locally. If you make additional')
185 mglog.info('modifications by hand (not using MadGraphControl) in your JO,')
186 mglog.info('make sure that you check and modify the script as needed.\n\n')
187 mglog.info('# Script start; trim off columns left of the "#"')
188 # Write offline stand-alone reproduction script
189 with open('standalone_script.sh','w') as standalone_script:
190 for command in MADGRAPH_COMMAND_STACK:
191 for line in command.split('\n'):
192 mglog.info(line)
193 standalone_script.write(line+'\n')
194 mglog.info('# Script end')
195 mglog.info('Script also written to %s/standalone_script.sh',os.getcwd())
196

Variable Documentation

◆ MADGRAPH_CATCH_ERRORS

bool python.MadGraphUtilsHelpers.MADGRAPH_CATCH_ERRORS = True

Definition at line 11 of file MadGraphUtilsHelpers.py.

◆ MADGRAPH_COMMAND_STACK

list python.MadGraphUtilsHelpers.MADGRAPH_COMMAND_STACK = []

Definition at line 12 of file MadGraphUtilsHelpers.py.

◆ MADGRAPH_GRIDPACK_LOCATION

str python.MadGraphUtilsHelpers.MADGRAPH_GRIDPACK_LOCATION = 'madevent'

Definition at line 9 of file MadGraphUtilsHelpers.py.

◆ mglog

python.MadGraphUtilsHelpers.mglog = Logging.logging.getLogger('MadGraphUtils')

Definition at line 6 of file MadGraphUtilsHelpers.py.