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
202
203
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
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)
227 os.rename(param_card_input, param_card_old)
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
233 blockName = ""
234 doneParams = {}
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
241 pos = 0 if line.strip().startswith('DECAY') else 1
242 if blockName=='MASS' and 'MASS' in paramsUpper:
243
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
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
261 if decayEdit:
262 continue
263
264 akey = None
265 if blockName !=
'DECAY' and len(line.strip().
split()) > 0:
266
267
268 if len(line.split())==2:
270 else:
271
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
280 if blockName not in paramsUpper:
281 newcard.write(linewithcomment)
282 continue
283 blockParams = paramsUpper[blockName]
284
285 akey = find_key_and_update(akey,blockParams)
286
287
288 stringkey = None
289 if '#' in linewithcomment:
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
310 if blockName=="DECAY":
311 if theParam.splitlines()[0].
split()[0].
upper()==
"DECAY":
312
313 for newline in theParam.splitlines():
314 newcard.write(newline+'\n')
315 mglog.info(newline)
316 decayEdit = True
317 else:
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
321 elif blockName=='QNUMBERS':
322
323 for newline in theParam.splitlines():
324 newcard.write(newline+'\n')
325 mglog.info(newline)
326 decayEdit = True
327 else:
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
331
332
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
341 oldcard.close()
342 newcard.close()
343